Move debugging to compiler flag

This commit is contained in:
FyloZ 2024-07-25 21:22:00 -04:00
parent 662d7efa59
commit 54825ecb5a
Signed by: william
GPG Key ID: 835378AE9AF4AE97
19 changed files with 59 additions and 417 deletions

View File

@ -3,6 +3,10 @@ set(CMAKE_C_COMPILER gcc)
cmake_minimum_required(VERSION 3.10)
project(nes_emulator LANGUAGES C VERSION 0.1 )
if (NES_DEBUG)
add_definitions(-DDEBUG=1)
endif(NES_DEBUG)
add_subdirectory(libs/log.c)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include_directories(${PROJECT_SOURCE_DIR}/libs/log.c/src ${COMMON_INCLUDES})
@ -11,7 +15,6 @@ add_subdirectory(cpu)
add_subdirectory(ppu)
add_subdirectory(mappers)
add_subdirectory(rom)
#add_subdirectory(debugger)
add_subdirectory(utils)
add_subdirectory(gui)

View File

@ -1,5 +1,10 @@
set(HEADERS canvas.h gui.h window.h main_window.h char_map.h pattern_display.h pattern_window.h nametable_window.h dbg_pattern_table.h dbg_nametable.h)
set(SOURCE canvas.c gui.c window.c main_window.c char_map.c pattern_display.c pattern_window.c nametable_window.c dbg_pattern_table.c dbg_nametable.c)
set(HEADERS gui.h window.h main_window.h)
set(SOURCE gui.c window.c main_window.c)
if (NES_DEBUG)
list(APPEND HEADERS char_map.h pattern_window.h nametable_window.h dbg_pattern_table.h dbg_nametable.h)
list(APPEND SOURCE char_map.c pattern_window.c nametable_window.c dbg_pattern_table.c dbg_nametable.c)
endif (NES_DEBUG)
add_library(nes_gui ${SOURCE} ${HEADERS})

View File

@ -1,50 +0,0 @@
//
// Created by william on 16/05/24.
//
#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 index) {
assert(index >= 0);
assert(index < canvas->width * canvas->height);
canvas->pixels[index] = pixel;
}
void canvas_draw_pos(Canvas *canvas, Pixel pixel, int x, int y) {
assert(x >= 0);
assert(x < canvas->width);
assert(y >= 0);
assert(y < canvas->height);
int index = x + y * canvas->width;
canvas_draw(canvas, pixel, index);
}
void canvas_reset(Canvas *canvas) {
memset(canvas->pixels, 0, sizeof(Pixel) * (canvas->width * canvas->height));
}

View File

@ -1,29 +0,0 @@
//
// Created by william on 16/05/24.
//
#ifndef NES_EMULATOR_CANVAS_H
#define NES_EMULATOR_CANVAS_H
#include "../include/types.h"
typedef struct pixel {
byte r;
byte g;
byte b;
} Pixel;
typedef struct canvas {
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 index);
void canvas_draw_pos(Canvas *canvas, Pixel pixel, int x, int y);
void canvas_reset(Canvas *canvas);
#endif //NES_EMULATOR_CANVAS_H

View File

@ -11,6 +11,7 @@
#include "nametable_window.h"
#include "dbg_pattern_table.h"
#include "dbg_nametable.h"
#include "char_map.h"
typedef struct nes_gui {
NesMainWindow main_window;
@ -19,11 +20,12 @@ typedef struct nes_gui {
TTF_Font *font;
// Debug info
bool debug_enabled;
Uint32 last_frame_tick;
Uint32 frame_delay;
#if DEBUG
unsigned long tick;
#endif
} NesGui;
NesGui gui;
@ -35,15 +37,15 @@ bool gui_init() {
return false;
}
gui.debug_enabled = true;
main_window_init(&gui.main_window);
#if DEBUG
gui.tick = 0;
pattern_window_init(&gui.pattern_window);
nametable_window_init(&gui.nametable_window);
main_window_init(&gui.main_window, gui.font);
if (gui.debug_enabled) {
pattern_window_init(&gui.pattern_window);
nametable_window_init(&gui.nametable_window);
}
char_map_init(gui.main_window.sdl_context.renderer, gui.font);
#endif
return true;
}
@ -51,22 +53,24 @@ bool gui_init() {
void gui_uninit() {
main_window_uninit(&gui.main_window);
if (gui.debug_enabled) {
pattern_window_uninit(&gui.pattern_window);
nametable_window_uninit(&gui.nametable_window);
}
#if DEBUG
char_map_uninit();
pattern_window_uninit(&gui.pattern_window);
nametable_window_uninit(&gui.nametable_window);
#endif
TTF_CloseFont(gui.font);
}
void gui_post_sysinit() {
if (gui.debug_enabled) {
dbg_pattern_table_init();
dbg_nametable_init();
#if DEBUG
dbg_pattern_table_init();
dbg_nametable_init();
pattern_window_build_table(&gui.pattern_window);
nametable_window_update(&gui.nametable_window);
}
pattern_window_build_table(&gui.pattern_window);
nametable_window_update(&gui.nametable_window);
#endif
}
int gui_input() {
@ -84,25 +88,23 @@ int gui_input() {
void gui_render() {
main_window_render(&gui.main_window, ppu_get_state()->pixels);
if (gui.debug_enabled) {
pattern_window_render(&gui.pattern_window);
#if DEBUG
pattern_window_render(&gui.pattern_window);
// if (gui.tick % 60 == 0) {
nametable_window_update(&gui.nametable_window);
// }
nametable_window_render(&gui.nametable_window);
}
nametable_window_update(&gui.nametable_window);
nametable_window_render(&gui.nametable_window);
gui.tick++;
#endif
}
void gui_present() {
main_window_present(&gui.main_window);
if (gui.debug_enabled) {
pattern_window_present(&gui.pattern_window);
nametable_window_present(&gui.nametable_window);
}
#if DEBUG
pattern_window_present(&gui.pattern_window);
nametable_window_present(&gui.nametable_window);
#endif
}
void gui_delay() {
@ -118,10 +120,6 @@ void gui_delay() {
gui.last_frame_tick = SDL_GetTicks();
}
bool gui_debug_enabled() {
return gui.debug_enabled;
}
unsigned int gui_get_frame_delay() {
return gui.frame_delay;
}

View File

@ -6,7 +6,6 @@
#define NES_EMULATOR_GUI_H
#include <stdbool.h>
#include "canvas.h"
bool gui_init();
void gui_uninit();
@ -18,7 +17,6 @@ void gui_render();
void gui_present();
void gui_delay();
bool gui_debug_enabled();
unsigned int gui_get_frame_delay();
#endif //NES_EMULATOR_GUI_H

View File

@ -8,20 +8,18 @@
#include "char_map.h"
#include "gui.h"
void main_window_init(NesMainWindow *window, TTF_Font *font) {
void main_window_init(NesMainWindow *window) {
window->sdl_context = window_init("NES Emulator", MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT, MAIN_WINDOW_SCALE);
window->texture = SDL_CreateTexture(window->sdl_context.renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT);
char_map_init(window->sdl_context.renderer, font);
}
void main_window_uninit(NesMainWindow *window) {
char_map_uninit();
SDL_DestroyTexture(window->texture);
window_uninit(window->sdl_context);
}
#if DEBUG
void main_window_render_delay(SDL_Renderer *renderer) {
Uint32 delay = gui_get_frame_delay();
@ -34,12 +32,12 @@ void main_window_render_delay(SDL_Renderer *renderer) {
char_map_render(renderer, buffer);
}
#endif
void main_window_render(NesMainWindow *window, PPUPixel *pixels) {
SDL_RenderClear(window->sdl_context.renderer);
unsigned int frame_buffer[240 * 256];
for (int i = 0; i < 240 * 256; i++) {
PPUPixel pixel = pixels[i];
@ -53,9 +51,9 @@ void main_window_render(NesMainWindow *window, PPUPixel *pixels) {
SDL_UpdateTexture(window->texture, NULL, &frame_buffer, 240 * sizeof(unsigned int));
SDL_RenderCopy(window->sdl_context.renderer, window->texture, NULL, NULL);
if (gui_debug_enabled()) {
main_window_render_delay(window->sdl_context.renderer);
}
#if DEBUG
main_window_render_delay(window->sdl_context.renderer);
#endif
}
void main_window_present(NesMainWindow *window) {

View File

@ -19,7 +19,7 @@ typedef struct nes_main_window {
SDL_Texture *texture;
} NesMainWindow;
void main_window_init(NesMainWindow *window, TTF_Font *font);
void main_window_init(NesMainWindow *window);
void main_window_uninit(NesMainWindow *window);
void main_window_render(NesMainWindow *window, PPUPixel* pixels);

View File

@ -10,8 +10,7 @@
#define NW_BUFFER_SIZE (NAMETABLE_ROW_WIDTH * NAMETABLE_COL_HEIGHT * PATTERN_DRAW_SIZE * PATTERN_DRAW_SIZE)
void nametable_window_init(NesNametableWindow *window) {
int win_size = pattern_display_get_size(NW_ROW_TILE_COUNT);
window->sdl_context = window_init("Nametable", win_size, win_size, NW_SCALE);
window->sdl_context = window_init("Nametable", NW_WIDTH, NW_HEIGHT, NW_SCALE);
window->texture = SDL_CreateTexture(window->sdl_context.renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, NW_WIDTH, NW_HEIGHT);
@ -22,7 +21,7 @@ void nametable_window_uninit(NesNametableWindow *window) {
window_uninit(window->sdl_context);
}
void nametable_window_update_bank(NesNametableWindow *window, int bank, pixel* buffer) {
void nametable_window_update_bank(NesNametableWindow *window, int bank, pixel *buffer) {
dbg_nametable_render_bank(bank, buffer);
SDL_Rect rect;

View File

@ -7,7 +7,6 @@
#include "window.h"
#include "../include/types.h"
#include "pattern_display.h"
#define NW_SCALE 1
#define NW_ROW_COUNT 60

View File

@ -1,123 +0,0 @@
//
// Created by william on 12/07/24.
//
#include <assert.h>
#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, int display_type) {
assert(tiles_x > 0);
assert(tiles_y > 0);
display->width = tiles_x;
display->height = tiles_y;
display->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, display_type,
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, int tile_count, read_func read_func,
void *read_func_data) {
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, read_func(tile_addr, read_func_data), 8);
memcpy(tile->data_high, read_func(tile_addr + 8, read_func_data), 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, read_func read_func, void *read_func_data) {
int tile_count = display->width * display->height;
PatternTile *tile_table = malloc(tile_count * sizeof(PatternTile));
pattern_display_build_table(tile_table, tile_count, read_func, read_func_data);
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);
}

View File

@ -1,47 +0,0 @@
//
// Created by william on 12/07/24.
//
#ifndef NES_EMULATOR_PATTERN_DISPLAY_H
#define NES_EMULATOR_PATTERN_DISPLAY_H
#include <SDL.h>
#include "../include/types.h"
#define PATTERN_DISPLAY_STATIC SDL_TEXTUREACCESS_STATIC
#define PATTERN_DISPLAY_DYNAMIC SDL_TEXTUREACCESS_STREAMING
#define PATTERN_SIZE 8
#define PATTERN_BORDER_WIDTH 1
#define PATTERN_BORDER_COLOR 0xff2223b2
#define PATTERN_DRAW_SIZE (PATTERN_SIZE + PATTERN_BORDER_WIDTH)
typedef unsigned int pixel;
typedef byte *(*read_func)(address, void *);
typedef struct pattern_tile {
byte data_low[8];
byte data_high[8];
} PatternTile;
typedef struct pattern_display {
SDL_Texture *texture;
PatternTile *tiles;
int width;
int height;
} PatternDisplay;
static inline int pattern_display_get_size(int tile_count) {
return tile_count * PATTERN_DRAW_SIZE + PATTERN_BORDER_WIDTH;
}
void pattern_display_init(PatternDisplay *display, SDL_Renderer *renderer, int tiles_x, int tiles_y, int display_type);
void pattern_display_uninit(PatternDisplay *display);
void pattern_display_build(PatternDisplay *display, read_func read_func, void *read_func_data);
void pattern_display_render(PatternDisplay *display, SDL_Renderer *renderer);
#endif //NES_EMULATOR_PATTERN_DISPLAY_H

View File

@ -10,8 +10,7 @@
#define PW_BUFFER_SIZE (PW_WIDTH * PW_HEIGHT)
void pattern_window_init(NesPatternWindow *window) {
int win_width = pattern_display_get_size(PW_ROW_TILE_COUNT);
window->sdl_context = window_init("Pattern Table", win_width, win_width * 2, PW_SCALE);
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);

View File

@ -7,14 +7,12 @@
#include "../include/types.h"
#include "window.h"
#include "pattern_display.h"
#define PW_SCALE 2
#define PW_ROW_TILE_COUNT 16
typedef struct nes_pattern_window {
NesSdlContext sdl_context;
PatternDisplay pattern_display;
SDL_Texture *texture;
} NesPatternWindow;

View File

@ -1,5 +1,5 @@
set(HEADERS pattern_table.h ppu.h palette.h)
set(SOURCE pattern_table.c ppu.c palette.c)
set(HEADERS ppu.h palette.h)
set(SOURCE ppu.c palette.c)
add_library(nes_ppu ${SOURCE} ${HEADERS})

View File

@ -1,61 +0,0 @@
//
// Created by william on 17/05/24.
//
#include "pattern_table.h"
#include "ppu.h"
#include "../gui/canvas.h"
#include "../gui/gui.h"
inline void test() {
}
void pt_debug() {
// Canvas *canvas = gui_get_canvas(WINDOW_ID_PATTERN);
//
// for (int palette = 0; palette < 2; palette++) {
// address palette_addr = palette * 0x1000;
// int palette_canvas_offset = palette * (PATTERN_TABLE_WIDTH * PATTERN_TILE_SIZE);
//
// for (int y = 0; y < PATTERN_TABLE_WIDTH; y++) {
// for (int x = 0; x < PATTERN_TABLE_WIDTH; x++) {
// address tile_addr = palette_addr + (x + y * PATTERN_TABLE_WIDTH) * PATTERN_TILE_MEM_SIZE;
//
// for (int tile_y = 0; tile_y < PATTERN_TILE_SIZE; tile_y++) {
// byte p1_data = ppu_read(tile_addr + tile_y);
// byte p2_data = ppu_read(tile_addr + tile_y + PATTERN_TILE_SIZE);
//
// for (int tile_x = 0; tile_x < PATTERN_TILE_SIZE; tile_x++) {
// byte bitmask = 1 << (PATTERN_TILE_SIZE - tile_x - 1);
// byte p1_byte = p1_data & bitmask;
// byte p2_byte = p2_data & bitmask;
//
// Pixel pixel;
// if (p1_byte && p2_byte) {
// pixel.r = 255;
// pixel.g = 255;
// pixel.b = 255;
// } else if (p2_byte) {
// pixel.r = 255;
// pixel.g = 0;
// pixel.b = 0;
// } else if (p1_byte) {
// pixel.r = 0;
// pixel.g = 255;
// pixel.b = 255;
// } else {
// pixel.r = 0;
// pixel.g = 0;
// pixel.b = 0;
// }
//
// int canvas_x = x * PATTERN_TILE_SIZE + tile_x;
// int canvas_y = y * PATTERN_TILE_SIZE + tile_y + palette_canvas_offset;
// canvas_draw_pos(canvas, pixel, canvas_x, canvas_y);
// }
// }
// }
// }
// }
}

View File

@ -1,14 +0,0 @@
//
// Created by william on 17/05/24.
//
#ifndef NES_EMULATOR_PATTERN_TABLE_H
#define NES_EMULATOR_PATTERN_TABLE_H
#define PATTERN_TABLE_WIDTH 16
#define PATTERN_TILE_MEM_SIZE 16
#define PATTERN_TILE_SIZE (PATTERN_TILE_MEM_SIZE / 2)
void pt_debug();
#endif //NES_EMULATOR_PATTERN_TABLE_H

View File

@ -19,7 +19,6 @@
#include "../include/ppu.h"
#include "../cpu/cpu.h"
#include "../include/rom.h"
#include "pattern_table.h"
#define PPU_VISIBLE_FRAME_END 240
#define PPU_POST_RENDER_LINE_START PPU_VISIBLE_FRAME_END
@ -76,7 +75,7 @@ static inline unsigned int ppu_pixel_get_index(unsigned int scanline, unsigned i
}
static inline byte ppu_pixel_get_mask(unsigned int tile_fine_x) {
return 1 << (PATTERN_TILE_SIZE - tile_fine_x - 1);
return 1 << (8 - tile_fine_x - 1);
}
static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_high) {
@ -160,31 +159,6 @@ void ppu_fetch_tile() {
ppu_state.ppu_address++;
}
}
// address read_addr;
// switch (fetch_cycle) {
// case 1:
// read_addr = 0x2000 + ((ppu_state.scanline / 8) * 0x20) + (ppu_state.cycle / 8);
// ppu_state.fetch.nametable = ppu_read(read_addr);
// break;
// case 3:
// read_addr = 0x23c0 + (ppu_state.cycle % 8);
// ppu_state.fetch.attribute_table = ppu_read(read_addr);
// break;
// case 5:
// read_addr = 0x1000 * ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_BG_PATTERN_TABLE_ADDR);
// read_addr += ppu_state.fetch.nametable * 16 + ppu_state.scanline % 8;
// ppu_state.fetch.pattern_table_tile_low = ppu_read(read_addr);
// break;
// case 7:
// read_addr = 0x1000 * ppu_read_flag(PPU_REGISTER_CTRL, PPU_CTRL_BG_PATTERN_TABLE_ADDR);
// read_addr += ppu_state.fetch.nametable * 16 + ppu_state.scanline % 8 + 8;
// ppu_state.fetch.pattern_table_tile_high = ppu_read(read_addr);
// ppu_tile_push();
// break;
// default:
// break;
// }
}
void ppu_visible_frame(unsigned int cycle) {
@ -208,7 +182,7 @@ void ppu_visible_frame(unsigned int cycle) {
ppu_state.ppu_address += 0x20;
} else {
ppu_state.ppu_address &= ~0x3e0;
// ppu_state.ppu_address ^= 0x0800;
ppu_state.ppu_address ^= 0x0800;
}
}
}
@ -262,8 +236,8 @@ void ppu_cycle() {
if (rendering_enabled && ppu_state.odd_frame) {
// With rendering enabled, the odd frames are shorter
// TODO: and doing the last cycle of the last dummy nametable fetch there instead
frame_width = PPU_LINE_WIDTH - 2;
frame_height = PPU_LINE_END - 1;
// frame_width = PPU_LINE_WIDTH - 2;
// frame_height = PPU_LINE_END - 1;
}
ppu_state.cycle++;

View File

@ -5,10 +5,7 @@
#include "include/cpu.h"
#include "include/system.h"
#include "memory.h"
#include <unistd.h>
#include <assert.h>
#include "cpu.h"
#include "pattern_table.h"
System current_sys;
@ -33,8 +30,6 @@ void system_next_frame() {
ppu_cycle();
}
}
pt_debug();
}
void system_uninit() {