Add palette colors the main emulator view

This commit is contained in:
william 2024-08-13 17:32:54 -04:00
parent 0066e77455
commit d1ddcb1b0f
7 changed files with 59 additions and 54 deletions

View File

@ -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) set(SOURCE gui.c window.c main_window.c)
if (NES_DEBUG) if (NES_DEBUG)

View File

@ -3,13 +3,12 @@
// //
#include <string.h> #include <string.h>
#include <stdio.h>
#include "dbg_palette.h" #include "dbg_palette.h"
#include "../include/ppu.h" #include "../include/ppu.h"
#include "colors.h" #include "../ppu/colors.h"
DebugPaletteMemory palette_memory; 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_PALETTE(memory, dest) memcpy(&(dest), &(memory), sizeof(DebugPalette))
#define COPY_PALETTES(memory, base_addr, dest) \ #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]; int color = palette_memory.background_palettes[palette][data - 1];
return color_list[color]; return dbg_color_list[color];
} }

View File

@ -37,18 +37,18 @@ void main_window_render_delay(SDL_Renderer *renderer) {
void main_window_render(NesMainWindow *window, PPUPixel *pixels) { void main_window_render(NesMainWindow *window, PPUPixel *pixels) {
SDL_RenderClear(window->sdl_context.renderer); SDL_RenderClear(window->sdl_context.renderer);
unsigned int frame_buffer[240 * 256]; // unsigned int frame_buffer[240 * 256];
for (int i = 0; i < 240 * 256; i++) { // for (int i = 0; i < 240 * 256; i++) {
PPUPixel pixel = pixels[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]; SDL_UpdateTexture(window->texture, NULL, pixels, 240 * sizeof(unsigned int));
*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_RenderCopy(window->sdl_context.renderer, window->texture, NULL, NULL); SDL_RenderCopy(window->sdl_context.renderer, window->texture, NULL, NULL);
#if DEBUG #if DEBUG

View File

@ -69,11 +69,12 @@ typedef struct ppu_tile_fetch {
byte pattern_table_tile_high; byte pattern_table_tile_high;
} PPUTileFetch; } PPUTileFetch;
typedef struct ppu_pixel { //typedef struct ppu_pixel {
byte r; // byte r;
byte g; // byte g;
byte b; // byte b;
} PPUPixel; //} PPUPixel;
typedef unsigned int PPUPixel;
typedef struct ppu_tile_queue { typedef struct ppu_tile_queue {
PPUTileFetch first_fetch; PPUTileFetch first_fetch;
@ -105,8 +106,6 @@ typedef struct ppu {
PPUTileFetch fetch; PPUTileFetch fetch;
PPUTileQueue tile_queue; PPUTileQueue tile_queue;
// PPUTileFetch tile_fetch;
// PPUTileFetch fetch;
unsigned long frame; unsigned long frame;
unsigned int scanline; unsigned int scanline;
unsigned int cycle; unsigned int cycle;

View File

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

View File

@ -1,5 +1,5 @@
// //
// Created by william on 7/29/24. // Created by william on 8/6/24.
// //
#ifndef NES_EMULATOR_COLORS_H #ifndef NES_EMULATOR_COLORS_H

View File

@ -19,6 +19,7 @@
#include "../include/ppu.h" #include "../include/ppu.h"
#include "../cpu/cpu.h" #include "../cpu/cpu.h"
#include "../include/rom.h" #include "../include/rom.h"
#include "colors.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
@ -27,7 +28,10 @@
#define PPU_LINE_END PPU_PRE_RENDER_LINE #define PPU_LINE_END PPU_PRE_RENDER_LINE
#define PPU_LINE_WIDTH 340 #define PPU_LINE_WIDTH 340
#define NAMETABLE_TILE_SIZE 8
PPU ppu_state; PPU ppu_state;
PPUPixel color_list[0x40] = COLOR_LIST;
void ppu_init() { void ppu_init() {
memset(&ppu_state, 0, sizeof(PPU)); 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 `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 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) { static inline byte ppu_pixel_get_palette(byte attribute) {
return scanline * PPU_VISIBLE_FRAME_END + cycle; 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) { static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_high, byte attribute) {
return 1 << (8 - tile_fine_x - 1);
}
static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_high) {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
PPUPixel *spixel = pixel + i; byte pixel_offset = 8 - i - 1;
byte bitmask = ppu_pixel_get_mask(i);
byte p1_byte = pt_low & bitmask; byte color_low = (pt_low >> pixel_offset) & 1;
byte p2_byte = pt_high & bitmask; byte color_high = (pt_high >> pixel_offset) & 1;
byte color_offset = (color_high << 1) | color_low;
if (p1_byte && p2_byte) { address color_addr = 0x3f00 + color_offset;
spixel->r = 255; if (color_offset != 0) { // The first color of a palette (0) is always the universal color
spixel->g = 255; color_addr += ppu_pixel_get_palette(attribute) * 4;
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;
} }
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; PPUTileFetch fetch = ppu_state.tile_queue.displayed_fetch;
unsigned int y = ppu_state.scanline; unsigned int y = ppu_state.scanline;
unsigned int x = ppu_state.cycle + 0; unsigned int x = ppu_state.cycle;
// if (x > PPU_LINE_WIDTH) { // if (x > PPU_LINE_WIDTH) {
// 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; unsigned int pixel_index = y * PPU_VISIBLE_FRAME_END + x;
PPUPixel *pixel = &ppu_state.pixels[pixel_index]; 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) { byte ppu_get_pattern(byte tile_index, byte high) {