Add tile debugger to main view

This commit is contained in:
william 2024-08-17 17:38:15 -04:00
parent 77b37fc3b6
commit 1add13dd20
9 changed files with 79 additions and 64 deletions

View File

@ -11,6 +11,7 @@ only tested on Linux. Here is how to run the project:
## Controls ## Controls
- `p`: Pauses the emulation - `p`: Pauses the emulation
- `o`: Go to the next palette in the pattern viewer - `o`: Go to the next palette in the pattern viewer
- `t`: Show tile IDs
## Dependencies ## Dependencies
- GCC compiler - GCC compiler

View File

@ -89,7 +89,12 @@ int gui_input() {
system_toggle_pause(); system_toggle_pause();
} else { } else {
#if DEBUG #if DEBUG
pattern_window_key_up(&gui.pattern_window, event.key.keysym.sym); if (event.key.keysym.sym == SDLK_t) {
PPUDebugFlags *ppu_debug = &ppu_get_state()->debug;
ppu_debug->flags.tile_debugger = !ppu_debug->flags.tile_debugger;
} else {
pattern_window_key_up(&gui.pattern_window, event.key.keysym.sym);
}
#endif #endif
} }
} }

View File

@ -34,20 +34,8 @@ void main_window_render_delay(SDL_Renderer *renderer) {
} }
#endif #endif
void main_window_render(NesMainWindow *window, PPUPixel *pixels) { void main_window_render(NesMainWindow *window, pixel *pixels) {
SDL_RenderClear(window->sdl_context.renderer); SDL_RenderClear(window->sdl_context.renderer);
// unsigned int frame_buffer[240 * 256];
// for (int i = 0; i < 240 * 256; i++) {
// PPUPixel pixel = pixels[i];
//
// unsigned int *data = &frame_buffer[i];
// *data = 0xff000000;
// *data |= pixel.r << 16;
// *data |= pixel.g << 8;
// *data |= pixel.b;
// }
SDL_UpdateTexture(window->texture, NULL, pixels, 240 * sizeof(unsigned int)); SDL_UpdateTexture(window->texture, NULL, pixels, 240 * sizeof(unsigned int));
SDL_RenderCopy(window->sdl_context.renderer, window->texture, NULL, NULL); SDL_RenderCopy(window->sdl_context.renderer, window->texture, NULL, NULL);

View File

@ -11,7 +11,7 @@
#define MAIN_WINDOW_WIDTH 256 #define MAIN_WINDOW_WIDTH 256
#define MAIN_WINDOW_HEIGHT 240 #define MAIN_WINDOW_HEIGHT 240
#define MAIN_WINDOW_SCALE 2 #define MAIN_WINDOW_SCALE 3
typedef struct nes_main_window { typedef struct nes_main_window {
NesSdlContext sdl_context; NesSdlContext sdl_context;
@ -22,7 +22,7 @@ typedef struct nes_main_window {
void main_window_init(NesMainWindow *window); void main_window_init(NesMainWindow *window);
void main_window_uninit(NesMainWindow *window); void main_window_uninit(NesMainWindow *window);
void main_window_render(NesMainWindow *window, PPUPixel* pixels); void main_window_render(NesMainWindow *window, pixel* pixels);
void main_window_present(NesMainWindow *window); void main_window_present(NesMainWindow *window);
#endif //NES_EMULATOR_MAIN_WINDOW_H #endif //NES_EMULATOR_MAIN_WINDOW_H

View File

@ -69,46 +69,42 @@ typedef struct ppu_tile_fetch {
byte pattern_table_tile_high; byte pattern_table_tile_high;
} PPUTileFetch; } PPUTileFetch;
//typedef struct ppu_pixel { #if DEBUG
// byte r; typedef union {
// byte g; struct {
// byte b; byte tile_debugger: 1;
//} PPUPixel; } flags;
typedef unsigned int PPUPixel; byte flags_byte;
} PPUDebugFlags;
typedef struct ppu_tile_queue { #endif
PPUTileFetch first_fetch;
PPUTileFetch second_fetch;
PPUTileFetch displayed_fetch;
} PPUTileQueue;
typedef struct ppu { typedef struct ppu {
PPUMemory memory; PPUMemory memory;
PPUPixel pixels[256 * 240]; pixel pixels[256 * 240];
byte registers[8]; byte registers[8];
byte oam_dma_register; byte oam_dma_register;
byte oam[PPU_OAM_SIZE]; byte oam[PPU_OAM_SIZE];
bool odd_frame; bool odd_frame;
address v;
address t;
byte x;
bool w;
byte x_scroll; byte x_scroll;
byte fine_x_scroll; byte fine_x_scroll;
byte y_scroll; byte y_scroll;
byte ppu_addr_increment; byte x;
bool w;
byte ppu_addr_increment;
address ppu_address; address ppu_address;
address temp_ppu_addr; address temp_ppu_addr;
address bg_pattern_table_addr; address bg_pattern_table_addr;
PPUTileFetch fetch; PPUTileFetch fetch;
PPUTileQueue tile_queue;
unsigned long frame; unsigned long frame;
unsigned int scanline; unsigned int scanline;
unsigned int cycle; unsigned int cycle;
#if DEBUG
PPUDebugFlags debug;
#endif
} PPU; } PPU;
PPU *ppu_get_state(); PPU *ppu_get_state();
@ -137,17 +133,6 @@ void ppu_cycle();
*/ */
bool ppu_read_flag(size_t reg, byte mask); bool ppu_read_flag(size_t reg, byte mask);
/**
* Read a value from the PPU registers. Does not apply any offset to the value, a mask of 0x20 will either result in 0x20 (true) or 0x0 (false).
* Read a value from the PPU registers. Does not apply any offset to the value, a mask of 0x20 will either result in 0x20 (true) or 0x0 (false).
*
* @param reg The register index
* @param mask The value mask
*/
//void ppu_sig_read_register(byte reg);
//
//void ppu_sig_write_register(byte reg);
byte ppu_read_reg(byte reg); byte ppu_read_reg(byte reg);
void ppu_write_reg(byte reg, byte data); void ppu_write_reg(byte reg, byte data);

View File

@ -5,14 +5,9 @@
#ifndef NESEMULATOR_TYPES_H #ifndef NESEMULATOR_TYPES_H
#define NESEMULATOR_TYPES_H #define NESEMULATOR_TYPES_H
//#define RAM_SIZE 0xffff
//#define VRAM_SIZE 0x4000
typedef unsigned char byte; typedef unsigned char byte;
typedef unsigned short address; typedef unsigned short address;
typedef unsigned short word; typedef unsigned short word;
typedef unsigned int pixel;
//typedef byte ram[RAM_SIZE];
//typedef byte vram[VRAM_SIZE];
#endif //NESEMULATOR_TYPES_H #endif //NESEMULATOR_TYPES_H

View File

@ -20,6 +20,7 @@
#include "../cpu/cpu.h" #include "../cpu/cpu.h"
#include "../include/rom.h" #include "../include/rom.h"
#include "colors.h" #include "colors.h"
#include "tile_debugger.h"
#define PPU_VISIBLE_FRAME_END 240 #define PPU_VISIBLE_FRAME_END 240
#define PPU_POST_RENDER_LINE_START PPU_VISIBLE_FRAME_END #define PPU_POST_RENDER_LINE_START PPU_VISIBLE_FRAME_END
@ -31,7 +32,7 @@
#define NAMETABLE_TILE_SIZE 8 #define NAMETABLE_TILE_SIZE 8
PPU ppu_state; PPU ppu_state;
PPUPixel color_list[0x40] = COLOR_LIST; pixel color_list[0x40] = COLOR_LIST;
void ppu_init() { void ppu_init() {
memset(&ppu_state, 0, sizeof(PPU)); memset(&ppu_state, 0, sizeof(PPU));
@ -95,7 +96,7 @@ static inline byte ppu_pixel_get_palette(byte attribute) {
return palette & 0b11; return palette & 0b11;
} }
static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_high, byte attribute) { static inline void ppu_pixel_set_color(pixel *pixel, byte pt_low, byte pt_high, byte attribute) {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
byte pixel_offset = 8 - i - 1; byte pixel_offset = 8 - i - 1;
@ -114,7 +115,7 @@ static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_hig
} }
void ppu_draw_tile() { void ppu_draw_tile() {
PPUTileFetch fetch = ppu_state.tile_queue.displayed_fetch; PPUTileFetch fetch = ppu_state.fetch;
unsigned int y = ppu_state.scanline; unsigned int y = ppu_state.scanline;
unsigned int x = ppu_state.cycle; unsigned int x = ppu_state.cycle;
@ -129,15 +130,20 @@ void ppu_draw_tile() {
// } // }
unsigned int pixel_index = y * PPU_VISIBLE_FRAME_END + x; unsigned int pixel_index = y * PPU_VISIBLE_FRAME_END + x;
PPUPixel *pixel = &ppu_state.pixels[pixel_index]; pixel *pixel = &ppu_state.pixels[pixel_index];
ppu_pixel_set_color(pixel, fetch.pattern_table_tile_low, fetch.pattern_table_tile_high, fetch.attribute_table); ppu_pixel_set_color(pixel, fetch.pattern_table_tile_low, fetch.pattern_table_tile_high, fetch.attribute_table);
} }
byte ppu_get_pattern(byte tile_index, byte high) { byte ppu_get_pattern(byte tile_index, byte high) {
return tile_index; #if DEBUG
// byte tile_row_index = (ppu_state.scanline + ppu_state.y_scroll) % 8; if (ppu_state.debug.flags.tile_debugger) {
// address pattern_addr = ppu_state.bg_pattern_table_addr | tile_index << 4 | high << 3 | tile_row_index; return tile_debugger_encode_number_as_pattern(tile_index, ppu_state.scanline % 8);
// return ppu_read(pattern_addr); }
#endif
byte tile_row_index = (ppu_state.scanline + ppu_state.y_scroll) % 8;
address pattern_addr = ppu_state.bg_pattern_table_addr | tile_index << 4 | high << 3 | tile_row_index;
return ppu_read(pattern_addr);
} }
void ppu_fetch_tile(bool render) { void ppu_fetch_tile(bool render) {
@ -169,7 +175,6 @@ void ppu_fetch_tile(bool render) {
ppu_state.fetch.pattern_table_tile_low = ppu_get_pattern(ppu_state.fetch.nametable, 0); ppu_state.fetch.pattern_table_tile_low = ppu_get_pattern(ppu_state.fetch.nametable, 0);
} else if (fetch_cycle == 7) { } else if (fetch_cycle == 7) {
ppu_state.fetch.pattern_table_tile_high = ppu_get_pattern(ppu_state.fetch.nametable, 1); ppu_state.fetch.pattern_table_tile_high = ppu_get_pattern(ppu_state.fetch.nametable, 1);
ppu_state.tile_queue.displayed_fetch = ppu_state.fetch;
if (render) { if (render) {
ppu_draw_tile(); ppu_draw_tile();

View File

@ -4,7 +4,34 @@
#include "tile_debugger.h" #include "tile_debugger.h"
byte tile_encode_number(byte num) { // Contains the patterns of every hexadecimal digit encoded as pattern data.
// 8 segment display // The first dimension of the table represents a row in a tile.
byte hex_pattern_table[5][0x10] = {
{0b111, 0b001, 0b111, 0b111, 0b101, 0b111, 0b111, 0b111, 0b111, 0b111, 0b010, 0b111, 0b111, 0b110, 0b111, 0b111},
{0b101, 0b001, 0b001, 0b001, 0b101, 0b100, 0b100, 0b001, 0b101, 0b101, 0b101, 0b101, 0b100, 0b101, 0b100, 0b100},
{0b101, 0b001, 0b111, 0b111, 0b111, 0b111, 0b111, 0b010, 0b111, 0b111, 0b111, 0b110, 0b100, 0b101, 0b111, 0b110},
{0b101, 0b001, 0b100, 0b001, 0b001, 0b001, 0b101, 0b010, 0b101, 0b001, 0b101, 0b101, 0b100, 0b101, 0b100, 0b100},
{0b111, 0b001, 0b111, 0b111, 0b001, 0b111, 0b111, 0b010, 0b111, 0b001, 0b101, 0b111, 0b111, 0b110, 0b111, 0b100},
};
byte tile_debugger_encode_number_as_pattern(byte num, byte tile_fine_y) {
if (tile_fine_y == 6) {
return 0x7f; // On row 6, a full line is drawn to make it easier to separate tiles
} else if (tile_fine_y == 5 || tile_fine_y == 7) {
return 0;
}
// The first digit of the hex is encoded
byte remaining = num % 0x10;
byte encoded = hex_pattern_table[tile_fine_y][remaining];
if (num > 0xf) {
// If the number is greater than 0xF, we need a second digit
// We encode it, then add it 4 pixels to the left of the already encoded digit
byte tenths = num / 0x10;
byte tenths_encoded = hex_pattern_table[tile_fine_y][tenths];
encoded = (tenths_encoded << 4) | encoded;
}
return encoded;
} }

View File

@ -7,4 +7,13 @@
#include "../include/types.h" #include "../include/types.h"
/**
* Encodes a number as pattern data.
*
* @param num The number to encode
* @param tile_fine_y The row of the tile
* @return Pattern data representing the row of the encoded number
*/
byte tile_debugger_encode_number_as_pattern(byte num, byte tile_fine_y);
#endif //NES_EMULATOR_TILE_DEBUGGER_H #endif //NES_EMULATOR_TILE_DEBUGGER_H