Skip to content

Commit

Permalink
Implement buffered reads to PPUDATA
Browse files Browse the repository at this point in the history
  • Loading branch information
SirBob01 committed Oct 11, 2023
1 parent 2380f94 commit 4fe986d
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 41 deletions.
25 changes: 15 additions & 10 deletions src/cpu_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,18 @@ unsigned char read_cpu_bus(cpu_bus_t *bus, address_t address) {

// Read from PPUDATA (overwrite result with value from VRAM)
if (ptr == &bus->ppu->data) {
result = read_ppu_bus(bus->ppu->bus, bus->ppu->v & 0x3FFF);
bus->ppu->v++;
bus->ppu->v += ((bus->ppu->ctrl >> 2) & 1) * 31;
address_t vram_addr = bus->ppu->v & 0x3FFF;
result = bus->buffer2007;
bus->buffer2007 = read_ppu_bus(bus->ppu->bus, vram_addr);

// Set high 2 bits from palette to io latch and apply PPU effects
if (bus->ppu->v >= 0x3F00) {
if (bus->ppu->v >= PPU_MAP_PALETTE && !is_rendering_ppu(bus->ppu)) {
address_t palette_addr = bus->ppu->v & 0x1F;
result = read_palette_ppu(bus->ppu, palette_addr);
result &= ~0xC0;
result |= bus->ppu->io_databus & 0xC0;
if (bus->ppu->mask & PPU_MASK_GREYSCALE) {
result &= 0x30;
}
}
increment_vram_address_ppu(bus->ppu);
bus->ppu->io_databus = result;
}

Expand Down Expand Up @@ -245,9 +245,14 @@ void write_cpu_bus(cpu_bus_t *bus, address_t address, unsigned char value) {

// Write to PPUDATA
if (ptr == &bus->ppu->data) {
write_ppu_bus(bus->ppu->bus, bus->ppu->v & 0x3FFF, value);
bus->ppu->v++;
bus->ppu->v += ((bus->ppu->ctrl >> 2) & 1) * 31;
if (bus->ppu->v >= PPU_MAP_PALETTE) {
address_t palette_addr = bus->ppu->v & 0x1F;
write_palette_ppu(bus->ppu, palette_addr, value);
} else {
address_t vram_addr = bus->ppu->v & 0x3FFF;
write_ppu_bus(bus->ppu->bus, vram_addr, value);
}
increment_vram_address_ppu(bus->ppu);
bus->ppu->io_databus = value;

// TODO:
Expand Down
6 changes: 6 additions & 0 deletions src/cpu_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ typedef struct {
*/
unsigned char memory[CPU_RAM_SIZE];

/**
* @brief Internal buffer for reading from PPU data register.
*
*/
unsigned char buffer2007;

/**
* @brief Pointer to the ROM.
*
Expand Down
26 changes: 24 additions & 2 deletions src/ppu.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,28 @@ void create_event_tables_ppu(ppu_t *ppu) {
}
}

unsigned char read_palette_ppu(ppu_t *ppu, unsigned char palette_index) {
unsigned char value = ppu->palette[palette_index];
if (ppu->mask & PPU_MASK_GREYSCALE) {
value &= 0x30;
}
return value;
}

void write_palette_ppu(ppu_t *ppu,
unsigned char palette_index,
unsigned char value) {
ppu->palette[palette_index] = value;
if ((palette_index & 0x3) == 0) {
ppu->palette[palette_index ^ 0x10] = value;
}
}

void increment_vram_address_ppu(ppu_t *ppu) {
ppu->v++;
ppu->v += ((ppu->ctrl >> 2) & 1) * 31;
}

void read_state_ppu(ppu_t *ppu, char *buffer, unsigned buffer_size) {
snprintf(buffer,
buffer_size,
Expand Down Expand Up @@ -247,8 +269,8 @@ void draw_dot_ppu(ppu_t *ppu) {
unsigned char color = pt0 | (pt1 << 1);

// Fetch the actual color value from the palette
address_t color_address = PPU_MAP_PALETTE | (palette << 2) | color;
unsigned char palette_byte = read_ppu_bus(ppu->bus, color_address);
unsigned char palette_index = (palette << 2) | color;
unsigned char palette_byte = read_palette_ppu(ppu, palette_index);

// Write to the color buffer
unsigned buffer_index = ppu->scanline * PPU_LINEDOTS + ppu->dot;
Expand Down
36 changes: 34 additions & 2 deletions src/ppu.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,19 @@ typedef struct {
* @brief Primary object attribute memory.
*
*/
unsigned char primary_oam[256];
unsigned char primary_oam[PPU_PRIMARY_OAM_SIZE];

/**
* @brief Secondary object attribute memory.
*
*/
unsigned char secondary_oam[32];
unsigned char secondary_oam[PPU_SECONDARY_OAM_SIZE];

/**
* @brief Internal palette memory.
*
*/
unsigned char palette[PPU_PALETTE_SIZE];

/**
* @brief Data bus for communicating with the CPU.
Expand Down Expand Up @@ -295,6 +301,32 @@ void destroy_ppu(ppu_t *ppu);
*/
void create_event_tables_ppu(ppu_t *ppu);

/**
* @brief Read from the internal palette memory.
*
* @param ppu
* @return unsigned char
*/
unsigned char read_palette_ppu(ppu_t *ppu, unsigned char palette_index);

/**
* @brief Write to the internal palette memory.
*
* @param ppu
* @param palette_index
* @param value
*/
void write_palette_ppu(ppu_t *ppu,
unsigned char palette_index,
unsigned char value);

/**
* @brief Increment the VRAM address.
*
* @param ppu
*/
void increment_vram_address_ppu(ppu_t *ppu);

/**
* @brief Read the current state of the CPU for debugging.
*
Expand Down
29 changes: 6 additions & 23 deletions src/ppu_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,15 @@ address_t mirror_address_ppu_bus(address_t address, rom_mirroring_t mirroring) {
}
}
}
} else if (address >= PPU_MAP_PALETTE && address < PPU_MAP_PALETTE_MIRROR) {
// Mirrored palette table regions
switch (address) {
case 0x3f10:
return 0x3f00;
case 0x3f14:
return 0x3f04;
case 0x3f18:
return 0x3f08;
case 0x3f1c:
return 0x3f0c;
default:
return address;
}
} else if (address >= PPU_MAP_PALETTE_MIRROR) {
} else if (address >= PPU_MAP_PALETTE) {
// Mirrored palette table regions
address_t norm = PPU_MAP_PALETTE + ((address - PPU_MAP_PALETTE) % 0x20);
switch (norm) {
case 0x3f10:
return 0x3f00;
case 0x3f14:
return 0x3f04;
case 0x3f18:
return 0x3f08;
case 0x3f1c:
return 0x3f0c;
case 0x3F10:
case 0x3F14:
case 0x3F18:
case 0x3F1C:
return norm - 0x10;
default:
return norm;
}
Expand Down
11 changes: 7 additions & 4 deletions src/ppu_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@
#include "./rom.h"

// 2C02 has a 16-bit address bus (64k)
#define PPU_RAM_SIZE 1 << 16
#define PPU_RAM_SIZE 1 << 16
#define PPU_PRIMARY_OAM_SIZE 1 << 8
#define PPU_SECONDARY_OAM_SIZE 1 << 5
#define PPU_PALETTE_SIZE 1 << 5

// PPU memory map address offsets
#define PPU_MAP_PATTERNTABLE_0 0x0000
#define PPU_MAP_PATTERNTABLE_1 0x1000
#define PPU_MAP_NAMETABLE_0 0x2000
#define PPU_MAP_NAMETABLE_1 0x2400
#define PPU_MAP_NAMETABLE_2 0x2800
#define PPU_MAP_NAMETABLE_3 0x2c00
#define PPU_MAP_NAMETABLE_3 0x2C00
#define PPU_MAP_NAMETABLE_MIRROR 0x3000
#define PPU_MAP_PALETTE 0x3f00
#define PPU_MAP_PALETTE_MIRROR 0x3f20
#define PPU_MAP_PALETTE 0x3F00
#define PPU_MAP_PALETTE_MIRROR 0x3F20

/**
* @brief PPU bus subsystem.
Expand Down

0 comments on commit 4fe986d

Please sign in to comment.