cleanup ppu class

This commit is contained in:
scawful
2024-04-26 12:05:49 -04:00
parent 89edcaa2a3
commit eca262bcc8
2 changed files with 301 additions and 298 deletions

View File

@@ -17,73 +17,73 @@ using namespace PpuRegisters;
// 0-7: mode 0-7; 8: mode 1 + l3prio; 9: mode 7 + extbg // 0-7: mode 0-7; 8: mode 1 + l3prio; 9: mode 7 + extbg
// 0-3; layers 1-4; 4: sprites; 5: nonexistent // 0-3; layers 1-4; 4: sprites; 5: nonexistent
static const int layersPerMode[10][12] = { static const int kLayersPerMode[10][12] = {
{4, 0, 1, 4, 0, 1, 4, 2, 3, 4, 2, 3}, {4, 0, 1, 4, 0, 1, 4, 2, 4, 2, 5, 5}, {4, 0, 1, 4, 0, 1, 4, 2, 3, 4, 2, 3}, {4, 0, 1, 4, 0, 1, 4, 2, 4, 2, 5, 5},
{4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5},
{4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5},
{4, 0, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5}, {4, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5, 5}, {4, 0, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5}, {4, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5, 5},
{2, 4, 0, 1, 4, 0, 1, 4, 4, 2, 5, 5}, {4, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5, 5}}; {2, 4, 0, 1, 4, 0, 1, 4, 4, 2, 5, 5}, {4, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5, 5}};
static const int prioritysPerMode[10][12] = { static const int kPrioritysPerMode[10][12] = {
{3, 1, 1, 2, 0, 0, 1, 1, 1, 0, 0, 0}, {3, 1, 1, 2, 0, 0, 1, 1, 0, 0, 5, 5}, {3, 1, 1, 2, 0, 0, 1, 1, 1, 0, 0, 0}, {3, 1, 1, 2, 0, 0, 1, 1, 0, 0, 5, 5},
{3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5},
{3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5},
{3, 1, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5}, {3, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5}, {3, 1, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5}, {3, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5},
{1, 3, 1, 1, 2, 0, 0, 1, 0, 0, 5, 5}, {3, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5, 5}}; {1, 3, 1, 1, 2, 0, 0, 1, 0, 0, 5, 5}, {3, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5, 5}};
static const int layerCountPerMode[10] = {12, 10, 8, 8, 8, 8, 6, 5, 10, 7}; static const int kLayerCountPerMode[10] = {12, 10, 8, 8, 8, 8, 6, 5, 10, 7};
static const int bitDepthsPerMode[10][4] = { static const int kBitDepthsPerMode[10][4] = {
{2, 2, 2, 2}, {4, 4, 2, 5}, {4, 4, 5, 5}, {8, 4, 5, 5}, {8, 2, 5, 5}, {2, 2, 2, 2}, {4, 4, 2, 5}, {4, 4, 5, 5}, {8, 4, 5, 5}, {8, 2, 5, 5},
{4, 2, 5, 5}, {4, 5, 5, 5}, {8, 5, 5, 5}, {4, 4, 2, 5}, {8, 7, 5, 5}}; {4, 2, 5, 5}, {4, 5, 5, 5}, {8, 5, 5, 5}, {4, 4, 2, 5}, {8, 7, 5, 5}};
static const int spriteSizes[8][2] = {{8, 16}, {8, 32}, {8, 64}, {16, 32}, static const int kSpriteSizes[8][2] = {{8, 16}, {8, 32}, {8, 64}, {16, 32},
{16, 64}, {32, 64}, {16, 32}, {16, 32}}; {16, 64}, {32, 64}, {16, 32}, {16, 32}};
void Ppu::Update() {} void Ppu::Update() {}
void Ppu::Reset() { void Ppu::Reset() {
memset(vram, 0, sizeof(vram)); memset(vram, 0, sizeof(vram));
vramPointer = 0; vram_pointer = 0;
vramIncrementOnHigh = false; vram_increment_on_high_ = false;
vramIncrement = 1; vram_increment_ = 1;
vramRemapMode = 0; vram_remap_mode_ = 0;
vramReadBuffer = 0; vram_read_buffer_ = 0;
memset(cgram, 0, sizeof(cgram)); memset(cgram, 0, sizeof(cgram));
cgramPointer = 0; cgram_pointer_ = 0;
cgramSecondWrite = false; cgram_second_write_ = false;
cgramBuffer = 0; cgram_buffer_ = 0;
memset(oam, 0, sizeof(oam)); memset(oam, 0, sizeof(oam));
memset(highOam, 0, sizeof(highOam)); memset(high_oam_, 0, sizeof(high_oam_));
oamAdr = 0; oam_adr_ = 0;
oamAdrWritten = 0; oam_adr_written_ = 0;
oamInHigh = false; oam_in_high_ = false;
oamInHighWritten = false; oam_in_high_written_ = false;
oamSecondWrite = false; oam_second_write_ = false;
oamBuffer = 0; oam_buffer_ = 0;
objPriority = false; obj_priority_ = false;
objTileAdr1 = 0; obj_tile_adr1_ = 0;
objTileAdr2 = 0; obj_tile_adr2_ = 0;
objSize = 0; obj_size_ = 0;
obj_pixel_buffer_.fill(0); obj_pixel_buffer_.fill(0);
memset(objPriorityBuffer, 0, sizeof(objPriorityBuffer)); obj_priority_buffer_.fill(0);
time_over_ = false; time_over_ = false;
range_over_ = false; range_over_ = false;
objInterlace = false; obj_interlace_ = false;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
bgLayer[i].hScroll = 0; bg_layer_[i].hScroll = 0;
bgLayer[i].vScroll = 0; bg_layer_[i].vScroll = 0;
bgLayer[i].tilemapWider = false; bg_layer_[i].tilemapWider = false;
bgLayer[i].tilemapHigher = false; bg_layer_[i].tilemapHigher = false;
bgLayer[i].tilemapAdr = 0; bg_layer_[i].tilemapAdr = 0;
bgLayer[i].tileAdr = 0; bg_layer_[i].tileAdr = 0;
bgLayer[i].bigTiles = false; bg_layer_[i].bigTiles = false;
bgLayer[i].mosaicEnabled = false; bg_layer_[i].mosaicEnabled = false;
} }
scrollPrev = 0; scroll_prev_ = 0;
scrollPrev2 = 0; scroll_prev2_ = 0;
mosaicSize = 1; mosaic_size_ = 1;
mosaicStartLine = 1; mosaic_startline_ = 1;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
layer_[i].mainScreenEnabled = false; layer_[i].mainScreenEnabled = false;
layer_[i].subScreenEnabled = false; layer_[i].subScreenEnabled = false;
@@ -113,30 +113,30 @@ void Ppu::Reset() {
clip_mode_ = 0; clip_mode_ = 0;
prevent_math_mode_ = 0; prevent_math_mode_ = 0;
add_subscreen_ = false; add_subscreen_ = false;
subtractColor = false; subtract_color_ = false;
halfColor = false; half_color_ = false;
memset(math_enabled_array_, 0, sizeof(math_enabled_array_)); memset(math_enabled_array_, 0, sizeof(math_enabled_array_));
fixedColorR = 0; fixed_color_r_ = 0;
fixedColorG = 0; fixed_color_g_ = 0;
fixedColorB = 0; fixed_color_b_ = 0;
forcedBlank = true; forced_blank_ = true;
brightness = 0; brightness = 0;
mode = 0; mode = 0;
bg3priority = false; bg3priority = false;
even_frame = false; even_frame = false;
pseudoHires = false; pseudo_hires_ = false;
overscan = false; overscan_ = false;
frameOverscan = false; frame_overscan_ = false;
interlace = false; interlace = false;
frame_interlace = false; frame_interlace = false;
directColor = false; direct_color_ = false;
hCount = 0; h_count_ = 0;
vCount = 0; v_count_ = 0;
hCountSecond = false; h_count_second_ = false;
vCountSecond = false; v_count_second_ = false;
countersLatched = false; counters_latched_ = false;
ppu1openBus = 0; ppu1_open_bus_ = 0;
ppu2openBus = 0; ppu2_open_bus_ = 0;
memset(pixelBuffer, 0, sizeof(pixelBuffer)); memset(pixelBuffer, 0, sizeof(pixelBuffer));
} }
@@ -152,7 +152,7 @@ void Ppu::RunLine(int line) {
// called for lines 1-224/239 // called for lines 1-224/239
// evaluate sprites // evaluate sprites
obj_pixel_buffer_.fill(0); obj_pixel_buffer_.fill(0);
if (!forcedBlank) EvaluateSprites(line - 1); if (!forced_blank_) EvaluateSprites(line - 1);
// actual line // actual line
if (mode == 7) CalculateMode7Starts(line); if (mode == 7) CalculateMode7Starts(line);
for (int x = 0; x < 256; x++) { for (int x = 0; x < 256; x++) {
@@ -164,7 +164,7 @@ void Ppu::HandlePixel(int x, int y) {
int r = 0, r2 = 0; int r = 0, r2 = 0;
int g = 0, g2 = 0; int g = 0, g2 = 0;
int b = 0, b2 = 0; int b = 0, b2 = 0;
if (!forcedBlank) { if (!forced_blank_) {
int mainLayer = GetPixel(x, y, false, &r, &g, &b); int mainLayer = GetPixel(x, y, false, &r, &g, &b);
bool colorWindowState = GetWindowState(5, x); bool colorWindowState = GetWindowState(5, x);
if (clip_mode_ == 3 || (clip_mode_ == 2 && colorWindowState) || if (clip_mode_ == 3 || (clip_mode_ == 2 && colorWindowState) ||
@@ -178,23 +178,23 @@ void Ppu::HandlePixel(int x, int y) {
!(prevent_math_mode_ == 3 || !(prevent_math_mode_ == 3 ||
(prevent_math_mode_ == 2 && colorWindowState) || (prevent_math_mode_ == 2 && colorWindowState) ||
(prevent_math_mode_ == 1 && !colorWindowState)); (prevent_math_mode_ == 1 && !colorWindowState));
if ((mathEnabled && add_subscreen_) || pseudoHires || mode == 5 || if ((mathEnabled && add_subscreen_) || pseudo_hires_ || mode == 5 ||
mode == 6) { mode == 6) {
secondLayer = GetPixel(x, y, true, &r2, &g2, &b2); secondLayer = GetPixel(x, y, true, &r2, &g2, &b2);
} }
// TODO: subscreen pixels can be clipped to black as well // TODO: subscreen pixels can be clipped to black as well
// TODO: math for subscreen pixels (add/sub sub to main) // TODO: math for subscreen pixels (add/sub sub to main)
if (mathEnabled) { if (mathEnabled) {
if (subtractColor) { if (subtract_color_) {
r -= (add_subscreen_ && secondLayer != 5) ? r2 : fixedColorR; r -= (add_subscreen_ && secondLayer != 5) ? r2 : fixed_color_r_;
g -= (add_subscreen_ && secondLayer != 5) ? g2 : fixedColorG; g -= (add_subscreen_ && secondLayer != 5) ? g2 : fixed_color_g_;
b -= (add_subscreen_ && secondLayer != 5) ? b2 : fixedColorB; b -= (add_subscreen_ && secondLayer != 5) ? b2 : fixed_color_b_;
} else { } else {
r += (add_subscreen_ && secondLayer != 5) ? r2 : fixedColorR; r += (add_subscreen_ && secondLayer != 5) ? r2 : fixed_color_r_;
g += (add_subscreen_ && secondLayer != 5) ? g2 : fixedColorG; g += (add_subscreen_ && secondLayer != 5) ? g2 : fixed_color_g_;
b += (add_subscreen_ && secondLayer != 5) ? b2 : fixedColorB; b += (add_subscreen_ && secondLayer != 5) ? b2 : fixed_color_b_;
} }
if (halfColor && (secondLayer != 5 || !add_subscreen_)) { if (half_color_ && (secondLayer != 5 || !add_subscreen_)) {
r >>= 1; r >>= 1;
g >>= 1; g >>= 1;
b >>= 1; b >>= 1;
@@ -206,7 +206,7 @@ void Ppu::HandlePixel(int x, int y) {
if (g < 0) g = 0; if (g < 0) g = 0;
if (b < 0) b = 0; if (b < 0) b = 0;
} }
if (!(pseudoHires || mode == 5 || mode == 6)) { if (!(pseudo_hires_ || mode == 5 || mode == 6)) {
r2 = r; r2 = r;
g2 = g; g2 = g;
b2 = b; b2 = b;
@@ -236,9 +236,9 @@ int Ppu::GetPixel(int x, int y, bool subscreen, int* r, int* g, int* b) {
actMode = mode == 7 && m7extBg ? 9 : actMode; actMode = mode == 7 && m7extBg ? 9 : actMode;
int layer = 5; int layer = 5;
int pixel = 0; int pixel = 0;
for (int i = 0; i < layerCountPerMode[actMode]; i++) { for (int i = 0; i < kLayerCountPerMode[actMode]; i++) {
int curLayer = layersPerMode[actMode][i]; int curLayer = kLayersPerMode[actMode][i];
int curPriority = prioritysPerMode[actMode][i]; int curPriority = kPrioritysPerMode[actMode][i];
bool layerActive = false; bool layerActive = false;
if (!subscreen) { if (!subscreen) {
layerActive = layer_[curLayer].mainScreenEnabled && layerActive = layer_[curLayer].mainScreenEnabled &&
@@ -254,23 +254,23 @@ int Ppu::GetPixel(int x, int y, bool subscreen, int* r, int* g, int* b) {
// bg layer // bg layer
int lx = x; int lx = x;
int ly = y; int ly = y;
if (bgLayer[curLayer].mosaicEnabled && mosaicSize > 1) { if (bg_layer_[curLayer].mosaicEnabled && mosaic_size_ > 1) {
lx -= lx % mosaicSize; lx -= lx % mosaic_size_;
ly -= (ly - mosaicStartLine) % mosaicSize; ly -= (ly - mosaic_startline_) % mosaic_size_;
} }
if (mode == 7) { if (mode == 7) {
pixel = GetPixelForMode7(lx, curLayer, curPriority); pixel = GetPixelForMode7(lx, curLayer, curPriority);
} else { } else {
lx += bgLayer[curLayer].hScroll; lx += bg_layer_[curLayer].hScroll;
if (mode == 5 || mode == 6) { if (mode == 5 || mode == 6) {
lx *= 2; lx *= 2;
lx += (subscreen || bgLayer[curLayer].mosaicEnabled) ? 0 : 1; lx += (subscreen || bg_layer_[curLayer].mosaicEnabled) ? 0 : 1;
if (interlace) { if (interlace) {
ly *= 2; ly *= 2;
ly += (even_frame || bgLayer[curLayer].mosaicEnabled) ? 0 : 1; ly += (even_frame || bg_layer_[curLayer].mosaicEnabled) ? 0 : 1;
} }
} }
ly += bgLayer[curLayer].vScroll; ly += bg_layer_[curLayer].vScroll;
if (mode == 2 || mode == 4 || mode == 6) { if (mode == 2 || mode == 4 || mode == 6) {
HandleOPT(curLayer, &lx, &ly); HandleOPT(curLayer, &lx, &ly);
} }
@@ -280,7 +280,8 @@ int Ppu::GetPixel(int x, int y, bool subscreen, int* r, int* g, int* b) {
} else { } else {
// get a pixel from the sprite buffer // get a pixel from the sprite buffer
pixel = 0; pixel = 0;
if (objPriorityBuffer[x] == curPriority) pixel = obj_pixel_buffer_[x]; if (obj_priority_buffer_[x] == curPriority)
pixel = obj_pixel_buffer_[x];
} }
} }
if (pixel > 0) { if (pixel > 0) {
@@ -288,7 +289,7 @@ int Ppu::GetPixel(int x, int y, bool subscreen, int* r, int* g, int* b) {
break; break;
} }
} }
if (directColor && layer < 4 && bitDepthsPerMode[actMode][layer] == 8) { if (direct_color_ && layer < 4 && kBitDepthsPerMode[actMode][layer] == 8) {
*r = ((pixel & 0x7) << 2) | ((pixel & 0x100) >> 7); *r = ((pixel & 0x7) << 2) | ((pixel & 0x100) >> 7);
*g = ((pixel & 0x38) >> 1) | ((pixel & 0x200) >> 8); *g = ((pixel & 0x38) >> 1) | ((pixel & 0x200) >> 8);
*b = ((pixel & 0xc0) >> 3) | ((pixel & 0x400) >> 8); *b = ((pixel & 0xc0) >> 3) | ((pixel & 0x400) >> 8);
@@ -357,9 +358,9 @@ void Ppu::HandleOPT(int layer, int* lx, int* ly) {
int y = *ly; int y = *ly;
int column = 0; int column = 0;
if (mode == 6) { if (mode == 6) {
column = ((x - (x & 0xf)) - ((bgLayer[layer].hScroll * 2) & 0xfff0)) >> 4; column = ((x - (x & 0xf)) - ((bg_layer_[layer].hScroll * 2) & 0xfff0)) >> 4;
} else { } else {
column = ((x - (x & 0x7)) - (bgLayer[layer].hScroll & 0xfff8)) >> 3; column = ((x - (x & 0x7)) - (bg_layer_[layer].hScroll & 0xfff8)) >> 3;
} }
if (column > 0) { if (column > 0) {
// fetch offset values from layer 3 tilemap // fetch offset values from layer 3 tilemap
@@ -382,36 +383,38 @@ void Ppu::HandleOPT(int layer, int* lx, int* ly) {
if (hOffset & valid) *lx = ((hOffset & 0x3f8) + (column * 8)) | (x & 0x7); if (hOffset & valid) *lx = ((hOffset & 0x3f8) + (column * 8)) | (x & 0x7);
} }
// TODO: not sure if correct for interlace // TODO: not sure if correct for interlace
if (vOffset & valid) *ly = (vOffset & 0x3ff) + (y - bgLayer[layer].vScroll); if (vOffset & valid)
*ly = (vOffset & 0x3ff) + (y - bg_layer_[layer].vScroll);
} }
} }
uint16_t Ppu::GetOffsetValue(int col, int row) { uint16_t Ppu::GetOffsetValue(int col, int row) {
int x = col * 8 + bgLayer[2].hScroll; int x = col * 8 + bg_layer_[2].hScroll;
int y = row * 8 + bgLayer[2].vScroll; int y = row * 8 + bg_layer_[2].vScroll;
int tileBits = bgLayer[2].bigTiles ? 4 : 3; int tileBits = bg_layer_[2].bigTiles ? 4 : 3;
int tileHighBit = bgLayer[2].bigTiles ? 0x200 : 0x100; int tileHighBit = bg_layer_[2].bigTiles ? 0x200 : 0x100;
uint16_t tilemapAdr = bgLayer[2].tilemapAdr + (((y >> tileBits) & 0x1f) << 5 | uint16_t tilemapAdr =
((x >> tileBits) & 0x1f)); bg_layer_[2].tilemapAdr +
if ((x & tileHighBit) && bgLayer[2].tilemapWider) tilemapAdr += 0x400; (((y >> tileBits) & 0x1f) << 5 | ((x >> tileBits) & 0x1f));
if ((y & tileHighBit) && bgLayer[2].tilemapHigher) if ((x & tileHighBit) && bg_layer_[2].tilemapWider) tilemapAdr += 0x400;
tilemapAdr += bgLayer[2].tilemapWider ? 0x800 : 0x400; if ((y & tileHighBit) && bg_layer_[2].tilemapHigher)
tilemapAdr += bg_layer_[2].tilemapWider ? 0x800 : 0x400;
return vram[tilemapAdr & 0x7fff]; return vram[tilemapAdr & 0x7fff];
} }
int Ppu::GetPixelForBgLayer(int x, int y, int layer, bool priority) { int Ppu::GetPixelForBgLayer(int x, int y, int layer, bool priority) {
// figure out address of tilemap word and read it // figure out address of tilemap word and read it
bool wideTiles = bgLayer[layer].bigTiles || mode == 5 || mode == 6; bool wideTiles = bg_layer_[layer].bigTiles || mode == 5 || mode == 6;
int tileBitsX = wideTiles ? 4 : 3; int tileBitsX = wideTiles ? 4 : 3;
int tileHighBitX = wideTiles ? 0x200 : 0x100; int tileHighBitX = wideTiles ? 0x200 : 0x100;
int tileBitsY = bgLayer[layer].bigTiles ? 4 : 3; int tileBitsY = bg_layer_[layer].bigTiles ? 4 : 3;
int tileHighBitY = bgLayer[layer].bigTiles ? 0x200 : 0x100; int tileHighBitY = bg_layer_[layer].bigTiles ? 0x200 : 0x100;
uint16_t tilemapAdr = uint16_t tilemapAdr =
bgLayer[layer].tilemapAdr + bg_layer_[layer].tilemapAdr +
(((y >> tileBitsY) & 0x1f) << 5 | ((x >> tileBitsX) & 0x1f)); (((y >> tileBitsY) & 0x1f) << 5 | ((x >> tileBitsX) & 0x1f));
if ((x & tileHighBitX) && bgLayer[layer].tilemapWider) tilemapAdr += 0x400; if ((x & tileHighBitX) && bg_layer_[layer].tilemapWider) tilemapAdr += 0x400;
if ((y & tileHighBitY) && bgLayer[layer].tilemapHigher) if ((y & tileHighBitY) && bg_layer_[layer].tilemapHigher)
tilemapAdr += bgLayer[layer].tilemapWider ? 0x800 : 0x400; tilemapAdr += bg_layer_[layer].tilemapWider ? 0x800 : 0x400;
uint16_t tile = vram[tilemapAdr & 0x7fff]; uint16_t tile = vram[tilemapAdr & 0x7fff];
// check priority, get palette // check priority, get palette
if (((bool)(tile & 0x2000)) != priority) return 0; // wrong priority if (((bool)(tile & 0x2000)) != priority) return 0; // wrong priority
@@ -424,24 +427,24 @@ int Ppu::GetPixelForBgLayer(int x, int y, int layer, bool priority) {
// if unflipped right half of tile, or flipped left half of tile // if unflipped right half of tile, or flipped left half of tile
if (((bool)(x & 8)) ^ ((bool)(tile & 0x4000))) tileNum += 1; if (((bool)(x & 8)) ^ ((bool)(tile & 0x4000))) tileNum += 1;
} }
if (bgLayer[layer].bigTiles) { if (bg_layer_[layer].bigTiles) {
// if unflipped bottom half of tile, or flipped upper half of tile // if unflipped bottom half of tile, or flipped upper half of tile
if (((bool)(y & 8)) ^ ((bool)(tile & 0x8000))) tileNum += 0x10; if (((bool)(y & 8)) ^ ((bool)(tile & 0x8000))) tileNum += 0x10;
} }
// read tiledata, ajust palette for mode 0 // read tiledata, ajust palette for mode 0
int bitDepth = bitDepthsPerMode[mode][layer]; int bitDepth = kBitDepthsPerMode[mode][layer];
if (mode == 0) paletteNum += 8 * layer; if (mode == 0) paletteNum += 8 * layer;
// plane 1 (always) // plane 1 (always)
int paletteSize = 4; int paletteSize = 4;
uint16_t plane1 = uint16_t plane1 = vram[(bg_layer_[layer].tileAdr +
vram[(bgLayer[layer].tileAdr + ((tileNum & 0x3ff) * 4 * bitDepth) + row) & ((tileNum & 0x3ff) * 4 * bitDepth) + row) &
0x7fff]; 0x7fff];
int pixel = (plane1 >> col) & 1; int pixel = (plane1 >> col) & 1;
pixel |= ((plane1 >> (8 + col)) & 1) << 1; pixel |= ((plane1 >> (8 + col)) & 1) << 1;
// plane 2 (for 4bpp, 8bpp) // plane 2 (for 4bpp, 8bpp)
if (bitDepth > 2) { if (bitDepth > 2) {
paletteSize = 16; paletteSize = 16;
uint16_t plane2 = vram[(bgLayer[layer].tileAdr + uint16_t plane2 = vram[(bg_layer_[layer].tileAdr +
((tileNum & 0x3ff) * 4 * bitDepth) + 8 + row) & ((tileNum & 0x3ff) * 4 * bitDepth) + 8 + row) &
0x7fff]; 0x7fff];
pixel |= ((plane2 >> col) & 1) << 2; pixel |= ((plane2 >> col) & 1) << 2;
@@ -450,12 +453,12 @@ int Ppu::GetPixelForBgLayer(int x, int y, int layer, bool priority) {
// plane 3 & 4 (for 8bpp) // plane 3 & 4 (for 8bpp)
if (bitDepth > 4) { if (bitDepth > 4) {
paletteSize = 256; paletteSize = 256;
uint16_t plane3 = vram[(bgLayer[layer].tileAdr + uint16_t plane3 = vram[(bg_layer_[layer].tileAdr +
((tileNum & 0x3ff) * 4 * bitDepth) + 16 + row) & ((tileNum & 0x3ff) * 4 * bitDepth) + 16 + row) &
0x7fff]; 0x7fff];
pixel |= ((plane3 >> col) & 1) << 4; pixel |= ((plane3 >> col) & 1) << 4;
pixel |= ((plane3 >> (8 + col)) & 1) << 5; pixel |= ((plane3 >> (8 + col)) & 1) << 5;
uint16_t plane4 = vram[(bgLayer[layer].tileAdr + uint16_t plane4 = vram[(bg_layer_[layer].tileAdr +
((tileNum & 0x3ff) * 4 * bitDepth) + 24 + row) & ((tileNum & 0x3ff) * 4 * bitDepth) + 24 + row) &
0x7fff]; 0x7fff];
pixel |= ((plane4 >> col) & 1) << 6; pixel |= ((plane4 >> col) & 1) << 6;
@@ -468,7 +471,7 @@ int Ppu::GetPixelForBgLayer(int x, int y, int layer, bool priority) {
void Ppu::EvaluateSprites(int line) { void Ppu::EvaluateSprites(int line) {
// TODO: rectangular sprites, wierdness with sprites at -256 // TODO: rectangular sprites, wierdness with sprites at -256
uint8_t index = objPriority ? (oamAdr & 0xfe) : 0; uint8_t index = obj_priority_ ? (oam_adr_ & 0xfe) : 0;
int spritesFound = 0; int spritesFound = 0;
int tilesFound = 0; int tilesFound = 0;
uint8_t foundSprites[32] = {}; uint8_t foundSprites[32] = {};
@@ -478,12 +481,13 @@ void Ppu::EvaluateSprites(int line) {
// check if the sprite is on this line and get the sprite size // check if the sprite is on this line and get the sprite size
uint8_t row = line - y; uint8_t row = line - y;
int spriteSize = int spriteSize =
spriteSizes[objSize][(highOam[index >> 3] >> ((index & 7) + 1)) & 1]; kSpriteSizes[obj_size_]
int spriteHeight = objInterlace ? spriteSize / 2 : spriteSize; [(high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
int spriteHeight = obj_interlace_ ? spriteSize / 2 : spriteSize;
if (row < spriteHeight) { if (row < spriteHeight) {
// in y-range, get the x location, using the high bit as well // in y-range, get the x location, using the high bit as well
int x = oam[index] & 0xff; int x = oam[index] & 0xff;
x |= ((highOam[index >> 3] >> (index & 7)) & 1) << 8; x |= ((high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
if (x > 255) x -= 512; if (x > 255) x -= 512;
// if in x-range, record // if in x-range, record
if (x > -spriteSize) { if (x > -spriteSize) {
@@ -505,13 +509,14 @@ void Ppu::EvaluateSprites(int line) {
uint8_t y = oam[index] >> 8; uint8_t y = oam[index] >> 8;
uint8_t row = line - y; uint8_t row = line - y;
int spriteSize = int spriteSize =
spriteSizes[objSize][(highOam[index >> 3] >> ((index & 7) + 1)) & 1]; kSpriteSizes[obj_size_]
[(high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
int x = oam[index] & 0xff; int x = oam[index] & 0xff;
x |= ((highOam[index >> 3] >> (index & 7)) & 1) << 8; x |= ((high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
if (x > 255) x -= 512; if (x > 255) x -= 512;
if (x > -spriteSize) { if (x > -spriteSize) {
// update row according to obj-interlace // update row according to obj-interlace
if (objInterlace) row = row * 2 + (even_frame ? 0 : 1); if (obj_interlace_) row = row * 2 + (even_frame ? 0 : 1);
// get some data for the sprite and y-flip row if needed // get some data for the sprite and y-flip row if needed
int tile = oam[index + 1] & 0xff; int tile = oam[index + 1] & 0xff;
int palette = (oam[index + 1] & 0xe00) >> 9; int palette = (oam[index + 1] & 0xe00) >> 9;
@@ -532,7 +537,7 @@ void Ppu::EvaluateSprites(int line) {
uint8_t usedTile = (((tile >> 4) + (row / 8)) << 4) | uint8_t usedTile = (((tile >> 4) + (row / 8)) << 4) |
(((tile & 0xf) + (usedCol / 8)) & 0xf); (((tile & 0xf) + (usedCol / 8)) & 0xf);
uint16_t objAdr = uint16_t objAdr =
(oam[index + 1] & 0x100) ? objTileAdr2 : objTileAdr1; (oam[index + 1] & 0x100) ? obj_tile_adr2_ : obj_tile_adr1_;
uint16_t plane1 = uint16_t plane1 =
vram[(objAdr + usedTile * 16 + (row & 0x7)) & 0x7fff]; vram[(objAdr + usedTile * 16 + (row & 0x7)) & 0x7fff];
uint16_t plane2 = uint16_t plane2 =
@@ -548,7 +553,7 @@ void Ppu::EvaluateSprites(int line) {
int screenCol = col + x + px; int screenCol = col + x + px;
if (pixel > 0 && screenCol >= 0 && screenCol < 256) { if (pixel > 0 && screenCol >= 0 && screenCol < 256) {
obj_pixel_buffer_[screenCol] = 0x80 + 16 * palette + pixel; obj_pixel_buffer_[screenCol] = 0x80 + 16 * palette + pixel;
objPriorityBuffer[screenCol] = (oam[index + 1] & 0x3000) >> 12; obj_priority_buffer_[screenCol] = (oam[index + 1] & 0x3000) >> 12;
} }
} }
} }
@@ -570,8 +575,8 @@ void Ppu::CalculateMode7Starts(int y) {
int clippedV = vScroll - yCenter; int clippedV = vScroll - yCenter;
clippedH = (clippedH & 0x2000) ? (clippedH | ~1023) : (clippedH & 1023); clippedH = (clippedH & 0x2000) ? (clippedH | ~1023) : (clippedH & 1023);
clippedV = (clippedV & 0x2000) ? (clippedV | ~1023) : (clippedV & 1023); clippedV = (clippedV & 0x2000) ? (clippedV | ~1023) : (clippedV & 1023);
if (bgLayer[0].mosaicEnabled && mosaicSize > 1) { if (bg_layer_[0].mosaicEnabled && mosaic_size_ > 1) {
y -= (y - mosaicStartLine) % mosaicSize; y -= (y - mosaic_startline_) % mosaic_size_;
} }
uint8_t ry = m7yFlip ? 255 - y : y; uint8_t ry = m7yFlip ? 255 - y : y;
m7startX = (((m7matrix[0] * clippedH) & ~63) + ((m7matrix[1] * ry) & ~63) + m7startX = (((m7matrix[0] * clippedH) & ~63) + ((m7matrix[1] * ry) & ~63) +
@@ -582,10 +587,10 @@ void Ppu::CalculateMode7Starts(int y) {
void Ppu::HandleVblank() { void Ppu::HandleVblank() {
// called either right after CheckOverscan at (0,225), or at (0,240) // called either right after CheckOverscan at (0,225), or at (0,240)
if (!forcedBlank) { if (!forced_blank_) {
oamAdr = oamAdrWritten; oam_adr_ = oam_adr_written_;
oamInHigh = oamInHighWritten; oam_in_high_ = oam_in_high_written_;
oamSecondWrite = false; oam_second_write_ = false;
} }
frame_interlace = interlace; // set if we have a interlaced frame frame_interlace = interlace; // set if we have a interlaced frame
} }
@@ -610,14 +615,14 @@ uint8_t Ppu::Read(uint8_t adr, bool latch) {
case 0x0a: case 0x0a:
case 0x1a: case 0x1a:
case 0x2a: { case 0x2a: {
return ppu1openBus; return ppu1_open_bus_;
} }
case 0x34: case 0x34:
case 0x35: case 0x35:
case 0x36: { case 0x36: {
int result = m7matrix[0] * (m7matrix[1] >> 8); int result = m7matrix[0] * (m7matrix[1] >> 8);
ppu1openBus = (result >> (8 * (adr - 0x34))) & 0xff; ppu1_open_bus_ = (result >> (8 * (adr - 0x34))) & 0xff;
return ppu1openBus; return ppu1_open_bus_;
} }
case 0x37: { case 0x37: {
// TODO: only when ppulatch is set // TODO: only when ppulatch is set
@@ -628,95 +633,95 @@ uint8_t Ppu::Read(uint8_t adr, bool latch) {
} }
case 0x38: { case 0x38: {
uint8_t ret = 0; uint8_t ret = 0;
if (oamInHigh) { if (oam_in_high_) {
ret = highOam[((oamAdr & 0xf) << 1) | oamSecondWrite]; ret = high_oam_[((oam_adr_ & 0xf) << 1) | oam_second_write_];
if (oamSecondWrite) { if (oam_second_write_) {
oamAdr++; oam_adr_++;
if (oamAdr == 0) oamInHigh = false; if (oam_adr_ == 0) oam_in_high_ = false;
} }
} else { } else {
if (!oamSecondWrite) { if (!oam_second_write_) {
ret = oam[oamAdr] & 0xff; ret = oam[oam_adr_] & 0xff;
} else { } else {
ret = oam[oamAdr++] >> 8; ret = oam[oam_adr_++] >> 8;
if (oamAdr == 0) oamInHigh = true; if (oam_adr_ == 0) oam_in_high_ = true;
} }
} }
oamSecondWrite = !oamSecondWrite; oam_second_write_ = !oam_second_write_;
ppu1openBus = ret; ppu1_open_bus_ = ret;
return ret; return ret;
} }
case 0x39: { case 0x39: {
uint16_t val = vramReadBuffer; uint16_t val = vram_read_buffer_;
if (!vramIncrementOnHigh) { if (!vram_increment_on_high_) {
vramReadBuffer = vram[GetVramRemap() & 0x7fff]; vram_read_buffer_ = vram[GetVramRemap() & 0x7fff];
vramPointer += vramIncrement; vram_pointer += vram_increment_;
} }
ppu1openBus = val & 0xff; ppu1_open_bus_ = val & 0xff;
return val & 0xff; return val & 0xff;
} }
case 0x3a: { case 0x3a: {
uint16_t val = vramReadBuffer; uint16_t val = vram_read_buffer_;
if (vramIncrementOnHigh) { if (vram_increment_on_high_) {
vramReadBuffer = vram[GetVramRemap() & 0x7fff]; vram_read_buffer_ = vram[GetVramRemap() & 0x7fff];
vramPointer += vramIncrement; vram_pointer += vram_increment_;
} }
ppu1openBus = val >> 8; ppu1_open_bus_ = val >> 8;
return val >> 8; return val >> 8;
} }
case 0x3b: { case 0x3b: {
uint8_t ret = 0; uint8_t ret = 0;
if (!cgramSecondWrite) { if (!cgram_second_write_) {
ret = cgram[cgramPointer] & 0xff; ret = cgram[cgram_pointer_] & 0xff;
} else { } else {
ret = ((cgram[cgramPointer++] >> 8) & 0x7f) | (ppu2openBus & 0x80); ret = ((cgram[cgram_pointer_++] >> 8) & 0x7f) | (ppu2_open_bus_ & 0x80);
} }
cgramSecondWrite = !cgramSecondWrite; cgram_second_write_ = !cgram_second_write_;
ppu2openBus = ret; ppu2_open_bus_ = ret;
return ret; return ret;
} }
case 0x3c: { case 0x3c: {
uint8_t val = 0; uint8_t val = 0;
if (hCountSecond) { if (h_count_second_) {
val = ((hCount >> 8) & 1) | (ppu2openBus & 0xfe); val = ((h_count_ >> 8) & 1) | (ppu2_open_bus_ & 0xfe);
} else { } else {
val = hCount & 0xff; val = h_count_ & 0xff;
} }
hCountSecond = !hCountSecond; h_count_second_ = !h_count_second_;
ppu2openBus = val; ppu2_open_bus_ = val;
return val; return val;
} }
case 0x3d: { case 0x3d: {
uint8_t val = 0; uint8_t val = 0;
if (vCountSecond) { if (v_count_second_) {
val = ((vCount >> 8) & 1) | (ppu2openBus & 0xfe); val = ((v_count_ >> 8) & 1) | (ppu2_open_bus_ & 0xfe);
} else { } else {
val = vCount & 0xff; val = v_count_ & 0xff;
} }
vCountSecond = !vCountSecond; v_count_second_ = !v_count_second_;
ppu2openBus = val; ppu2_open_bus_ = val;
return val; return val;
} }
case 0x3e: { case 0x3e: {
uint8_t val = 0x1; // ppu1 version (4 bit) uint8_t val = 0x1; // ppu1 version (4 bit)
val |= ppu1openBus & 0x10; val |= ppu1_open_bus_ & 0x10;
val |= range_over_ << 6; val |= range_over_ << 6;
val |= time_over_ << 7; val |= time_over_ << 7;
ppu1openBus = val; ppu1_open_bus_ = val;
return val; return val;
} }
case 0x3f: { case 0x3f: {
uint8_t val = 0x3; // ppu2 version (4 bit) uint8_t val = 0x3; // ppu2 version (4 bit)
val |= memory_.pal_timing() << 4; // ntsc/pal val |= memory_.pal_timing() << 4; // ntsc/pal
val |= ppu2openBus & 0x20; val |= ppu2_open_bus_ & 0x20;
val |= countersLatched << 6; val |= counters_latched_ << 6;
val |= even_frame << 7; val |= even_frame << 7;
if (latch) { if (latch) {
countersLatched = false; counters_latched_ = false;
hCountSecond = false; h_count_second_ = false;
vCountSecond = false; v_count_second_ = false;
} }
ppu2openBus = val; ppu2_open_bus_ = val;
return val; return val;
} }
default: { default: {
@@ -731,84 +736,84 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
// TODO: oam address reset when written on first line of vblank, (and when // TODO: oam address reset when written on first line of vblank, (and when
// forced blank is disabled?) // forced blank is disabled?)
brightness = val & 0xf; brightness = val & 0xf;
forcedBlank = val & 0x80; forced_blank_ = val & 0x80;
break; break;
} }
case 0x01: { case 0x01: {
objSize = val >> 5; obj_size_ = val >> 5;
objTileAdr1 = (val & 7) << 13; obj_tile_adr1_ = (val & 7) << 13;
objTileAdr2 = objTileAdr1 + (((val & 0x18) + 8) << 9); obj_tile_adr2_ = obj_tile_adr1_ + (((val & 0x18) + 8) << 9);
break; break;
} }
case 0x02: { case 0x02: {
oamAdr = val; oam_adr_ = val;
oamAdrWritten = oamAdr; oam_adr_written_ = oam_adr_;
oamInHigh = oamInHighWritten; oam_in_high_ = oam_in_high_written_;
oamSecondWrite = false; oam_second_write_ = false;
break; break;
} }
case 0x03: { case 0x03: {
objPriority = val & 0x80; obj_priority_ = val & 0x80;
oamInHigh = val & 1; oam_in_high_ = val & 1;
oamInHighWritten = oamInHigh; oam_in_high_written_ = oam_in_high_;
oamAdr = oamAdrWritten; oam_adr_ = oam_adr_written_;
oamSecondWrite = false; oam_second_write_ = false;
break; break;
} }
case 0x04: { case 0x04: {
if (oamInHigh) { if (oam_in_high_) {
highOam[((oamAdr & 0xf) << 1) | oamSecondWrite] = val; high_oam_[((oam_adr_ & 0xf) << 1) | oam_second_write_] = val;
if (oamSecondWrite) { if (oam_second_write_) {
oamAdr++; oam_adr_++;
if (oamAdr == 0) oamInHigh = false; if (oam_adr_ == 0) oam_in_high_ = false;
} }
} else { } else {
if (!oamSecondWrite) { if (!oam_second_write_) {
oamBuffer = val; oam_buffer_ = val;
} else { } else {
oam[oamAdr++] = (val << 8) | oamBuffer; oam[oam_adr_++] = (val << 8) | oam_buffer_;
if (oamAdr == 0) oamInHigh = true; if (oam_adr_ == 0) oam_in_high_ = true;
} }
} }
oamSecondWrite = !oamSecondWrite; oam_second_write_ = !oam_second_write_;
break; break;
} }
case 0x05: { case 0x05: {
mode = val & 0x7; mode = val & 0x7;
bg3priority = val & 0x8; bg3priority = val & 0x8;
bgLayer[0].bigTiles = val & 0x10; bg_layer_[0].bigTiles = val & 0x10;
bgLayer[1].bigTiles = val & 0x20; bg_layer_[1].bigTiles = val & 0x20;
bgLayer[2].bigTiles = val & 0x40; bg_layer_[2].bigTiles = val & 0x40;
bgLayer[3].bigTiles = val & 0x80; bg_layer_[3].bigTiles = val & 0x80;
break; break;
} }
case 0x06: { case 0x06: {
// TODO: mosaic line reset specifics // TODO: mosaic line reset specifics
bgLayer[0].mosaicEnabled = val & 0x1; bg_layer_[0].mosaicEnabled = val & 0x1;
bgLayer[1].mosaicEnabled = val & 0x2; bg_layer_[1].mosaicEnabled = val & 0x2;
bgLayer[2].mosaicEnabled = val & 0x4; bg_layer_[2].mosaicEnabled = val & 0x4;
bgLayer[3].mosaicEnabled = val & 0x8; bg_layer_[3].mosaicEnabled = val & 0x8;
mosaicSize = (val >> 4) + 1; mosaic_size_ = (val >> 4) + 1;
mosaicStartLine = memory_.v_pos(); mosaic_startline_ = memory_.v_pos();
break; break;
} }
case 0x07: case 0x07:
case 0x08: case 0x08:
case 0x09: case 0x09:
case 0x0a: { case 0x0a: {
bgLayer[adr - 7].tilemapWider = val & 0x1; bg_layer_[adr - 7].tilemapWider = val & 0x1;
bgLayer[adr - 7].tilemapHigher = val & 0x2; bg_layer_[adr - 7].tilemapHigher = val & 0x2;
bgLayer[adr - 7].tilemapAdr = (val & 0xfc) << 8; bg_layer_[adr - 7].tilemapAdr = (val & 0xfc) << 8;
break; break;
} }
case 0x0b: { case 0x0b: {
bgLayer[0].tileAdr = (val & 0xf) << 12; bg_layer_[0].tileAdr = (val & 0xf) << 12;
bgLayer[1].tileAdr = (val & 0xf0) << 8; bg_layer_[1].tileAdr = (val & 0xf0) << 8;
break; break;
} }
case 0x0c: { case 0x0c: {
bgLayer[2].tileAdr = (val & 0xf) << 12; bg_layer_[2].tileAdr = (val & 0xf) << 12;
bgLayer[3].tileAdr = (val & 0xf0) << 8; bg_layer_[3].tileAdr = (val & 0xf0) << 8;
break; break;
} }
case 0x0d: { case 0x0d: {
@@ -819,10 +824,10 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
case 0x0f: case 0x0f:
case 0x11: case 0x11:
case 0x13: { case 0x13: {
bgLayer[(adr - 0xd) / 2].hScroll = bg_layer_[(adr - 0xd) / 2].hScroll =
((val << 8) | (scrollPrev & 0xf8) | (scrollPrev2 & 0x7)) & 0x3ff; ((val << 8) | (scroll_prev_ & 0xf8) | (scroll_prev2_ & 0x7)) & 0x3ff;
scrollPrev = val; scroll_prev_ = val;
scrollPrev2 = val; scroll_prev2_ = val;
break; break;
} }
case 0x0e: { case 0x0e: {
@@ -833,43 +838,43 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
case 0x10: case 0x10:
case 0x12: case 0x12:
case 0x14: { case 0x14: {
bgLayer[(adr - 0xe) / 2].vScroll = ((val << 8) | scrollPrev) & 0x3ff; bg_layer_[(adr - 0xe) / 2].vScroll = ((val << 8) | scroll_prev_) & 0x3ff;
scrollPrev = val; scroll_prev_ = val;
break; break;
} }
case 0x15: { case 0x15: {
if ((val & 3) == 0) { if ((val & 3) == 0) {
vramIncrement = 1; vram_increment_ = 1;
} else if ((val & 3) == 1) { } else if ((val & 3) == 1) {
vramIncrement = 32; vram_increment_ = 32;
} else { } else {
vramIncrement = 128; vram_increment_ = 128;
} }
vramRemapMode = (val & 0xc) >> 2; vram_remap_mode_ = (val & 0xc) >> 2;
vramIncrementOnHigh = val & 0x80; vram_increment_on_high_ = val & 0x80;
break; break;
} }
case 0x16: { case 0x16: {
vramPointer = (vramPointer & 0xff00) | val; vram_pointer = (vram_pointer & 0xff00) | val;
vramReadBuffer = vram[GetVramRemap() & 0x7fff]; vram_read_buffer_ = vram[GetVramRemap() & 0x7fff];
break; break;
} }
case 0x17: { case 0x17: {
vramPointer = (vramPointer & 0x00ff) | (val << 8); vram_pointer = (vram_pointer & 0x00ff) | (val << 8);
vramReadBuffer = vram[GetVramRemap() & 0x7fff]; vram_read_buffer_ = vram[GetVramRemap() & 0x7fff];
break; break;
} }
case 0x18: { case 0x18: {
// TODO: vram access during rendering (also cgram and oam) // TODO: vram access during rendering (also cgram and oam)
uint16_t vramAdr = GetVramRemap(); uint16_t vramAdr = GetVramRemap();
vram[vramAdr & 0x7fff] = (vram[vramAdr & 0x7fff] & 0xff00) | val; vram[vramAdr & 0x7fff] = (vram[vramAdr & 0x7fff] & 0xff00) | val;
if (!vramIncrementOnHigh) vramPointer += vramIncrement; if (!vram_increment_on_high_) vram_pointer += vram_increment_;
break; break;
} }
case 0x19: { case 0x19: {
uint16_t vramAdr = GetVramRemap(); uint16_t vramAdr = GetVramRemap();
vram[vramAdr & 0x7fff] = (vram[vramAdr & 0x7fff] & 0x00ff) | (val << 8); vram[vramAdr & 0x7fff] = (vram[vramAdr & 0x7fff] & 0x00ff) | (val << 8);
if (vramIncrementOnHigh) vramPointer += vramIncrement; if (vram_increment_on_high_) vram_pointer += vram_increment_;
break; break;
} }
case 0x1a: { case 0x1a: {
@@ -894,17 +899,17 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
break; break;
} }
case 0x21: { case 0x21: {
cgramPointer = val; cgram_pointer_ = val;
cgramSecondWrite = false; cgram_second_write_ = false;
break; break;
} }
case 0x22: { case 0x22: {
if (!cgramSecondWrite) { if (!cgram_second_write_) {
cgramBuffer = val; cgram_buffer_ = val;
} else { } else {
cgram[cgramPointer++] = (val << 8) | cgramBuffer; cgram[cgram_pointer_++] = (val << 8) | cgram_buffer_;
} }
cgramSecondWrite = !cgramSecondWrite; cgram_second_write_ = !cgram_second_write_;
break; break;
} }
case 0x23: case 0x23:
@@ -981,31 +986,31 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
break; break;
} }
case 0x30: { case 0x30: {
directColor = val & 0x1; direct_color_ = val & 0x1;
add_subscreen_ = val & 0x2; add_subscreen_ = val & 0x2;
prevent_math_mode_ = (val & 0x30) >> 4; prevent_math_mode_ = (val & 0x30) >> 4;
clip_mode_ = (val & 0xc0) >> 6; clip_mode_ = (val & 0xc0) >> 6;
break; break;
} }
case 0x31: { case 0x31: {
subtractColor = val & 0x80; subtract_color_ = val & 0x80;
halfColor = val & 0x40; half_color_ = val & 0x40;
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
math_enabled_array_[i] = val & (1 << i); math_enabled_array_[i] = val & (1 << i);
} }
break; break;
} }
case 0x32: { case 0x32: {
if (val & 0x80) fixedColorB = val & 0x1f; if (val & 0x80) fixed_color_b_ = val & 0x1f;
if (val & 0x40) fixedColorG = val & 0x1f; if (val & 0x40) fixed_color_g_ = val & 0x1f;
if (val & 0x20) fixedColorR = val & 0x1f; if (val & 0x20) fixed_color_r_ = val & 0x1f;
break; break;
} }
case 0x33: { case 0x33: {
interlace = val & 0x1; interlace = val & 0x1;
objInterlace = val & 0x2; obj_interlace_ = val & 0x2;
overscan = val & 0x4; overscan_ = val & 0x4;
pseudoHires = val & 0x8; pseudo_hires_ = val & 0x8;
m7extBg = val & 0x40; m7extBg = val & 0x40;
break; break;
} }
@@ -1016,8 +1021,8 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
} }
uint16_t Ppu::GetVramRemap() { uint16_t Ppu::GetVramRemap() {
uint16_t adr = vramPointer; uint16_t adr = vram_pointer;
switch (vramRemapMode) { switch (vram_remap_mode_) {
case 0: case 0:
return adr; return adr;
case 1: case 1:
@@ -1031,8 +1036,8 @@ uint16_t Ppu::GetVramRemap() {
} }
void Ppu::PutPixels(uint8_t* pixels) { void Ppu::PutPixels(uint8_t* pixels) {
for (int y = 0; y < (frameOverscan ? 239 : 224); y++) { for (int y = 0; y < (frame_overscan_ ? 239 : 224); y++) {
int dest = y * 2 + (frameOverscan ? 2 : 16); int dest = y * 2 + (frame_overscan_ ? 2 : 16);
int y1 = y, y2 = y + 239; int y1 = y, y2 = y + 239;
if (!frame_interlace) { if (!frame_interlace) {
y1 = y + (even_frame ? 0 : 239); y1 = y + (even_frame ? 0 : 239);
@@ -1043,7 +1048,7 @@ void Ppu::PutPixels(uint8_t* pixels) {
} }
// clear top 2 lines, and following 14 and last 16 lines if not overscanning // clear top 2 lines, and following 14 and last 16 lines if not overscanning
memset(pixels, 0, 2048 * 2); memset(pixels, 0, 2048 * 2);
if (!frameOverscan) { if (!frame_overscan_) {
memset(pixels + (2 * 2048), 0, 2048 * 14); memset(pixels + (2 * 2048), 0, 2048 * 14);
memset(pixels + (464 * 2048), 0, 2048 * 16); memset(pixels + (464 * 2048), 0, 2048 * 16);
} }

View File

@@ -279,9 +279,9 @@ class Ppu : public SharedRom {
void HandlePixel(int x, int y); void HandlePixel(int x, int y);
void LatchHV() { void LatchHV() {
hCount = memory_.h_pos() / 4; h_count_ = memory_.h_pos() / 4;
vCount = memory_.v_pos(); v_count_ = memory_.v_pos();
countersLatched = true; counters_latched_ = true;
} }
int GetPixel(int x, int y, bool sub, int* r, int* g, int* b); int GetPixel(int x, int y, bool sub, int* r, int* g, int* b);
@@ -292,23 +292,21 @@ class Ppu : public SharedRom {
bool GetWindowState(int layer, int x); bool GetWindowState(int layer, int x);
// if we are overscanning this frame (determined at 0,225)
bool frame_overscan_ = false; bool frame_overscan_ = false;
bool overscan_ = false; bool overscan_ = false;
// settings // settings
bool forcedBlank; bool forced_blank_;
uint8_t brightness; uint8_t brightness;
uint8_t mode; uint8_t mode;
bool bg3priority; bool bg3priority;
bool even_frame; bool even_frame;
bool pseudoHires; bool pseudo_hires_;
bool overscan;
bool
frameOverscan; // if we are overscanning this frame (determined at 0,225)
bool interlace; bool interlace;
bool frame_interlace; // if we are interlacing this frame (determined at bool frame_interlace; // if we are interlacing this frame (determined at
// start vblank) // start vblank)
bool directColor; bool direct_color_;
bool CheckOverscan() { bool CheckOverscan() {
frame_overscan_ = overscan_; frame_overscan_ = overscan_;
@@ -331,61 +329,62 @@ class Ppu : public SharedRom {
const std::vector<uint8_t>& GetFrameBuffer() const { return frame_buffer_; } const std::vector<uint8_t>& GetFrameBuffer() const { return frame_buffer_; }
private: private:
bool enable_forced_blanking_ = false; int GetPixelForMode7(int x, int layer, bool priority);
int cycle_count_ = 0;
int current_scanline_ = 0;
const int cyclesPerScanline = 341; // SNES PPU has 341 cycles per scanline const int cyclesPerScanline = 341; // SNES PPU has 341 cycles per scanline
const int totalScanlines = 262; // SNES PPU has 262 scanlines per frame const int totalScanlines = 262; // SNES PPU has 262 scanlines per frame
const int visibleScanlines = 224; // SNES PPU renders 224 visible scanlines const int visibleScanlines = 224; // SNES PPU renders 224 visible scanlines
int GetPixelForMode7(int x, int layer, bool priority); bool enable_forced_blanking_ = false;
int cycle_count_ = 0;
int current_scanline_ = 0;
// vram access // vram access
uint16_t vram[0x8000]; uint16_t vram[0x8000];
uint16_t vramPointer; uint16_t vram_pointer;
bool vramIncrementOnHigh; bool vram_increment_on_high_;
uint16_t vramIncrement; uint16_t vram_increment_;
uint8_t vramRemapMode; uint8_t vram_remap_mode_;
uint16_t vramReadBuffer; uint16_t vram_read_buffer_;
// cgram access // cgram access
uint16_t cgram[0x100]; uint16_t cgram[0x100];
uint8_t cgramPointer; uint8_t cgram_pointer_;
bool cgramSecondWrite; bool cgram_second_write_;
uint8_t cgramBuffer; uint8_t cgram_buffer_;
// oam access // oam access
uint16_t oam[0x100]; uint16_t oam[0x100];
uint8_t highOam[0x20]; uint8_t high_oam_[0x20];
uint8_t oamAdr; uint8_t oam_adr_;
uint8_t oamAdrWritten; uint8_t oam_adr_written_;
bool oamInHigh; bool oam_in_high_;
bool oamInHighWritten; bool oam_in_high_written_;
bool oamSecondWrite; bool oam_second_write_;
uint8_t oamBuffer; uint8_t oam_buffer_;
// Objects / Sprites // Objects / Sprites
bool objPriority;
uint16_t objTileAdr1;
uint16_t objTileAdr2;
uint8_t objSize;
std::array<uint8_t, 256> obj_pixel_buffer_;
uint8_t objPriorityBuffer[256];
bool time_over_ = false; bool time_over_ = false;
bool range_over_ = false; bool range_over_ = false;
bool objInterlace; bool obj_interlace_;
bool obj_priority_;
uint16_t obj_tile_adr1_;
uint16_t obj_tile_adr2_;
uint8_t obj_size_;
std::array<uint8_t, 256> obj_pixel_buffer_;
std::array<uint8_t, 256> obj_priority_buffer_;
// Color Math // Color Math
uint8_t clip_mode_ = 0; uint8_t clip_mode_ = 0;
uint8_t prevent_math_mode_ = 0; uint8_t prevent_math_mode_ = 0;
bool math_enabled_array_[6] = {false, false, false, false, false, false}; bool math_enabled_array_[6] = {false, false, false, false, false, false};
bool add_subscreen_ = false; bool add_subscreen_ = false;
bool subtractColor; bool subtract_color_;
bool halfColor; bool half_color_;
uint8_t fixedColorR; uint8_t fixed_color_r_;
uint8_t fixedColorG; uint8_t fixed_color_g_;
uint8_t fixedColorB; uint8_t fixed_color_b_;
// layers // layers
Layer layer_[5]; Layer layer_[5];
@@ -414,11 +413,10 @@ class Ppu : public SharedRom {
std::array<BackgroundLayer, 4> bg_layers_; std::array<BackgroundLayer, 4> bg_layers_;
uint8_t mosaic_startline_ = 1; uint8_t mosaic_startline_ = 1;
BgLayer bgLayer[4]; BgLayer bg_layer_[4];
uint8_t scrollPrev; uint8_t scroll_prev_;
uint8_t scrollPrev2; uint8_t scroll_prev2_;
uint8_t mosaicSize; uint8_t mosaic_size_;
uint8_t mosaicStartLine;
// pixel buffer (xbgr) // pixel buffer (xbgr)
// times 2 for even and odd frame // times 2 for even and odd frame
@@ -426,13 +424,13 @@ class Ppu : public SharedRom {
uint8_t pixelOutputFormat = 0; uint8_t pixelOutputFormat = 0;
// latching // latching
uint16_t hCount; uint16_t h_count_;
uint16_t vCount; uint16_t v_count_;
bool hCountSecond; bool h_count_second_;
bool vCountSecond; bool v_count_second_;
bool countersLatched; bool counters_latched_;
uint8_t ppu1openBus; uint8_t ppu1_open_bus_;
uint8_t ppu2openBus; uint8_t ppu2_open_bus_;
uint16_t tile_data_size_; uint16_t tile_data_size_;
uint16_t vram_base_address_; uint16_t vram_base_address_;