diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 4d25092..06bb855 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -1,4 +1,4 @@ -set(HEADERS gui.h window.h main_window.h colors.h) +set(HEADERS gui.h window.h main_window.h) set(SOURCE gui.c window.c main_window.c) if (NES_DEBUG) diff --git a/gui/dbg_palette.c b/gui/dbg_palette.c index 9b6f932..7f40aaf 100644 --- a/gui/dbg_palette.c +++ b/gui/dbg_palette.c @@ -3,13 +3,12 @@ // #include -#include #include "dbg_palette.h" #include "../include/ppu.h" -#include "colors.h" +#include "../ppu/colors.h" DebugPaletteMemory palette_memory; -pixel color_list[0x40] = COLOR_LIST; +pixel dbg_color_list[0x40] = COLOR_LIST; #define COPY_PALETTE(memory, dest) memcpy(&(dest), &(memory), sizeof(DebugPalette)) #define COPY_PALETTES(memory, base_addr, dest) \ @@ -34,5 +33,5 @@ pixel dbg_get_background_color(byte palette, byte data) { } int color = palette_memory.background_palettes[palette][data - 1]; - return color_list[color]; + return dbg_color_list[color]; } \ No newline at end of file diff --git a/gui/main_window.c b/gui/main_window.c index 83ecbc9..b255437 100644 --- a/gui/main_window.c +++ b/gui/main_window.c @@ -37,18 +37,18 @@ void main_window_render_delay(SDL_Renderer *renderer) { 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]; +// 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; +// } - unsigned int *data = &frame_buffer[i]; - *data = 0xff000000; - *data |= pixel.r << 16; - *data |= pixel.g << 8; - *data |= pixel.b; - } - - SDL_UpdateTexture(window->texture, NULL, &frame_buffer, 240 * sizeof(unsigned int)); + SDL_UpdateTexture(window->texture, NULL, pixels, 240 * sizeof(unsigned int)); SDL_RenderCopy(window->sdl_context.renderer, window->texture, NULL, NULL); #if DEBUG diff --git a/include/ppu.h b/include/ppu.h index eba088f..8d58d7c 100644 --- a/include/ppu.h +++ b/include/ppu.h @@ -69,11 +69,12 @@ typedef struct ppu_tile_fetch { byte pattern_table_tile_high; } PPUTileFetch; -typedef struct ppu_pixel { - byte r; - byte g; - byte b; -} PPUPixel; +//typedef struct ppu_pixel { +// byte r; +// byte g; +// byte b; +//} PPUPixel; +typedef unsigned int PPUPixel; typedef struct ppu_tile_queue { PPUTileFetch first_fetch; @@ -105,8 +106,6 @@ typedef struct ppu { PPUTileFetch fetch; PPUTileQueue tile_queue; -// PPUTileFetch tile_fetch; -// PPUTileFetch fetch; unsigned long frame; unsigned int scanline; unsigned int cycle; diff --git a/ppu/CMakeLists.txt b/ppu/CMakeLists.txt index b5fc80a..4997c17 100644 --- a/ppu/CMakeLists.txt +++ b/ppu/CMakeLists.txt @@ -1,4 +1,4 @@ -set(HEADERS ppu.h palette.h) +set(HEADERS ppu.h palette.h colors.h) set(SOURCE ppu.c palette.c) add_library(nes_ppu ${SOURCE} ${HEADERS}) diff --git a/gui/colors.h b/ppu/colors.h similarity index 98% rename from gui/colors.h rename to ppu/colors.h index 35c2f2d..1e61808 100644 --- a/gui/colors.h +++ b/ppu/colors.h @@ -1,5 +1,5 @@ // -// Created by william on 7/29/24. +// Created by william on 8/6/24. // #ifndef NES_EMULATOR_COLORS_H diff --git a/ppu/ppu.c b/ppu/ppu.c index 3600108..80b8dcc 100644 --- a/ppu/ppu.c +++ b/ppu/ppu.c @@ -19,6 +19,7 @@ #include "../include/ppu.h" #include "../cpu/cpu.h" #include "../include/rom.h" +#include "colors.h" #define PPU_VISIBLE_FRAME_END 240 #define PPU_POST_RENDER_LINE_START PPU_VISIBLE_FRAME_END @@ -27,7 +28,10 @@ #define PPU_LINE_END PPU_PRE_RENDER_LINE #define PPU_LINE_WIDTH 340 +#define NAMETABLE_TILE_SIZE 8 + PPU ppu_state; +PPUPixel color_list[0x40] = COLOR_LIST; void ppu_init() { memset(&ppu_state, 0, sizeof(PPU)); @@ -70,39 +74,42 @@ void ppu_trigger_vbl_nmi() { 88 `88. 88. 88 V888 88 .8D 88. 88 `88. .88. 88 V888 88. ~8~ 88 YD Y88888P VP V8P Y8888D' Y88888P 88 YD Y888888P VP V8P Y888P */ -static inline unsigned int ppu_pixel_get_index(unsigned int scanline, unsigned int cycle) { - return scanline * PPU_VISIBLE_FRAME_END + cycle; +static inline byte ppu_pixel_get_palette(byte attribute) { + unsigned int tile_x = ppu_state.cycle / NAMETABLE_TILE_SIZE; + unsigned int tile_y = ppu_state.scanline / NAMETABLE_TILE_SIZE; + + // 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 = attribute; + if (tile_y % 4 >= 2) { + palette >>= 4; + } + if (tile_x % 4 >= 2) { + palette >>= 2; + } + + return palette & 0b11; } -static inline byte ppu_pixel_get_mask(unsigned int tile_fine_x) { - return 1 << (8 - tile_fine_x - 1); -} - -static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_high) { +static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_high, byte attribute) { for (int i = 0; i < 8; i++) { - PPUPixel *spixel = pixel + i; - byte bitmask = ppu_pixel_get_mask(i); + byte pixel_offset = 8 - i - 1; - byte p1_byte = pt_low & bitmask; - byte p2_byte = pt_high & bitmask; + byte color_low = (pt_low >> pixel_offset) & 1; + byte color_high = (pt_high >> pixel_offset) & 1; + byte color_offset = (color_high << 1) | color_low; - if (p1_byte && p2_byte) { - spixel->r = 255; - spixel->g = 255; - spixel->b = 255; - } else if (p2_byte) { - spixel->r = 255; - spixel->g = 0; - spixel->b = 0; - } else if (p1_byte) { - spixel->r = 0; - spixel->g = 255; - spixel->b = 255; - } else { - spixel->r = 0; - spixel->g = 0; - spixel->b = 0; + address color_addr = 0x3f00 + color_offset; + if (color_offset != 0) { // The first color of a palette (0) is always the universal color + color_addr += ppu_pixel_get_palette(attribute) * 4; } + + byte color = ppu_read(color_addr); + *(pixel + i) = color_list[color]; } } @@ -110,7 +117,7 @@ void ppu_draw_tile() { PPUTileFetch fetch = ppu_state.tile_queue.displayed_fetch; unsigned int y = ppu_state.scanline; - unsigned int x = ppu_state.cycle + 0; + unsigned int x = ppu_state.cycle; // if (x > PPU_LINE_WIDTH) { // x -= PPU_LINE_WIDTH; @@ -123,7 +130,7 @@ void ppu_draw_tile() { unsigned int pixel_index = y * PPU_VISIBLE_FRAME_END + x; PPUPixel *pixel = &ppu_state.pixels[pixel_index]; - ppu_pixel_set_color(pixel, fetch.pattern_table_tile_low, fetch.pattern_table_tile_high); + 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) {