Browse Source

Add skeleton SDL renderer for PPU

master
Nathaniel Walizer 1 year ago
parent
commit
787bd6b739
6 changed files with 157 additions and 6 deletions
  1. +3
    -3
      Makefile
  2. +13
    -1
      src/nese.c
  3. +2
    -2
      src/ppu.c
  4. +3
    -0
      src/ppu.h
  5. +27
    -0
      src/render.h
  6. +109
    -0
      src/sdl_render.c

+ 3
- 3
Makefile View File

@@ -1,6 +1,6 @@
CC = gcc
LD = $(CC)
CFLAGS = -Wall -Werror -Wshadow -I.. -g -DE6502_DEBUG
CFLAGS = -Wall -Werror -Wshadow -I.. -g #-DE6502_DEBUG
LDFLAGS =

OBJDIR = obj
@@ -11,9 +11,9 @@ BINDIR = bin
# nese

TARGET_1 = nese
LDLIBS_1 =
LDLIBS_1 = -lSDL

SRC_SRCS_1 = nese.c ines.c nes.c ppu.c
SRC_SRCS_1 = nese.c ines.c nes.c ppu.c sdl_render.c

EXT_SRCS_1 = e6502/e6502.c



+ 13
- 1
src/nese.c View File

@@ -2,7 +2,7 @@
#include <stdlib.h>

#include "ines.h"
#include "render.h"


void e6502_print_registers(const e6502_Registers* regs,
@@ -33,6 +33,7 @@ void e6502_dump_stack(e6502_Core* core, FILE* file) {
}


extern nes_Renderer sdl_renderer;

static nes sys = {0};

@@ -44,11 +45,17 @@ int main(int argc, char* argv[]) {

status = ines_load(&sys.cart.rom, stdin);

nes_Renderer* rend = &sdl_renderer;
if (status == 0) {
status = nes_render_init(rend);
}

if (status == 0) {
nes_init(&sys);
nes_reset(&sys);

int total_cycles = 0;
int last_frame_rendered = -1;
for (int i = 0; i < n_loops && status == 0; ++i) {
int run = 0;
status = nes_run(&sys, 1000, &run);
@@ -61,6 +68,11 @@ int main(int argc, char* argv[]) {
us_run, run,
status == 0 ? "OK" : "Halted");
*/
if ( status == 0 &&
sys.ppu.frame != last_frame_rendered) {
status = nes_render(rend, &sys.ppu);
last_frame_rendered = sys.ppu.frame;
}
}

float ms_run = ( total_cycles * 1000. *


+ 2
- 2
src/ppu.c View File

@@ -49,13 +49,13 @@ uint8_t nes_ppu_read(nes_ppu* ppu, uint16_t addr) {
32 : 1;
}

fprintf(stderr, "PPU: <-R $%04x %02x\n", addr, val);
// fprintf(stdout, "PPU: <-R $%04x %02x\n", addr, val);

return val;
}

void nes_ppu_write(nes_ppu* ppu, uint16_t addr, uint8_t val) {
fprintf(stderr, "PPU: W-> $%04x %02x\n", addr, val);
// fprintf(stdout, "PPU: W-> $%04x %02x\n", addr, val);

if (ppu_reg_ctrl == addr) {
ppu->control = val;


+ 3
- 0
src/ppu.h View File

@@ -10,6 +10,9 @@
#define nes_ppu_postrender (1U)
#define nes_ppu_vblank (20U)

#define nes_ppu_render_w (320U)
#define nes_ppu_render_h nes_ppu_height

#define nes_ppu_mem_size (0x4000U)
#define nes_ppu_mem_pal_start (0x3F00U)
#define nes_ppu_mem_pal_size (0x0020U)


+ 27
- 0
src/render.h View File

@@ -0,0 +1,27 @@
#ifndef NES_RENDER_H_
#define NES_RENDER_H_

#include "ppu.h"


typedef struct nes_Renderer_t {
int (*init)(struct nes_Renderer_t*);
void (*done)(struct nes_Renderer_t*);
int (*render)(struct nes_Renderer_t*, nes_ppu*);
void* data;
} nes_Renderer;

static inline int nes_render_init(nes_Renderer* rend) {
return rend->init(rend);
}

static inline void nes_render_done(nes_Renderer* rend) {
rend->done(rend);
}

static inline int nes_render(nes_Renderer* rend, nes_ppu* ppu) {
return rend->render(rend, ppu);
}


#endif // NES_RENDER_H_

+ 109
- 0
src/sdl_render.c View File

@@ -0,0 +1,109 @@
#include <SDL/SDL.h>

#include "render.h"
#include "ppu.h"


typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} __attribute__ (( packed )) sPal;

static struct sPal nes_palette[64] = {
{0x80,0x80,0x80}, {0x00,0x00,0xBB}, {0x37,0x00,0xBF}, {0x84,0x00,0xA6},
{0xBB,0x00,0x6A}, {0xB7,0x00,0x1E}, {0xB3,0x00,0x00}, {0x91,0x26,0x00},
{0x7B,0x2B,0x00}, {0x00,0x3E,0x00}, {0x00,0x48,0x0D}, {0x00,0x3C,0x22},
{0x00,0x2F,0x66}, {0x00,0x00,0x00}, {0x05,0x05,0x05}, {0x05,0x05,0x05},

{0xC8,0xC8,0xC8}, {0x00,0x59,0xFF}, {0x44,0x3C,0xFF}, {0xB7,0x33,0xCC},
{0xFF,0x33,0xAA}, {0xFF,0x37,0x5E}, {0xFF,0x37,0x1A}, {0xD5,0x4B,0x00},
{0xC4,0x62,0x00}, {0x3C,0x7B,0x00}, {0x1E,0x84,0x15}, {0x00,0x95,0x66},
{0x00,0x84,0xC4}, {0x11,0x11,0x11}, {0x09,0x09,0x09}, {0x09,0x09,0x09},

{0xFF,0xFF,0xFF}, {0x00,0x95,0xFF}, {0x6F,0x84,0xFF}, {0xD5,0x6F,0xFF},
{0xFF,0x77,0xCC}, {0xFF,0x6F,0x99}, {0xFF,0x7B,0x59}, {0xFF,0x91,0x5F},
{0xFF,0xA2,0x33}, {0xA6,0xBF,0x00}, {0x51,0xD9,0x6A}, {0x4D,0xD5,0xAE},
{0x00,0xD9,0xFF}, {0x66,0x66,0x66}, {0x0D,0x0D,0x0D}, {0x0D,0x0D,0x0D},

{0xFF,0xFF,0xFF}, {0x84,0xBF,0xFF}, {0xBB,0xBB,0xFF}, {0xD0,0xBB,0xFF},
{0xFF,0xBF,0xEA}, {0xFF,0xBF,0xCC}, {0xFF,0xC4,0xB7}, {0xFF,0xCC,0xAE},
{0xFF,0xD9,0xA2}, {0xCC,0xE1,0x99}, {0xAE,0xEE,0xB7}, {0xAA,0xF7,0xEE},
{0xB3,0xEE,0xFF}, {0xDD,0xDD,0xDD}, {0x11,0x11,0x11}, {0x11,0x11,0x11}
};


typedef struct {
SDL_Surface* surface;
uint8_t buffer[3 * nes_ppu_render_w * nes_ppu_render_h];
} sdl_render_data;

static sdl_render_data the_render_data = {0};


static int filter(const SDL_Event* event) {
return event->type == SDL_QUIT;
}

static int sdl_render_init(nes_Renderer* rend) {
int status = SDL_Init(SDL_INIT_VIDEO);

if (0 != status) {
fprintf(stderr, "SDL: Failed to initialize\n");

} else {
SDL_WM_SetCaption("NESe", "NESe");

if (NULL == SDL_SetVideoMode(nes_ppu_render_w,
nes_ppu_render_h,
24, SDL_HWSURFACE)) {
fprintf(stderr, "SDL: Failed to set video mode\n");
status = -1;
}
}

if (0 == status) {
the_render_data.surface = SDL_CreateRGBSurfaceFrom(
the_render_data.buffer, nes_ppu_render_w,
nes_ppu_render_h, 24, nes_ppu_render_w * 3,
0xFFU, 0xFF00U, 0xFF0000U, 0
);

SDL_SetEventFilter(filter);

rend->data = &the_render_data;
}

return status;
}

static void sdl_render_done(nes_Renderer* rend) {
sdl_render_data* data = (sdl_render_data*)rend->data;
if (NULL != data->surface) {
SDL_FreeSurface(data->surface);
data->surface = NULL;
}
SDL_Quit();
}

static int sdl_render(nes_Renderer* rend, nes_ppu* ppu) {
sdl_render_data* data = (sdl_render_data*)rend->data;

// TODO

SDL_Surface* screen = SDL_GetVideoSurface();
if (0 == SDL_BlitSurface(data->surface, NULL, screen, NULL)) {
SDL_UpdateRect(screen, 0, 0, 0, 0);
}

SDL_Event event = {0};
return (1 == SDL_PollEvent(&event) && event.type == SDL_QUIT) ?
-1 : 0;
}


nes_Renderer sdl_renderer = {
.init = sdl_render_init,
.done = sdl_render_done,
.render = sdl_render,
};

Loading…
Cancel
Save