Nametable view palette

This commit is contained in:
william 2024-08-03 21:51:31 -04:00
parent 96af510b19
commit 81451b24ad
13 changed files with 226 additions and 38 deletions

View File

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

99
gui/colors.h Normal file
View File

@ -0,0 +1,99 @@
//
// Created by william on 7/29/24.
//
#ifndef NES_EMULATOR_COLORS_H
#define NES_EMULATOR_COLORS_H
// Generated from http://drag.wootest.net/misc/palgen.html
#define COLOR_00 0x555555
#define COLOR_01 0x001773
#define COLOR_02 0x000786
#define COLOR_03 0x2e0578
#define COLOR_04 0x59024d
#define COLOR_05 0x720011
#define COLOR_06 0x6e0000
#define COLOR_07 0x4c0800
#define COLOR_08 0x171b00
#define COLOR_09 0x002a00
#define COLOR_0A 0x003100
#define COLOR_0B 0x002e00
#define COLOR_0C 0x002645
#define COLOR_0D 0x000000
#define COLOR_0E 0x000000
#define COLOR_0F 0x000000
#define COLOR_10 0xa5a5a5
#define COLOR_11 0x0057c6
#define COLOR_12 0x223fe5
#define COLOR_13 0x6e28d9
#define COLOR_14 0xae1aa6
#define COLOR_15 0xd21759
#define COLOR_16 0xd12107
#define COLOR_17 0xa73700
#define COLOR_18 0x635100
#define COLOR_19 0x186700
#define COLOR_1A 0x007200
#define COLOR_1B 0x007331
#define COLOR_1C 0x006a84
#define COLOR_1D 0x000000
#define COLOR_1E 0x000000
#define COLOR_1F 0x000000
#define COLOR_20 0xfefeff
#define COLOR_21 0x2aa3ff
#define COLOR_22 0x587cff
#define COLOR_23 0x976bff
#define COLOR_24 0xf36eff
#define COLOR_25 0xff5ea4
#define COLOR_26 0xff635a
#define COLOR_27 0xfe8122
#define COLOR_28 0xcda000
#define COLOR_29 0x81b802
#define COLOR_2A 0x3dc830
#define COLOR_2B 0x12cd7b
#define COLOR_2C 0x0dc5d0
#define COLOR_2D 0x3c3c3c
#define COLOR_2E 0x000000
#define COLOR_2F 0x000000
#define COLOR_30 0xfefeff
#define COLOR_31 0xa2dcff
#define COLOR_32 0xadc4ff
#define COLOR_33 0xc9baff
#define COLOR_34 0xf1bfff
#define COLOR_35 0xffb8dd
#define COLOR_36 0xffb7b9
#define COLOR_37 0xffc5a3
#define COLOR_38 0xffd696
#define COLOR_39 0xd0e095
#define COLOR_3A 0xb3e7a5
#define COLOR_3B 0x9feac3
#define COLOR_3C 0x9ae8e6
#define COLOR_3D 0xafafaf
#define COLOR_3E 0x000000
#define COLOR_3F 0x000000
#define COLOR_LIST_(row) \
COLOR_ ## row ## 0, \
COLOR_ ## row ## 1, \
COLOR_ ## row ## 2, \
COLOR_ ## row ## 3, \
COLOR_ ## row ## 4, \
COLOR_ ## row ## 5, \
COLOR_ ## row ## 6, \
COLOR_ ## row ## 7, \
COLOR_ ## row ## 8, \
COLOR_ ## row ## 9, \
COLOR_ ## row ## A, \
COLOR_ ## row ## B, \
COLOR_ ## row ## C, \
COLOR_ ## row ## D, \
COLOR_ ## row ## E, \
COLOR_ ## row ## F
#define COLOR_LIST {\
COLOR_LIST_(0), \
COLOR_LIST_(1), \
COLOR_LIST_(2), \
COLOR_LIST_(3) \
}
#endif //NES_EMULATOR_COLORS_H

View File

@ -7,8 +7,6 @@
#include "../include/system.h" #include "../include/system.h"
#include "../include/rom.h" #include "../include/rom.h"
// TODO: Add support for palettes
#define NAMETABLE_ROW_DRAW_WIDTH (NAMETABLE_ROW_WIDTH * PATTERN_DRAW_SIZE) #define NAMETABLE_ROW_DRAW_WIDTH (NAMETABLE_ROW_WIDTH * PATTERN_DRAW_SIZE)
DebugNameTable dbg_nametable; DebugNameTable dbg_nametable;
@ -22,6 +20,9 @@ void dbg_nametable_build_bank(byte *nametable, DebugTile *bank) {
DebugTile *tile = &bank[i]; DebugTile *tile = &bank[i];
tile->tile_id = nametable[i]; tile->tile_id = nametable[i];
address attr_addr = 0x3c0 | (i & 0xc00) | ((i >> 4) & 0x38) | ((i >> 2) & 0x7);
tile->attribute = nametable[attr_addr];
} }
} }
@ -62,6 +63,21 @@ void dbg_nametable_render_bank(int bank, pixel *buffer) {
(row * PATTERN_DRAW_SIZE * PATTERN_DRAW_SIZE * NAMETABLE_ROW_WIDTH) + (col * PATTERN_DRAW_SIZE); (row * PATTERN_DRAW_SIZE * PATTERN_DRAW_SIZE * NAMETABLE_ROW_WIDTH) + (col * PATTERN_DRAW_SIZE);
pixel *tile_buffer = &buffer[tile_pixel_addr]; pixel *tile_buffer = &buffer[tile_pixel_addr];
dbg_pattern_draw(pattern_id, pattern_bank, tile_buffer, NAMETABLE_ROW_DRAW_WIDTH); // Attribute Data:
// 7654 3210
// |||| ||++- Color bits 3-2 for top left quadrant of this byte
// |||| ++--- Color bits 3-2 for top right quadrant of this byte
// ||++------ Color bits 3-2 for bottom left quadrant of this byte
// ++-------- Color bits 3-2 for bottom right quadrant of this byte
byte palette = table[i].attribute;
if (row % 4 >= 2) {
palette >>= 4;
}
if (col % 4 >= 2) {
palette >>= 2;
}
palette &= 0b11;
dbg_pattern_draw(pattern_id, pattern_bank, tile_buffer, NAMETABLE_ROW_DRAW_WIDTH, palette);
} }
} }

View File

@ -13,8 +13,9 @@
#define NAMETABLE_ROW_WIDTH 32 #define NAMETABLE_ROW_WIDTH 32
#define NAMETABLE_COL_HEIGHT 30 #define NAMETABLE_COL_HEIGHT 30
typedef struct db_tile { typedef struct dbg_tile {
int tile_id; int tile_id;
int attribute;
} DebugTile; } DebugTile;
typedef struct dbg_nametable { typedef struct dbg_nametable {

38
gui/dbg_palette.c Normal file
View File

@ -0,0 +1,38 @@
//
// Created by william on 7/28/24.
//
#include <string.h>
#include <stdio.h>
#include "dbg_palette.h"
#include "../include/ppu.h"
#include "colors.h"
DebugPaletteMemory palette_memory;
pixel color_list[0x40] = COLOR_LIST;
#define COPY_PALETTE(memory, dest) memcpy(&(dest), &(memory), sizeof(DebugPalette))
#define COPY_PALETTES(memory, base_addr, dest) \
COPY_PALETTE((memory)[(base_addr) + 0x1], (dest)[0]); \
COPY_PALETTE((memory)[(base_addr) + 0x5], (dest)[1]); \
COPY_PALETTE((memory)[(base_addr) + 0x9], (dest)[2]); \
COPY_PALETTE((memory)[(base_addr) + 0xd], (dest)[3]) \
void dbg_palette_init() {
byte *memory = ppu_get_state()->memory.palette;
palette_memory.universal_background_color = memory[0];
COPY_PALETTES(memory, 0, palette_memory.background_palettes);
COPY_PALETTES(memory, 0x10, palette_memory.sprite_palettes);
}
pixel dbg_get_background_color(byte palette, byte data) {
if (data == 0) {
return palette_memory.universal_background_color;
}
int color = palette_memory.background_palettes[palette][data - 1];
return color_list[color];
}

26
gui/dbg_palette.h Normal file
View File

@ -0,0 +1,26 @@
//
// Created by william on 7/28/24.
//
#ifndef NES_EMULATOR_DBG_PALETTE_H
#define NES_EMULATOR_DBG_PALETTE_H
#include "../include/types.h"
#include "dbg_pattern_table.h"
#define PALETTE_SIZE 3
#define PALETTE_COUNT 4
typedef byte DebugPalette[PALETTE_SIZE];
typedef struct dbg_palette_memory {
byte universal_background_color;
DebugPalette background_palettes[PALETTE_COUNT];
DebugPalette sprite_palettes[PALETTE_COUNT];
} DebugPaletteMemory;
void dbg_palette_init();
pixel dbg_get_background_color(byte palette, byte data);
#endif //NES_EMULATOR_DBG_PALETTE_H

View File

@ -8,6 +8,7 @@
#include "dbg_pattern_table.h" #include "dbg_pattern_table.h"
#include "../include/ppu.h" #include "../include/ppu.h"
#include "../include/system.h" #include "../include/system.h"
#include "dbg_palette.h"
DebugPatternTable pattern_table; DebugPatternTable pattern_table;
@ -29,6 +30,7 @@ void dbg_pattern_table_init() {
} }
DebugPattern dbg_pattern_get(int pattern_id, int bank) { DebugPattern dbg_pattern_get(int pattern_id, int bank) {
// TODO Should not use same bank
switch (bank) { switch (bank) {
case PATTERN_BANK_0: case PATTERN_BANK_0:
return pattern_table.bank_1[pattern_id]; return pattern_table.bank_1[pattern_id];
@ -61,43 +63,34 @@ void dbg_pattern_draw_borders(pixel *buffer, int buffer_width) {
} }
} }
void dbg_pattern_draw_pattern(DebugPattern pattern, pixel *buffer, int buffer_width) { void dbg_pattern_draw_pattern(DebugPattern pattern, pixel *buffer, int buffer_width, byte palette) {
for (int fine_y = 0; fine_y < PATTERN_SIZE; fine_y++) { for (int fine_y = 0; fine_y < PATTERN_SIZE; fine_y++) {
byte data_high = pattern.data_high[fine_y]; byte data_high = pattern.data_high[fine_y];
byte data_low = pattern.data_low[fine_y]; byte data_low = pattern.data_low[fine_y];
for (int fine_x = 0; fine_x < PATTERN_SIZE; fine_x++) { for (int fine_x = 0; fine_x < PATTERN_SIZE; fine_x++) {
byte bitmask = 1 << (PATTERN_SIZE - fine_x - 1); byte offset = PATTERN_SIZE - fine_x - 1;
byte bit_high = data_high & bitmask; byte bit_high = (data_high >> offset) & 1;
byte bit_low = data_low & bitmask; byte bit_low = (data_low >> offset) & 1;
address pixel_addr = fine_x + fine_y * buffer_width; address pixel_addr = fine_x + fine_y * buffer_width;
pixel *pixel = &buffer[pixel_addr];
// TODO: Use palette colors byte palette_data = (bit_high << 1) | bit_low;
if (bit_high && bit_low) { buffer[pixel_addr] = dbg_get_background_color(palette, palette_data);
*pixel = 0xffffffff;
} else if (bit_low) {
*pixel = 0xffff0000;
} else if (bit_high) {
*pixel = 0xff00ffff;
} else {
*pixel = 0xff000000;
}
} }
} }
dbg_pattern_draw_borders(buffer, buffer_width); dbg_pattern_draw_borders(buffer, buffer_width);
} }
void dbg_pattern_draw(int pattern_id, int bank, pixel *buffer, int buffer_width) { void dbg_pattern_draw(int pattern_id, int bank, pixel *buffer, int buffer_width, int palette) {
DebugPattern pattern = dbg_pattern_get(pattern_id, bank); DebugPattern pattern = dbg_pattern_get(pattern_id, bank);
dbg_pattern_draw_pattern(pattern, buffer, buffer_width); dbg_pattern_draw_pattern(pattern, buffer, buffer_width, palette);
} }
void dbg_pattern_draw_pos(int x, int y, int bank, pixel *buffer, int buffer_width) { void dbg_pattern_draw_pos(int x, int y, int bank, pixel *buffer, int buffer_width, int palette) {
DebugPattern pattern = dbg_pattern_get_pos(x, y, bank); DebugPattern pattern = dbg_pattern_get_pos(x, y, bank);
dbg_pattern_draw_pattern(pattern, buffer, buffer_width); dbg_pattern_draw_pattern(pattern, buffer, buffer_width, palette);
} }
void dbg_pattern_draw_bank(int bank, pixel *buffer) { void dbg_pattern_draw_bank(int bank, pixel *buffer) {
@ -108,7 +101,7 @@ void dbg_pattern_draw_bank(int bank, pixel *buffer) {
address row_addr = (y * PATTERN_DRAW_SIZE) * buffer_width; address row_addr = (y * PATTERN_DRAW_SIZE) * buffer_width;
address tile_addr = row_addr + (x * PATTERN_DRAW_SIZE); address tile_addr = row_addr + (x * PATTERN_DRAW_SIZE);
dbg_pattern_draw_pos(x, y, bank, &buffer[tile_addr], buffer_width); dbg_pattern_draw_pos(x, y, bank, &buffer[tile_addr], buffer_width, 01);
} }
} }
} }

View File

@ -59,8 +59,9 @@ DebugPattern dbg_pattern_get_pos(int x, int y, int bank);
* @param bank The bank of the pattern * @param bank The bank of the pattern
* @param buffer The buffer to write the pattern data to * @param buffer The buffer to write the pattern data to
* @param buffer_width The width of a pixel row in the buffer * @param buffer_width The width of a pixel row in the buffer
* @param palette The background palette to use
*/ */
void dbg_pattern_draw(int pattern_id, int bank, pixel *buffer, int buffer_width); void dbg_pattern_draw(int pattern_id, int bank, pixel *buffer, int buffer_width, int palette);
/** /**
* Draws a pattern to a buffer. The pattern is determined by its position. * Draws a pattern to a buffer. The pattern is determined by its position.
@ -69,11 +70,12 @@ void dbg_pattern_draw(int pattern_id, int bank, pixel *buffer, int buffer_width)
* @param bank The bank of the pattern * @param bank The bank of the pattern
* @param buffer The buffer to write the pattern data to * @param buffer The buffer to write the pattern data to
* @param buffer_width The width of a pixel row in the buffer * @param buffer_width The width of a pixel row in the buffer
* @param palette The background palette to use
*/ */
void dbg_pattern_draw_pos(int x, int y, int bank, pixel *buffer, int buffer_width); void dbg_pattern_draw_pos(int x, int y, int bank, pixel *buffer, int buffer_width, int palette);
/** /**
* Draws a pattern bank to a buffer. * Draws a pattern bank to a buffer. Uses the palette #0.
* @param bank The bank to draw (0 -> 0x0000, 1 -> 0x1000) * @param bank The bank to draw (0 -> 0x0000, 1 -> 0x1000)
* @param buffer The buffer to write the patterns data to. * @param buffer The buffer to write the patterns data to.
*/ */

View File

@ -12,6 +12,7 @@
#include "dbg_pattern_table.h" #include "dbg_pattern_table.h"
#include "dbg_nametable.h" #include "dbg_nametable.h"
#include "char_map.h" #include "char_map.h"
#include "dbg_palette.h"
typedef struct nes_gui { typedef struct nes_gui {
NesMainWindow main_window; NesMainWindow main_window;
@ -65,6 +66,7 @@ void gui_uninit() {
void gui_post_sysinit() { void gui_post_sysinit() {
#if DEBUG #if DEBUG
dbg_palette_init();
dbg_pattern_table_init(); dbg_pattern_table_init();
dbg_nametable_init(); dbg_nametable_init();
@ -80,6 +82,10 @@ int gui_input() {
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) { if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) {
return -1; return -1;
} }
if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_p) {
system_toggle_pause();
}
} }
return 1; return 1;
@ -87,6 +93,7 @@ int gui_input() {
void gui_render() { void gui_render() {
#if DEBUG #if DEBUG
dbg_palette_init();
pattern_window_render(&gui.pattern_window); pattern_window_render(&gui.pattern_window);
nametable_window_update(&gui.nametable_window); nametable_window_update(&gui.nametable_window);

View File

@ -8,7 +8,7 @@
#include "window.h" #include "window.h"
#include "../include/types.h" #include "../include/types.h"
#define NW_SCALE 1 #define NW_SCALE 2
#define NW_ROW_COUNT 60 #define NW_ROW_COUNT 60
#define NW_ROW_TILE_COUNT 64 #define NW_ROW_TILE_COUNT 64

View File

@ -24,8 +24,8 @@
typedef struct system { typedef struct system {
void *rom_header; void *rom_header;
Mapper mapper; Mapper mapper;
byte apu_registers[APU_REGISTERS_COUNT];
unsigned long cycle_count; unsigned long cycle_count;
bool paused;
} System; } System;
/** /**
@ -38,9 +38,9 @@ void system_start();
void system_next_frame(); void system_next_frame();
/** /**
* Starts the main loop of a system. * Toggle pause for the system. If not paused, CPU and PPU cycles will be stopped until this method is called again.
*/ */
void system_loop(); void system_toggle_pause();
/** /**
* De-initialize the components of a system. * De-initialize the components of a system.
@ -49,8 +49,6 @@ void system_uninit();
unsigned int system_get_cycles(); unsigned int system_get_cycles();
void system_add_cycles(unsigned int cycles);
Mapper *system_get_mapper(); Mapper *system_get_mapper();
#endif //NESEMULATOR_SYSTEM_H #endif //NESEMULATOR_SYSTEM_H

4
main.c
View File

@ -23,8 +23,8 @@
#include "gui.h" #include "gui.h"
int main() { int main() {
char *rom_path = "./test_roms/dk_jp.nes"; // char *rom_path = "./test_roms/dk_japan.nes";
// char *rom_path = "./test_roms/nes-test-roms/other/BLOCKS.NES"; char *rom_path = "./test_roms/smb.nes";
log_set_level(LOG_INFO); log_set_level(LOG_INFO);
if (!gui_init()) { if (!gui_init()) {

View File

@ -23,6 +23,10 @@ void system_start() {
} }
void system_next_frame() { void system_next_frame() {
if (current_sys.paused) {
return;
}
for (int cpu_c = 0; cpu_c < CPU_CYCLE_PER_FRAME; cpu_c++) { for (int cpu_c = 0; cpu_c < CPU_CYCLE_PER_FRAME; cpu_c++) {
cpu_cycle(); cpu_cycle();
@ -32,6 +36,10 @@ void system_next_frame() {
} }
} }
void system_toggle_pause() {
current_sys.paused = !current_sys.paused;
}
void system_uninit() { void system_uninit() {
} }