Skip to content

Commit

Permalink
wip: prepare seperation of interfaces to ppu .
Browse files Browse the repository at this point in the history
One interface to emulator and one (ppu internal) interface to
actual video output
  • Loading branch information
semiversus committed Oct 30, 2018
1 parent e7f73cc commit 4372a45
Show file tree
Hide file tree
Showing 13 changed files with 694 additions and 527 deletions.
6 changes: 3 additions & 3 deletions platform/linux/Makefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
NES_SRC_PATH=../../src/

INCLUDE_PATHS_NES=cartridge cpu ppu .
SRCS_NES=cartridge/cartridge.c cpu/cpu6502.c ppu/ppu.c nes.c
SRCS_NES=cartridge/cartridge.c cpu/cpu6502.c ppu/ppu_framebuffer.c nes.c

# target specific
SRCS=$(addprefix $(NES_SRC_PATH), $(SRCS_NES)) ui.c
INCLUDE_PATHS=$(addprefix $(NES_SRC_PATH), $(INCLUDE_PATHS_NES))

jeg:
jeg: $(SRCS)
$(CC) $(SRCS) $(addprefix -I,$(INCLUDE_PATHS)) -O3 -o $@ `sdl2-config --cflags --libs` -Wall -pedantic $(CFLAGS)

clean:
rm jeg -rf
rm jeg -rf
5 changes: 3 additions & 2 deletions platform/linux/ui.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <SDL.h>
#include "ppu_framebuffer.h"
#include "nes.h"

// global variables
Expand Down Expand Up @@ -33,6 +34,7 @@ void update_frame(uint8_t* frame_data) {
int main(int argc, char* argv[]) {
int result;
nes_t nes_console;
ppu_t ppu;
SDL_Event event;
FILE *rom_file;
uint8_t *rom_data;
Expand Down Expand Up @@ -79,15 +81,14 @@ int main(int argc, char* argv[]) {
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 256, 240);

// init nes
ppu_init(&nes_console, &ppu, video_frame_data);
nes_init(&nes_console);
result=nes_setup_rom(&nes_console, rom_data, rom_size);
if (result) {
printf("unable to parse rom file (result:%d)\n", result);
return 6;
}

nes_setup_video(&nes_console, video_frame_data);

int quit = 0;
uint16_t key_value;

Expand Down
2 changes: 1 addition & 1 deletion platform/windows/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
NES_SRC_PATH=../../src/

INCLUDE_PATHS_NES=cartridge cpu ppu .
SRCS_NES=cartridge/cartridge.c cpu/cpu6502.c ppu/ppu.c nes.c
SRCS_NES=cartridge/cartridge.c cpu/cpu6502.c ppu/ppu_framebuffer.c nes.c

# target specific
SRCS=$(addprefix $(NES_SRC_PATH), $(SRCS_NES)) ../linux/ui.c
Expand Down
180 changes: 6 additions & 174 deletions src/nes.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static uint_fast8_t cpu6502_bus_read (void *ref, uint_fast16_t address)
return cartridge_read_prg(&nes->cartridge, address);

} else if (address<0x4000) {
return ppu_read(&nes->ppu, address);
return nes->ppu.read(nes, address);

} else if (address==0x4016) {
value=nes->controller_shift_reg[0]&1;
Expand All @@ -40,10 +40,10 @@ static void cpu6502_bus_write (void *ref, uint_fast16_t address, uint_fast8_t va
nes->ram_data[address & 0x7FF] = value;

} else if (address<0x4000) {
ppu_write(&nes->ppu, address, value);
nes->ppu.write(nes, address, value);

} else if (address==0x4014) {
ppu_dma_access(&nes->ppu, value);
nes->ppu.write(nes, address, value);

} else if (address==0x4016 && value&0x01) {
nes->controller_shift_reg[0]=nes->controller_data[0];
Expand Down Expand Up @@ -113,158 +113,6 @@ uint_fast8_t find_name_attribute_table_index(uint_fast8_t chMode, uint_fast16_t
return mirror_lookup[chMode*4+((hwAddress & 0x0FFF)>>10)];
}


static uint_fast8_t ppu_bus_read (nes_t *ptNES, uint_fast16_t hwAddress)
{
uint_fast8_t chData;
hwAddress &= 0x3FFF;

if (hwAddress <0x2000) {
chData=cartridge_read_chr(&ptNES->cartridge, hwAddress);

} else if (hwAddress<0x3F00) {
uint_fast8_t chPhysicTableIndex =
find_name_attribute_table_index(ptNES->cartridge.chMirror, hwAddress) ;
chData = ptNES->ppu.tNameAttributeTable[chPhysicTableIndex].chBuffer[hwAddress & 0x3FF];

} else if (hwAddress<0x4000) {
hwAddress &= 0x1F;
if (hwAddress>=16 && (!(hwAddress & 0x03))) {
hwAddress-=16;
}
chData = ptNES->ppu.palette[hwAddress];
}

return chData;
}

static void write_name_attribute_table(nes_t *ptNES, uint_fast16_t hwAddress, uint_fast8_t chData)
{
uint_fast8_t chPhysicTableIndex =
find_name_attribute_table_index(ptNES->cartridge.chMirror, hwAddress);
name_attribute_table_t *ptTable = &(ptNES->ppu.tNameAttributeTable[chPhysicTableIndex]);

hwAddress &= 0x3FF;

#if JEG_USE_BACKGROUND_BUFFERING == ENABLED
uint8_t chOldData = ptTable->chBuffer[hwAddress];
#endif

ptTable->chBuffer[hwAddress] = chData;

#if JEG_USE_BACKGROUND_BUFFERING == ENABLED
if (chOldData == chData) {
return ;
}

ptTable->bRequestRefresh = true;
//! update dirty matrix
do {
if (hwAddress < 32 * 30) {
uint_fast32_t wMask = _BV(hwAddress & 0x1F);

//! update nametable dirty matrix directly
ptTable->wDirtyMatrix[hwAddress>>5] |= wMask;

} else {
//! addressing attribute table, update name table dirty matrix indirectly
hwAddress -= 32 * 30;

/*! \note Each byte controls the palette of a 32x32 pixel or 4x4 tile part of
the nametable and is divided into four 2-bit areas. Each area covers
16x16 pixels or 2x2 tiles, the size of a [?] block in Super Mario Bros.
Given palette numbers topleft, topright, bottomleft, bottomright,
each in the range 0 to 3, the value of the byte is
2xx0 2xx1 2xx2 2xx3 2xx4 2xx5 2xx6 2xx7
,-------+-------+-------+-------+-------+-------+-------+-------.
| 0 . 1 | . | . | . | . | . | . | . |
2xC0:| - + - | - + - | - + - | - + - | - + - | - + - | - + - | - + - |
| 2 . 3 | . | . | . | . | . | . | . |
+-------+-------+-------+-------+-------+-------+-------+-------+
| . | . | . | . | . | . | . | . |
2xC8:| - + - | - + - | - + - | - + - | - + - | - + - | - + - | - + - |
| . | . | . | . | . | . | . | . |
+-------+-------+-------+-------+-------+-------+-------+-------+
| . | . | . | . | . | . | . | . |
2xD0:| - + - | - + - | - + - | - + - | - + - | - + - | - + - | - + - |
| . | . | . | . | . | . | . | . |
+-------+-------+-------+-------+-------+-------+-------+-------+
| . | . | . | . | . | . | . | . |
2xD8:| - + - | - + - | - + - | - + - | - + - | - + - | - + - | - + - |
| . | . | . | . | . | . | . | . |
+-------+-------+-------+-------+-------+-------+-------+-------+
| . | . | . | . | . | . | . | . |
2xE0:| - + - | - + - | - + - | - + - | - + - | - + - | - + - | - + - |
| . | . | . | . | . | . | . | . |
+-------+-------+-------+-------+-------+-------+-------+-------+
| . | . | . | . | . | . | . | . |
2xE8:| - + - | - + - | - + - | - + - | - + - | - + - | - + - | - + - |
| . | . | . | . | . | . | . | . |
+-------+-------+-------+-------+-------+-------+-------+-------+
| . | . | . | . | . | . | . | . |
2xF0:| - + - | - + - | - + - | - + - | - + - | - + - | - + - | - + - |
| . | . | . | . | . | . | . | . |
+-------+-------+-------+-------+-------+-------+-------+-------+
2xF8:| . | . | . | . | . | . | . | . |
`-------+-------+-------+-------+-------+-------+-------+-------'
*/

uint_fast8_t chTileY = (hwAddress >> 3) * 4;
uint_fast8_t chTileX = (hwAddress & 0x07) * 4;

const struct {
uint_fast8_t chX;
uint_fast8_t chY;
} c_OffSite[] = {
{0,0},
{2,0},
{0,2},
{2,2}
};

for (uint_fast8_t chGroup = 0; chGroup < 4; chGroup++) {
if ((chOldData & 0x03) != (chData & 0x03)) {
//! current group has been affected

uint_fast8_t chY = chTileY + c_OffSite[chGroup].chY;
uint_fast8_t chX = chTileX + c_OffSite[chGroup].chX;
uint_fast32_t wMask = 0x03 << (chX);

ptTable->wDirtyMatrix[chY+1] |= wMask;
ptTable->wDirtyMatrix[chY] |= wMask;

}
chOldData >>= 2;
chData >>= 2;
}
}

} while(0);

#endif
}

static void ppu_bus_write (nes_t *ptNES, uint_fast16_t hwAddress, uint_fast8_t chData)
{
hwAddress &= 0x3FFF;

if (hwAddress<0x2000) {
cartridge_write_chr(&ptNES->cartridge, hwAddress, chData);

} else if (hwAddress<0x3F00) {
write_name_attribute_table(ptNES, hwAddress, chData);

} else if (hwAddress<0x4000) {
hwAddress &= 0x1F;
if (hwAddress>=16 && (!(hwAddress & 0x03))) {
hwAddress-=16;
}
ptNES->ppu.palette[hwAddress] = chData;
}
}

#if JEG_USE_EXTERNAL_DRAW_PIXEL_INTERFACE == ENABLED
bool nes_init(nes_t *ptNES, nes_cfg_t *ptCFG)
#else
Expand Down Expand Up @@ -324,8 +172,6 @@ void nes_init(nes_t *ptNES)
}
}
bResult = true;
#else
ppu_init(&ptNES->ppu, ptNES, ppu_bus_read, ppu_bus_write);
#endif

} while(false);
Expand Down Expand Up @@ -358,34 +204,20 @@ nes_err_t nes_setup_rom(nes_t *ptNES, uint8_t *pchData, uint_fast32_t wSize)
return tResult;
}

#if JEG_USE_EXTERNAL_DRAW_PIXEL_INTERFACE == DISABLED
void nes_setup_video(nes_t *nes, uint8_t *video_frame_data)
{
ppu_setup_video(&nes->ppu, video_frame_data);
}
#endif

void nes_reset(nes_t *nes)
void nes_reset(nes_t *nes)
{
cpu6502_reset(&nes->cpu);
ppu_reset(&nes->ppu);
nes->ppu.reset(nes);
memset(&nes->ram_data, 0, 0x800);
}

void nes_iterate_frame(nes_t *nes)
{
cpu6502_run(&nes->cpu, ppu_update(&nes->ppu));
cpu6502_run(&nes->cpu, nes->ppu.update(nes));
}

void nes_set_controller(nes_t *nes, uint8_t controller1, uint8_t controller2)
{
nes->controller_data[0] = controller1;
nes->controller_data[1] = controller2;
}

#if JEG_USE_FRAME_SYNC_UP_FLAG == ENABLED
bool nes_is_frame_ready(nes_t *ptNES)
{
return ppu_is_frame_ready(&(ptNES->ppu));
}
#endif
18 changes: 14 additions & 4 deletions src/nes.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
#ifndef NES_H
#define NES_H

#include "ppu.h"
#include "cpu6502.h"
#include "cartridge.h"
#include "common.h"
#include "jeg_cfg.h"

struct nes_t;

typedef uint_fast8_t ppu_read_func_t (struct nes_t *, uint_fast16_t);
typedef void ppu_write_func_t (struct nes_t *, uint_fast16_t, uint_fast8_t);
typedef uint_fast32_t ppu_update_func_t(struct nes_t *);
typedef void ppu_reset_func_t(struct nes_t *);


typedef struct nes_t {
cpu6502_t cpu;
ppu_t ppu;
struct {
ppu_read_func_t *read;
ppu_write_func_t *write;
ppu_update_func_t *update;
ppu_reset_func_t *reset;
void *internal;
} ppu;
cartridge_t cartridge;
uint8_t controller_data[2];
uint8_t controller_shift_reg[2];
Expand All @@ -29,8 +41,6 @@ extern void nes_init(nes_t *ptNES);
#endif
extern nes_err_t nes_setup_rom(nes_t *, uint8_t *, uint_fast32_t );

extern void nes_setup_video(nes_t *, uint8_t *);

extern void nes_reset(nes_t *);

extern void nes_iterate_frame(nes_t *); // run cpu until next complete frame
Expand Down

0 comments on commit 4372a45

Please sign in to comment.