Add palette colors the main emulator view
This commit is contained in:
parent
0066e77455
commit
d1ddcb1b0f
|
@ -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)
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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
|
73
ppu/ppu.c
73
ppu/ppu.c
|
@ -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;
|
||||||
|
|
||||||
static inline byte ppu_pixel_get_mask(unsigned int tile_fine_x) {
|
// Attribute Data:
|
||||||
return 1 << (8 - tile_fine_x - 1);
|
// 7654 3210
|
||||||
}
|
// |||| ||++- Color bits 3-2 for top left quadrant of this byte
|
||||||
|
// |||| ++--- Color bits 3-2 for top right quadrant of this byte
|
||||||
static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_high) {
|
// ||++------ Color bits 3-2 for bottom left quadrant of this byte
|
||||||
for (int i = 0; i < 8; i++) {
|
// ++-------- Color bits 3-2 for bottom right quadrant of this byte
|
||||||
PPUPixel *spixel = pixel + i;
|
byte palette = attribute;
|
||||||
byte bitmask = ppu_pixel_get_mask(i);
|
if (tile_y % 4 >= 2) {
|
||||||
|
palette >>= 4;
|
||||||
byte p1_byte = pt_low & bitmask;
|
|
||||||
byte p2_byte = pt_high & bitmask;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
if (tile_x % 4 >= 2) {
|
||||||
|
palette >>= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return palette & 0b11;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ppu_pixel_set_color(PPUPixel *pixel, byte pt_low, byte pt_high, byte attribute) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
byte pixel_offset = 8 - i - 1;
|
||||||
|
|
||||||
|
byte color_low = (pt_low >> pixel_offset) & 1;
|
||||||
|
byte color_high = (pt_high >> pixel_offset) & 1;
|
||||||
|
byte color_offset = (color_high << 1) | color_low;
|
||||||
|
|
||||||
|
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;
|
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) {
|
||||||
|
|
Loading…
Reference in New Issue