cleanup ppu class
This commit is contained in:
@@ -17,73 +17,73 @@ using namespace PpuRegisters;
|
||||
// 0-7: mode 0-7; 8: mode 1 + l3prio; 9: mode 7 + extbg
|
||||
|
||||
// 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, 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},
|
||||
{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, 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},
|
||||
{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},
|
||||
{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},
|
||||
{16, 64}, {32, 64}, {16, 32}, {16, 32}};
|
||||
static const int kSpriteSizes[8][2] = {{8, 16}, {8, 32}, {8, 64}, {16, 32},
|
||||
{16, 64}, {32, 64}, {16, 32}, {16, 32}};
|
||||
|
||||
void Ppu::Update() {}
|
||||
|
||||
void Ppu::Reset() {
|
||||
memset(vram, 0, sizeof(vram));
|
||||
vramPointer = 0;
|
||||
vramIncrementOnHigh = false;
|
||||
vramIncrement = 1;
|
||||
vramRemapMode = 0;
|
||||
vramReadBuffer = 0;
|
||||
vram_pointer = 0;
|
||||
vram_increment_on_high_ = false;
|
||||
vram_increment_ = 1;
|
||||
vram_remap_mode_ = 0;
|
||||
vram_read_buffer_ = 0;
|
||||
memset(cgram, 0, sizeof(cgram));
|
||||
cgramPointer = 0;
|
||||
cgramSecondWrite = false;
|
||||
cgramBuffer = 0;
|
||||
cgram_pointer_ = 0;
|
||||
cgram_second_write_ = false;
|
||||
cgram_buffer_ = 0;
|
||||
memset(oam, 0, sizeof(oam));
|
||||
memset(highOam, 0, sizeof(highOam));
|
||||
oamAdr = 0;
|
||||
oamAdrWritten = 0;
|
||||
oamInHigh = false;
|
||||
oamInHighWritten = false;
|
||||
oamSecondWrite = false;
|
||||
oamBuffer = 0;
|
||||
objPriority = false;
|
||||
objTileAdr1 = 0;
|
||||
objTileAdr2 = 0;
|
||||
objSize = 0;
|
||||
memset(high_oam_, 0, sizeof(high_oam_));
|
||||
oam_adr_ = 0;
|
||||
oam_adr_written_ = 0;
|
||||
oam_in_high_ = false;
|
||||
oam_in_high_written_ = false;
|
||||
oam_second_write_ = false;
|
||||
oam_buffer_ = 0;
|
||||
obj_priority_ = false;
|
||||
obj_tile_adr1_ = 0;
|
||||
obj_tile_adr2_ = 0;
|
||||
obj_size_ = 0;
|
||||
obj_pixel_buffer_.fill(0);
|
||||
memset(objPriorityBuffer, 0, sizeof(objPriorityBuffer));
|
||||
obj_priority_buffer_.fill(0);
|
||||
time_over_ = false;
|
||||
range_over_ = false;
|
||||
objInterlace = false;
|
||||
obj_interlace_ = false;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
bgLayer[i].hScroll = 0;
|
||||
bgLayer[i].vScroll = 0;
|
||||
bgLayer[i].tilemapWider = false;
|
||||
bgLayer[i].tilemapHigher = false;
|
||||
bgLayer[i].tilemapAdr = 0;
|
||||
bgLayer[i].tileAdr = 0;
|
||||
bgLayer[i].bigTiles = false;
|
||||
bgLayer[i].mosaicEnabled = false;
|
||||
bg_layer_[i].hScroll = 0;
|
||||
bg_layer_[i].vScroll = 0;
|
||||
bg_layer_[i].tilemapWider = false;
|
||||
bg_layer_[i].tilemapHigher = false;
|
||||
bg_layer_[i].tilemapAdr = 0;
|
||||
bg_layer_[i].tileAdr = 0;
|
||||
bg_layer_[i].bigTiles = false;
|
||||
bg_layer_[i].mosaicEnabled = false;
|
||||
}
|
||||
scrollPrev = 0;
|
||||
scrollPrev2 = 0;
|
||||
mosaicSize = 1;
|
||||
mosaicStartLine = 1;
|
||||
scroll_prev_ = 0;
|
||||
scroll_prev2_ = 0;
|
||||
mosaic_size_ = 1;
|
||||
mosaic_startline_ = 1;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
layer_[i].mainScreenEnabled = false;
|
||||
layer_[i].subScreenEnabled = false;
|
||||
@@ -113,30 +113,30 @@ void Ppu::Reset() {
|
||||
clip_mode_ = 0;
|
||||
prevent_math_mode_ = 0;
|
||||
add_subscreen_ = false;
|
||||
subtractColor = false;
|
||||
halfColor = false;
|
||||
subtract_color_ = false;
|
||||
half_color_ = false;
|
||||
memset(math_enabled_array_, 0, sizeof(math_enabled_array_));
|
||||
fixedColorR = 0;
|
||||
fixedColorG = 0;
|
||||
fixedColorB = 0;
|
||||
forcedBlank = true;
|
||||
fixed_color_r_ = 0;
|
||||
fixed_color_g_ = 0;
|
||||
fixed_color_b_ = 0;
|
||||
forced_blank_ = true;
|
||||
brightness = 0;
|
||||
mode = 0;
|
||||
bg3priority = false;
|
||||
even_frame = false;
|
||||
pseudoHires = false;
|
||||
overscan = false;
|
||||
frameOverscan = false;
|
||||
pseudo_hires_ = false;
|
||||
overscan_ = false;
|
||||
frame_overscan_ = false;
|
||||
interlace = false;
|
||||
frame_interlace = false;
|
||||
directColor = false;
|
||||
hCount = 0;
|
||||
vCount = 0;
|
||||
hCountSecond = false;
|
||||
vCountSecond = false;
|
||||
countersLatched = false;
|
||||
ppu1openBus = 0;
|
||||
ppu2openBus = 0;
|
||||
direct_color_ = false;
|
||||
h_count_ = 0;
|
||||
v_count_ = 0;
|
||||
h_count_second_ = false;
|
||||
v_count_second_ = false;
|
||||
counters_latched_ = false;
|
||||
ppu1_open_bus_ = 0;
|
||||
ppu2_open_bus_ = 0;
|
||||
memset(pixelBuffer, 0, sizeof(pixelBuffer));
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ void Ppu::RunLine(int line) {
|
||||
// called for lines 1-224/239
|
||||
// evaluate sprites
|
||||
obj_pixel_buffer_.fill(0);
|
||||
if (!forcedBlank) EvaluateSprites(line - 1);
|
||||
if (!forced_blank_) EvaluateSprites(line - 1);
|
||||
// actual line
|
||||
if (mode == 7) CalculateMode7Starts(line);
|
||||
for (int x = 0; x < 256; x++) {
|
||||
@@ -164,7 +164,7 @@ void Ppu::HandlePixel(int x, int y) {
|
||||
int r = 0, r2 = 0;
|
||||
int g = 0, g2 = 0;
|
||||
int b = 0, b2 = 0;
|
||||
if (!forcedBlank) {
|
||||
if (!forced_blank_) {
|
||||
int mainLayer = GetPixel(x, y, false, &r, &g, &b);
|
||||
bool colorWindowState = GetWindowState(5, x);
|
||||
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_ == 2 && colorWindowState) ||
|
||||
(prevent_math_mode_ == 1 && !colorWindowState));
|
||||
if ((mathEnabled && add_subscreen_) || pseudoHires || mode == 5 ||
|
||||
if ((mathEnabled && add_subscreen_) || pseudo_hires_ || mode == 5 ||
|
||||
mode == 6) {
|
||||
secondLayer = GetPixel(x, y, true, &r2, &g2, &b2);
|
||||
}
|
||||
// TODO: subscreen pixels can be clipped to black as well
|
||||
// TODO: math for subscreen pixels (add/sub sub to main)
|
||||
if (mathEnabled) {
|
||||
if (subtractColor) {
|
||||
r -= (add_subscreen_ && secondLayer != 5) ? r2 : fixedColorR;
|
||||
g -= (add_subscreen_ && secondLayer != 5) ? g2 : fixedColorG;
|
||||
b -= (add_subscreen_ && secondLayer != 5) ? b2 : fixedColorB;
|
||||
if (subtract_color_) {
|
||||
r -= (add_subscreen_ && secondLayer != 5) ? r2 : fixed_color_r_;
|
||||
g -= (add_subscreen_ && secondLayer != 5) ? g2 : fixed_color_g_;
|
||||
b -= (add_subscreen_ && secondLayer != 5) ? b2 : fixed_color_b_;
|
||||
} else {
|
||||
r += (add_subscreen_ && secondLayer != 5) ? r2 : fixedColorR;
|
||||
g += (add_subscreen_ && secondLayer != 5) ? g2 : fixedColorG;
|
||||
b += (add_subscreen_ && secondLayer != 5) ? b2 : fixedColorB;
|
||||
r += (add_subscreen_ && secondLayer != 5) ? r2 : fixed_color_r_;
|
||||
g += (add_subscreen_ && secondLayer != 5) ? g2 : fixed_color_g_;
|
||||
b += (add_subscreen_ && secondLayer != 5) ? b2 : fixed_color_b_;
|
||||
}
|
||||
if (halfColor && (secondLayer != 5 || !add_subscreen_)) {
|
||||
if (half_color_ && (secondLayer != 5 || !add_subscreen_)) {
|
||||
r >>= 1;
|
||||
g >>= 1;
|
||||
b >>= 1;
|
||||
@@ -206,7 +206,7 @@ void Ppu::HandlePixel(int x, int y) {
|
||||
if (g < 0) g = 0;
|
||||
if (b < 0) b = 0;
|
||||
}
|
||||
if (!(pseudoHires || mode == 5 || mode == 6)) {
|
||||
if (!(pseudo_hires_ || mode == 5 || mode == 6)) {
|
||||
r2 = r;
|
||||
g2 = g;
|
||||
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;
|
||||
int layer = 5;
|
||||
int pixel = 0;
|
||||
for (int i = 0; i < layerCountPerMode[actMode]; i++) {
|
||||
int curLayer = layersPerMode[actMode][i];
|
||||
int curPriority = prioritysPerMode[actMode][i];
|
||||
for (int i = 0; i < kLayerCountPerMode[actMode]; i++) {
|
||||
int curLayer = kLayersPerMode[actMode][i];
|
||||
int curPriority = kPrioritysPerMode[actMode][i];
|
||||
bool layerActive = false;
|
||||
if (!subscreen) {
|
||||
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
|
||||
int lx = x;
|
||||
int ly = y;
|
||||
if (bgLayer[curLayer].mosaicEnabled && mosaicSize > 1) {
|
||||
lx -= lx % mosaicSize;
|
||||
ly -= (ly - mosaicStartLine) % mosaicSize;
|
||||
if (bg_layer_[curLayer].mosaicEnabled && mosaic_size_ > 1) {
|
||||
lx -= lx % mosaic_size_;
|
||||
ly -= (ly - mosaic_startline_) % mosaic_size_;
|
||||
}
|
||||
if (mode == 7) {
|
||||
pixel = GetPixelForMode7(lx, curLayer, curPriority);
|
||||
} else {
|
||||
lx += bgLayer[curLayer].hScroll;
|
||||
lx += bg_layer_[curLayer].hScroll;
|
||||
if (mode == 5 || mode == 6) {
|
||||
lx *= 2;
|
||||
lx += (subscreen || bgLayer[curLayer].mosaicEnabled) ? 0 : 1;
|
||||
lx += (subscreen || bg_layer_[curLayer].mosaicEnabled) ? 0 : 1;
|
||||
if (interlace) {
|
||||
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) {
|
||||
HandleOPT(curLayer, &lx, &ly);
|
||||
}
|
||||
@@ -280,7 +280,8 @@ int Ppu::GetPixel(int x, int y, bool subscreen, int* r, int* g, int* b) {
|
||||
} else {
|
||||
// get a pixel from the sprite buffer
|
||||
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) {
|
||||
@@ -288,7 +289,7 @@ int Ppu::GetPixel(int x, int y, bool subscreen, int* r, int* g, int* b) {
|
||||
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);
|
||||
*g = ((pixel & 0x38) >> 1) | ((pixel & 0x200) >> 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 column = 0;
|
||||
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 {
|
||||
column = ((x - (x & 0x7)) - (bgLayer[layer].hScroll & 0xfff8)) >> 3;
|
||||
column = ((x - (x & 0x7)) - (bg_layer_[layer].hScroll & 0xfff8)) >> 3;
|
||||
}
|
||||
if (column > 0) {
|
||||
// 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);
|
||||
}
|
||||
// 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) {
|
||||
int x = col * 8 + bgLayer[2].hScroll;
|
||||
int y = row * 8 + bgLayer[2].vScroll;
|
||||
int tileBits = bgLayer[2].bigTiles ? 4 : 3;
|
||||
int tileHighBit = bgLayer[2].bigTiles ? 0x200 : 0x100;
|
||||
uint16_t tilemapAdr = bgLayer[2].tilemapAdr + (((y >> tileBits) & 0x1f) << 5 |
|
||||
((x >> tileBits) & 0x1f));
|
||||
if ((x & tileHighBit) && bgLayer[2].tilemapWider) tilemapAdr += 0x400;
|
||||
if ((y & tileHighBit) && bgLayer[2].tilemapHigher)
|
||||
tilemapAdr += bgLayer[2].tilemapWider ? 0x800 : 0x400;
|
||||
int x = col * 8 + bg_layer_[2].hScroll;
|
||||
int y = row * 8 + bg_layer_[2].vScroll;
|
||||
int tileBits = bg_layer_[2].bigTiles ? 4 : 3;
|
||||
int tileHighBit = bg_layer_[2].bigTiles ? 0x200 : 0x100;
|
||||
uint16_t tilemapAdr =
|
||||
bg_layer_[2].tilemapAdr +
|
||||
(((y >> tileBits) & 0x1f) << 5 | ((x >> tileBits) & 0x1f));
|
||||
if ((x & tileHighBit) && bg_layer_[2].tilemapWider) tilemapAdr += 0x400;
|
||||
if ((y & tileHighBit) && bg_layer_[2].tilemapHigher)
|
||||
tilemapAdr += bg_layer_[2].tilemapWider ? 0x800 : 0x400;
|
||||
return vram[tilemapAdr & 0x7fff];
|
||||
}
|
||||
|
||||
int Ppu::GetPixelForBgLayer(int x, int y, int layer, bool priority) {
|
||||
// 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 tileHighBitX = wideTiles ? 0x200 : 0x100;
|
||||
int tileBitsY = bgLayer[layer].bigTiles ? 4 : 3;
|
||||
int tileHighBitY = bgLayer[layer].bigTiles ? 0x200 : 0x100;
|
||||
int tileBitsY = bg_layer_[layer].bigTiles ? 4 : 3;
|
||||
int tileHighBitY = bg_layer_[layer].bigTiles ? 0x200 : 0x100;
|
||||
uint16_t tilemapAdr =
|
||||
bgLayer[layer].tilemapAdr +
|
||||
bg_layer_[layer].tilemapAdr +
|
||||
(((y >> tileBitsY) & 0x1f) << 5 | ((x >> tileBitsX) & 0x1f));
|
||||
if ((x & tileHighBitX) && bgLayer[layer].tilemapWider) tilemapAdr += 0x400;
|
||||
if ((y & tileHighBitY) && bgLayer[layer].tilemapHigher)
|
||||
tilemapAdr += bgLayer[layer].tilemapWider ? 0x800 : 0x400;
|
||||
if ((x & tileHighBitX) && bg_layer_[layer].tilemapWider) tilemapAdr += 0x400;
|
||||
if ((y & tileHighBitY) && bg_layer_[layer].tilemapHigher)
|
||||
tilemapAdr += bg_layer_[layer].tilemapWider ? 0x800 : 0x400;
|
||||
uint16_t tile = vram[tilemapAdr & 0x7fff];
|
||||
// check priority, get palette
|
||||
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 (((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 (((bool)(y & 8)) ^ ((bool)(tile & 0x8000))) tileNum += 0x10;
|
||||
}
|
||||
// read tiledata, ajust palette for mode 0
|
||||
int bitDepth = bitDepthsPerMode[mode][layer];
|
||||
int bitDepth = kBitDepthsPerMode[mode][layer];
|
||||
if (mode == 0) paletteNum += 8 * layer;
|
||||
// plane 1 (always)
|
||||
int paletteSize = 4;
|
||||
uint16_t plane1 =
|
||||
vram[(bgLayer[layer].tileAdr + ((tileNum & 0x3ff) * 4 * bitDepth) + row) &
|
||||
0x7fff];
|
||||
uint16_t plane1 = vram[(bg_layer_[layer].tileAdr +
|
||||
((tileNum & 0x3ff) * 4 * bitDepth) + row) &
|
||||
0x7fff];
|
||||
int pixel = (plane1 >> col) & 1;
|
||||
pixel |= ((plane1 >> (8 + col)) & 1) << 1;
|
||||
// plane 2 (for 4bpp, 8bpp)
|
||||
if (bitDepth > 2) {
|
||||
paletteSize = 16;
|
||||
uint16_t plane2 = vram[(bgLayer[layer].tileAdr +
|
||||
uint16_t plane2 = vram[(bg_layer_[layer].tileAdr +
|
||||
((tileNum & 0x3ff) * 4 * bitDepth) + 8 + row) &
|
||||
0x7fff];
|
||||
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)
|
||||
if (bitDepth > 4) {
|
||||
paletteSize = 256;
|
||||
uint16_t plane3 = vram[(bgLayer[layer].tileAdr +
|
||||
uint16_t plane3 = vram[(bg_layer_[layer].tileAdr +
|
||||
((tileNum & 0x3ff) * 4 * bitDepth) + 16 + row) &
|
||||
0x7fff];
|
||||
pixel |= ((plane3 >> col) & 1) << 4;
|
||||
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) &
|
||||
0x7fff];
|
||||
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) {
|
||||
// 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 tilesFound = 0;
|
||||
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
|
||||
uint8_t row = line - y;
|
||||
int spriteSize =
|
||||
spriteSizes[objSize][(highOam[index >> 3] >> ((index & 7) + 1)) & 1];
|
||||
int spriteHeight = objInterlace ? spriteSize / 2 : spriteSize;
|
||||
kSpriteSizes[obj_size_]
|
||||
[(high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
|
||||
int spriteHeight = obj_interlace_ ? spriteSize / 2 : spriteSize;
|
||||
if (row < spriteHeight) {
|
||||
// in y-range, get the x location, using the high bit as well
|
||||
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 in x-range, record
|
||||
if (x > -spriteSize) {
|
||||
@@ -505,13 +509,14 @@ void Ppu::EvaluateSprites(int line) {
|
||||
uint8_t y = oam[index] >> 8;
|
||||
uint8_t row = line - y;
|
||||
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;
|
||||
x |= ((highOam[index >> 3] >> (index & 7)) & 1) << 8;
|
||||
x |= ((high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
|
||||
if (x > 255) x -= 512;
|
||||
if (x > -spriteSize) {
|
||||
// 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
|
||||
int tile = oam[index + 1] & 0xff;
|
||||
int palette = (oam[index + 1] & 0xe00) >> 9;
|
||||
@@ -532,7 +537,7 @@ void Ppu::EvaluateSprites(int line) {
|
||||
uint8_t usedTile = (((tile >> 4) + (row / 8)) << 4) |
|
||||
(((tile & 0xf) + (usedCol / 8)) & 0xf);
|
||||
uint16_t objAdr =
|
||||
(oam[index + 1] & 0x100) ? objTileAdr2 : objTileAdr1;
|
||||
(oam[index + 1] & 0x100) ? obj_tile_adr2_ : obj_tile_adr1_;
|
||||
uint16_t plane1 =
|
||||
vram[(objAdr + usedTile * 16 + (row & 0x7)) & 0x7fff];
|
||||
uint16_t plane2 =
|
||||
@@ -548,7 +553,7 @@ void Ppu::EvaluateSprites(int line) {
|
||||
int screenCol = col + x + px;
|
||||
if (pixel > 0 && screenCol >= 0 && screenCol < 256) {
|
||||
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;
|
||||
clippedH = (clippedH & 0x2000) ? (clippedH | ~1023) : (clippedH & 1023);
|
||||
clippedV = (clippedV & 0x2000) ? (clippedV | ~1023) : (clippedV & 1023);
|
||||
if (bgLayer[0].mosaicEnabled && mosaicSize > 1) {
|
||||
y -= (y - mosaicStartLine) % mosaicSize;
|
||||
if (bg_layer_[0].mosaicEnabled && mosaic_size_ > 1) {
|
||||
y -= (y - mosaic_startline_) % mosaic_size_;
|
||||
}
|
||||
uint8_t ry = m7yFlip ? 255 - y : y;
|
||||
m7startX = (((m7matrix[0] * clippedH) & ~63) + ((m7matrix[1] * ry) & ~63) +
|
||||
@@ -582,10 +587,10 @@ void Ppu::CalculateMode7Starts(int y) {
|
||||
|
||||
void Ppu::HandleVblank() {
|
||||
// called either right after CheckOverscan at (0,225), or at (0,240)
|
||||
if (!forcedBlank) {
|
||||
oamAdr = oamAdrWritten;
|
||||
oamInHigh = oamInHighWritten;
|
||||
oamSecondWrite = false;
|
||||
if (!forced_blank_) {
|
||||
oam_adr_ = oam_adr_written_;
|
||||
oam_in_high_ = oam_in_high_written_;
|
||||
oam_second_write_ = false;
|
||||
}
|
||||
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 0x1a:
|
||||
case 0x2a: {
|
||||
return ppu1openBus;
|
||||
return ppu1_open_bus_;
|
||||
}
|
||||
case 0x34:
|
||||
case 0x35:
|
||||
case 0x36: {
|
||||
int result = m7matrix[0] * (m7matrix[1] >> 8);
|
||||
ppu1openBus = (result >> (8 * (adr - 0x34))) & 0xff;
|
||||
return ppu1openBus;
|
||||
ppu1_open_bus_ = (result >> (8 * (adr - 0x34))) & 0xff;
|
||||
return ppu1_open_bus_;
|
||||
}
|
||||
case 0x37: {
|
||||
// TODO: only when ppulatch is set
|
||||
@@ -628,95 +633,95 @@ uint8_t Ppu::Read(uint8_t adr, bool latch) {
|
||||
}
|
||||
case 0x38: {
|
||||
uint8_t ret = 0;
|
||||
if (oamInHigh) {
|
||||
ret = highOam[((oamAdr & 0xf) << 1) | oamSecondWrite];
|
||||
if (oamSecondWrite) {
|
||||
oamAdr++;
|
||||
if (oamAdr == 0) oamInHigh = false;
|
||||
if (oam_in_high_) {
|
||||
ret = high_oam_[((oam_adr_ & 0xf) << 1) | oam_second_write_];
|
||||
if (oam_second_write_) {
|
||||
oam_adr_++;
|
||||
if (oam_adr_ == 0) oam_in_high_ = false;
|
||||
}
|
||||
} else {
|
||||
if (!oamSecondWrite) {
|
||||
ret = oam[oamAdr] & 0xff;
|
||||
if (!oam_second_write_) {
|
||||
ret = oam[oam_adr_] & 0xff;
|
||||
} else {
|
||||
ret = oam[oamAdr++] >> 8;
|
||||
if (oamAdr == 0) oamInHigh = true;
|
||||
ret = oam[oam_adr_++] >> 8;
|
||||
if (oam_adr_ == 0) oam_in_high_ = true;
|
||||
}
|
||||
}
|
||||
oamSecondWrite = !oamSecondWrite;
|
||||
ppu1openBus = ret;
|
||||
oam_second_write_ = !oam_second_write_;
|
||||
ppu1_open_bus_ = ret;
|
||||
return ret;
|
||||
}
|
||||
case 0x39: {
|
||||
uint16_t val = vramReadBuffer;
|
||||
if (!vramIncrementOnHigh) {
|
||||
vramReadBuffer = vram[GetVramRemap() & 0x7fff];
|
||||
vramPointer += vramIncrement;
|
||||
uint16_t val = vram_read_buffer_;
|
||||
if (!vram_increment_on_high_) {
|
||||
vram_read_buffer_ = vram[GetVramRemap() & 0x7fff];
|
||||
vram_pointer += vram_increment_;
|
||||
}
|
||||
ppu1openBus = val & 0xff;
|
||||
ppu1_open_bus_ = val & 0xff;
|
||||
return val & 0xff;
|
||||
}
|
||||
case 0x3a: {
|
||||
uint16_t val = vramReadBuffer;
|
||||
if (vramIncrementOnHigh) {
|
||||
vramReadBuffer = vram[GetVramRemap() & 0x7fff];
|
||||
vramPointer += vramIncrement;
|
||||
uint16_t val = vram_read_buffer_;
|
||||
if (vram_increment_on_high_) {
|
||||
vram_read_buffer_ = vram[GetVramRemap() & 0x7fff];
|
||||
vram_pointer += vram_increment_;
|
||||
}
|
||||
ppu1openBus = val >> 8;
|
||||
ppu1_open_bus_ = val >> 8;
|
||||
return val >> 8;
|
||||
}
|
||||
case 0x3b: {
|
||||
uint8_t ret = 0;
|
||||
if (!cgramSecondWrite) {
|
||||
ret = cgram[cgramPointer] & 0xff;
|
||||
if (!cgram_second_write_) {
|
||||
ret = cgram[cgram_pointer_] & 0xff;
|
||||
} else {
|
||||
ret = ((cgram[cgramPointer++] >> 8) & 0x7f) | (ppu2openBus & 0x80);
|
||||
ret = ((cgram[cgram_pointer_++] >> 8) & 0x7f) | (ppu2_open_bus_ & 0x80);
|
||||
}
|
||||
cgramSecondWrite = !cgramSecondWrite;
|
||||
ppu2openBus = ret;
|
||||
cgram_second_write_ = !cgram_second_write_;
|
||||
ppu2_open_bus_ = ret;
|
||||
return ret;
|
||||
}
|
||||
case 0x3c: {
|
||||
uint8_t val = 0;
|
||||
if (hCountSecond) {
|
||||
val = ((hCount >> 8) & 1) | (ppu2openBus & 0xfe);
|
||||
if (h_count_second_) {
|
||||
val = ((h_count_ >> 8) & 1) | (ppu2_open_bus_ & 0xfe);
|
||||
} else {
|
||||
val = hCount & 0xff;
|
||||
val = h_count_ & 0xff;
|
||||
}
|
||||
hCountSecond = !hCountSecond;
|
||||
ppu2openBus = val;
|
||||
h_count_second_ = !h_count_second_;
|
||||
ppu2_open_bus_ = val;
|
||||
return val;
|
||||
}
|
||||
case 0x3d: {
|
||||
uint8_t val = 0;
|
||||
if (vCountSecond) {
|
||||
val = ((vCount >> 8) & 1) | (ppu2openBus & 0xfe);
|
||||
if (v_count_second_) {
|
||||
val = ((v_count_ >> 8) & 1) | (ppu2_open_bus_ & 0xfe);
|
||||
} else {
|
||||
val = vCount & 0xff;
|
||||
val = v_count_ & 0xff;
|
||||
}
|
||||
vCountSecond = !vCountSecond;
|
||||
ppu2openBus = val;
|
||||
v_count_second_ = !v_count_second_;
|
||||
ppu2_open_bus_ = val;
|
||||
return val;
|
||||
}
|
||||
case 0x3e: {
|
||||
uint8_t val = 0x1; // ppu1 version (4 bit)
|
||||
val |= ppu1openBus & 0x10;
|
||||
val |= ppu1_open_bus_ & 0x10;
|
||||
val |= range_over_ << 6;
|
||||
val |= time_over_ << 7;
|
||||
ppu1openBus = val;
|
||||
ppu1_open_bus_ = val;
|
||||
return val;
|
||||
}
|
||||
case 0x3f: {
|
||||
uint8_t val = 0x3; // ppu2 version (4 bit)
|
||||
val |= memory_.pal_timing() << 4; // ntsc/pal
|
||||
val |= ppu2openBus & 0x20;
|
||||
val |= countersLatched << 6;
|
||||
val |= ppu2_open_bus_ & 0x20;
|
||||
val |= counters_latched_ << 6;
|
||||
val |= even_frame << 7;
|
||||
if (latch) {
|
||||
countersLatched = false;
|
||||
hCountSecond = false;
|
||||
vCountSecond = false;
|
||||
counters_latched_ = false;
|
||||
h_count_second_ = false;
|
||||
v_count_second_ = false;
|
||||
}
|
||||
ppu2openBus = val;
|
||||
ppu2_open_bus_ = val;
|
||||
return val;
|
||||
}
|
||||
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
|
||||
// forced blank is disabled?)
|
||||
brightness = val & 0xf;
|
||||
forcedBlank = val & 0x80;
|
||||
forced_blank_ = val & 0x80;
|
||||
break;
|
||||
}
|
||||
case 0x01: {
|
||||
objSize = val >> 5;
|
||||
objTileAdr1 = (val & 7) << 13;
|
||||
objTileAdr2 = objTileAdr1 + (((val & 0x18) + 8) << 9);
|
||||
obj_size_ = val >> 5;
|
||||
obj_tile_adr1_ = (val & 7) << 13;
|
||||
obj_tile_adr2_ = obj_tile_adr1_ + (((val & 0x18) + 8) << 9);
|
||||
break;
|
||||
}
|
||||
case 0x02: {
|
||||
oamAdr = val;
|
||||
oamAdrWritten = oamAdr;
|
||||
oamInHigh = oamInHighWritten;
|
||||
oamSecondWrite = false;
|
||||
oam_adr_ = val;
|
||||
oam_adr_written_ = oam_adr_;
|
||||
oam_in_high_ = oam_in_high_written_;
|
||||
oam_second_write_ = false;
|
||||
break;
|
||||
}
|
||||
case 0x03: {
|
||||
objPriority = val & 0x80;
|
||||
oamInHigh = val & 1;
|
||||
oamInHighWritten = oamInHigh;
|
||||
oamAdr = oamAdrWritten;
|
||||
oamSecondWrite = false;
|
||||
obj_priority_ = val & 0x80;
|
||||
oam_in_high_ = val & 1;
|
||||
oam_in_high_written_ = oam_in_high_;
|
||||
oam_adr_ = oam_adr_written_;
|
||||
oam_second_write_ = false;
|
||||
break;
|
||||
}
|
||||
case 0x04: {
|
||||
if (oamInHigh) {
|
||||
highOam[((oamAdr & 0xf) << 1) | oamSecondWrite] = val;
|
||||
if (oamSecondWrite) {
|
||||
oamAdr++;
|
||||
if (oamAdr == 0) oamInHigh = false;
|
||||
if (oam_in_high_) {
|
||||
high_oam_[((oam_adr_ & 0xf) << 1) | oam_second_write_] = val;
|
||||
if (oam_second_write_) {
|
||||
oam_adr_++;
|
||||
if (oam_adr_ == 0) oam_in_high_ = false;
|
||||
}
|
||||
} else {
|
||||
if (!oamSecondWrite) {
|
||||
oamBuffer = val;
|
||||
if (!oam_second_write_) {
|
||||
oam_buffer_ = val;
|
||||
} else {
|
||||
oam[oamAdr++] = (val << 8) | oamBuffer;
|
||||
if (oamAdr == 0) oamInHigh = true;
|
||||
oam[oam_adr_++] = (val << 8) | oam_buffer_;
|
||||
if (oam_adr_ == 0) oam_in_high_ = true;
|
||||
}
|
||||
}
|
||||
oamSecondWrite = !oamSecondWrite;
|
||||
oam_second_write_ = !oam_second_write_;
|
||||
break;
|
||||
}
|
||||
case 0x05: {
|
||||
mode = val & 0x7;
|
||||
bg3priority = val & 0x8;
|
||||
bgLayer[0].bigTiles = val & 0x10;
|
||||
bgLayer[1].bigTiles = val & 0x20;
|
||||
bgLayer[2].bigTiles = val & 0x40;
|
||||
bgLayer[3].bigTiles = val & 0x80;
|
||||
bg_layer_[0].bigTiles = val & 0x10;
|
||||
bg_layer_[1].bigTiles = val & 0x20;
|
||||
bg_layer_[2].bigTiles = val & 0x40;
|
||||
bg_layer_[3].bigTiles = val & 0x80;
|
||||
break;
|
||||
}
|
||||
case 0x06: {
|
||||
// TODO: mosaic line reset specifics
|
||||
bgLayer[0].mosaicEnabled = val & 0x1;
|
||||
bgLayer[1].mosaicEnabled = val & 0x2;
|
||||
bgLayer[2].mosaicEnabled = val & 0x4;
|
||||
bgLayer[3].mosaicEnabled = val & 0x8;
|
||||
mosaicSize = (val >> 4) + 1;
|
||||
mosaicStartLine = memory_.v_pos();
|
||||
bg_layer_[0].mosaicEnabled = val & 0x1;
|
||||
bg_layer_[1].mosaicEnabled = val & 0x2;
|
||||
bg_layer_[2].mosaicEnabled = val & 0x4;
|
||||
bg_layer_[3].mosaicEnabled = val & 0x8;
|
||||
mosaic_size_ = (val >> 4) + 1;
|
||||
mosaic_startline_ = memory_.v_pos();
|
||||
break;
|
||||
}
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a: {
|
||||
bgLayer[adr - 7].tilemapWider = val & 0x1;
|
||||
bgLayer[adr - 7].tilemapHigher = val & 0x2;
|
||||
bgLayer[adr - 7].tilemapAdr = (val & 0xfc) << 8;
|
||||
bg_layer_[adr - 7].tilemapWider = val & 0x1;
|
||||
bg_layer_[adr - 7].tilemapHigher = val & 0x2;
|
||||
bg_layer_[adr - 7].tilemapAdr = (val & 0xfc) << 8;
|
||||
break;
|
||||
}
|
||||
case 0x0b: {
|
||||
bgLayer[0].tileAdr = (val & 0xf) << 12;
|
||||
bgLayer[1].tileAdr = (val & 0xf0) << 8;
|
||||
bg_layer_[0].tileAdr = (val & 0xf) << 12;
|
||||
bg_layer_[1].tileAdr = (val & 0xf0) << 8;
|
||||
break;
|
||||
}
|
||||
case 0x0c: {
|
||||
bgLayer[2].tileAdr = (val & 0xf) << 12;
|
||||
bgLayer[3].tileAdr = (val & 0xf0) << 8;
|
||||
bg_layer_[2].tileAdr = (val & 0xf) << 12;
|
||||
bg_layer_[3].tileAdr = (val & 0xf0) << 8;
|
||||
break;
|
||||
}
|
||||
case 0x0d: {
|
||||
@@ -819,10 +824,10 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
|
||||
case 0x0f:
|
||||
case 0x11:
|
||||
case 0x13: {
|
||||
bgLayer[(adr - 0xd) / 2].hScroll =
|
||||
((val << 8) | (scrollPrev & 0xf8) | (scrollPrev2 & 0x7)) & 0x3ff;
|
||||
scrollPrev = val;
|
||||
scrollPrev2 = val;
|
||||
bg_layer_[(adr - 0xd) / 2].hScroll =
|
||||
((val << 8) | (scroll_prev_ & 0xf8) | (scroll_prev2_ & 0x7)) & 0x3ff;
|
||||
scroll_prev_ = val;
|
||||
scroll_prev2_ = val;
|
||||
break;
|
||||
}
|
||||
case 0x0e: {
|
||||
@@ -833,43 +838,43 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
|
||||
case 0x10:
|
||||
case 0x12:
|
||||
case 0x14: {
|
||||
bgLayer[(adr - 0xe) / 2].vScroll = ((val << 8) | scrollPrev) & 0x3ff;
|
||||
scrollPrev = val;
|
||||
bg_layer_[(adr - 0xe) / 2].vScroll = ((val << 8) | scroll_prev_) & 0x3ff;
|
||||
scroll_prev_ = val;
|
||||
break;
|
||||
}
|
||||
case 0x15: {
|
||||
if ((val & 3) == 0) {
|
||||
vramIncrement = 1;
|
||||
vram_increment_ = 1;
|
||||
} else if ((val & 3) == 1) {
|
||||
vramIncrement = 32;
|
||||
vram_increment_ = 32;
|
||||
} else {
|
||||
vramIncrement = 128;
|
||||
vram_increment_ = 128;
|
||||
}
|
||||
vramRemapMode = (val & 0xc) >> 2;
|
||||
vramIncrementOnHigh = val & 0x80;
|
||||
vram_remap_mode_ = (val & 0xc) >> 2;
|
||||
vram_increment_on_high_ = val & 0x80;
|
||||
break;
|
||||
}
|
||||
case 0x16: {
|
||||
vramPointer = (vramPointer & 0xff00) | val;
|
||||
vramReadBuffer = vram[GetVramRemap() & 0x7fff];
|
||||
vram_pointer = (vram_pointer & 0xff00) | val;
|
||||
vram_read_buffer_ = vram[GetVramRemap() & 0x7fff];
|
||||
break;
|
||||
}
|
||||
case 0x17: {
|
||||
vramPointer = (vramPointer & 0x00ff) | (val << 8);
|
||||
vramReadBuffer = vram[GetVramRemap() & 0x7fff];
|
||||
vram_pointer = (vram_pointer & 0x00ff) | (val << 8);
|
||||
vram_read_buffer_ = vram[GetVramRemap() & 0x7fff];
|
||||
break;
|
||||
}
|
||||
case 0x18: {
|
||||
// TODO: vram access during rendering (also cgram and oam)
|
||||
uint16_t vramAdr = GetVramRemap();
|
||||
vram[vramAdr & 0x7fff] = (vram[vramAdr & 0x7fff] & 0xff00) | val;
|
||||
if (!vramIncrementOnHigh) vramPointer += vramIncrement;
|
||||
if (!vram_increment_on_high_) vram_pointer += vram_increment_;
|
||||
break;
|
||||
}
|
||||
case 0x19: {
|
||||
uint16_t vramAdr = GetVramRemap();
|
||||
vram[vramAdr & 0x7fff] = (vram[vramAdr & 0x7fff] & 0x00ff) | (val << 8);
|
||||
if (vramIncrementOnHigh) vramPointer += vramIncrement;
|
||||
if (vram_increment_on_high_) vram_pointer += vram_increment_;
|
||||
break;
|
||||
}
|
||||
case 0x1a: {
|
||||
@@ -894,17 +899,17 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
|
||||
break;
|
||||
}
|
||||
case 0x21: {
|
||||
cgramPointer = val;
|
||||
cgramSecondWrite = false;
|
||||
cgram_pointer_ = val;
|
||||
cgram_second_write_ = false;
|
||||
break;
|
||||
}
|
||||
case 0x22: {
|
||||
if (!cgramSecondWrite) {
|
||||
cgramBuffer = val;
|
||||
if (!cgram_second_write_) {
|
||||
cgram_buffer_ = val;
|
||||
} else {
|
||||
cgram[cgramPointer++] = (val << 8) | cgramBuffer;
|
||||
cgram[cgram_pointer_++] = (val << 8) | cgram_buffer_;
|
||||
}
|
||||
cgramSecondWrite = !cgramSecondWrite;
|
||||
cgram_second_write_ = !cgram_second_write_;
|
||||
break;
|
||||
}
|
||||
case 0x23:
|
||||
@@ -981,31 +986,31 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
|
||||
break;
|
||||
}
|
||||
case 0x30: {
|
||||
directColor = val & 0x1;
|
||||
direct_color_ = val & 0x1;
|
||||
add_subscreen_ = val & 0x2;
|
||||
prevent_math_mode_ = (val & 0x30) >> 4;
|
||||
clip_mode_ = (val & 0xc0) >> 6;
|
||||
break;
|
||||
}
|
||||
case 0x31: {
|
||||
subtractColor = val & 0x80;
|
||||
halfColor = val & 0x40;
|
||||
subtract_color_ = val & 0x80;
|
||||
half_color_ = val & 0x40;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
math_enabled_array_[i] = val & (1 << i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x32: {
|
||||
if (val & 0x80) fixedColorB = val & 0x1f;
|
||||
if (val & 0x40) fixedColorG = val & 0x1f;
|
||||
if (val & 0x20) fixedColorR = val & 0x1f;
|
||||
if (val & 0x80) fixed_color_b_ = val & 0x1f;
|
||||
if (val & 0x40) fixed_color_g_ = val & 0x1f;
|
||||
if (val & 0x20) fixed_color_r_ = val & 0x1f;
|
||||
break;
|
||||
}
|
||||
case 0x33: {
|
||||
interlace = val & 0x1;
|
||||
objInterlace = val & 0x2;
|
||||
overscan = val & 0x4;
|
||||
pseudoHires = val & 0x8;
|
||||
obj_interlace_ = val & 0x2;
|
||||
overscan_ = val & 0x4;
|
||||
pseudo_hires_ = val & 0x8;
|
||||
m7extBg = val & 0x40;
|
||||
break;
|
||||
}
|
||||
@@ -1016,8 +1021,8 @@ void Ppu::Write(uint8_t adr, uint8_t val) {
|
||||
}
|
||||
|
||||
uint16_t Ppu::GetVramRemap() {
|
||||
uint16_t adr = vramPointer;
|
||||
switch (vramRemapMode) {
|
||||
uint16_t adr = vram_pointer;
|
||||
switch (vram_remap_mode_) {
|
||||
case 0:
|
||||
return adr;
|
||||
case 1:
|
||||
@@ -1031,8 +1036,8 @@ uint16_t Ppu::GetVramRemap() {
|
||||
}
|
||||
|
||||
void Ppu::PutPixels(uint8_t* pixels) {
|
||||
for (int y = 0; y < (frameOverscan ? 239 : 224); y++) {
|
||||
int dest = y * 2 + (frameOverscan ? 2 : 16);
|
||||
for (int y = 0; y < (frame_overscan_ ? 239 : 224); y++) {
|
||||
int dest = y * 2 + (frame_overscan_ ? 2 : 16);
|
||||
int y1 = y, y2 = y + 239;
|
||||
if (!frame_interlace) {
|
||||
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
|
||||
memset(pixels, 0, 2048 * 2);
|
||||
if (!frameOverscan) {
|
||||
if (!frame_overscan_) {
|
||||
memset(pixels + (2 * 2048), 0, 2048 * 14);
|
||||
memset(pixels + (464 * 2048), 0, 2048 * 16);
|
||||
}
|
||||
|
||||
@@ -279,9 +279,9 @@ class Ppu : public SharedRom {
|
||||
void HandlePixel(int x, int y);
|
||||
|
||||
void LatchHV() {
|
||||
hCount = memory_.h_pos() / 4;
|
||||
vCount = memory_.v_pos();
|
||||
countersLatched = true;
|
||||
h_count_ = memory_.h_pos() / 4;
|
||||
v_count_ = memory_.v_pos();
|
||||
counters_latched_ = true;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// if we are overscanning this frame (determined at 0,225)
|
||||
bool frame_overscan_ = false;
|
||||
bool overscan_ = false;
|
||||
|
||||
// settings
|
||||
bool forcedBlank;
|
||||
bool forced_blank_;
|
||||
uint8_t brightness;
|
||||
uint8_t mode;
|
||||
bool bg3priority;
|
||||
bool even_frame;
|
||||
bool pseudoHires;
|
||||
bool overscan;
|
||||
bool
|
||||
frameOverscan; // if we are overscanning this frame (determined at 0,225)
|
||||
bool pseudo_hires_;
|
||||
bool interlace;
|
||||
bool frame_interlace; // if we are interlacing this frame (determined at
|
||||
// start vblank)
|
||||
bool directColor;
|
||||
bool direct_color_;
|
||||
|
||||
bool CheckOverscan() {
|
||||
frame_overscan_ = overscan_;
|
||||
@@ -331,61 +329,62 @@ class Ppu : public SharedRom {
|
||||
const std::vector<uint8_t>& GetFrameBuffer() const { return frame_buffer_; }
|
||||
|
||||
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 totalScanlines = 262; // SNES PPU has 262 scanlines per frame
|
||||
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
|
||||
uint16_t vram[0x8000];
|
||||
uint16_t vramPointer;
|
||||
bool vramIncrementOnHigh;
|
||||
uint16_t vramIncrement;
|
||||
uint8_t vramRemapMode;
|
||||
uint16_t vramReadBuffer;
|
||||
uint16_t vram_pointer;
|
||||
bool vram_increment_on_high_;
|
||||
uint16_t vram_increment_;
|
||||
uint8_t vram_remap_mode_;
|
||||
uint16_t vram_read_buffer_;
|
||||
|
||||
// cgram access
|
||||
uint16_t cgram[0x100];
|
||||
uint8_t cgramPointer;
|
||||
bool cgramSecondWrite;
|
||||
uint8_t cgramBuffer;
|
||||
uint8_t cgram_pointer_;
|
||||
bool cgram_second_write_;
|
||||
uint8_t cgram_buffer_;
|
||||
|
||||
// oam access
|
||||
uint16_t oam[0x100];
|
||||
uint8_t highOam[0x20];
|
||||
uint8_t oamAdr;
|
||||
uint8_t oamAdrWritten;
|
||||
bool oamInHigh;
|
||||
bool oamInHighWritten;
|
||||
bool oamSecondWrite;
|
||||
uint8_t oamBuffer;
|
||||
uint8_t high_oam_[0x20];
|
||||
uint8_t oam_adr_;
|
||||
uint8_t oam_adr_written_;
|
||||
bool oam_in_high_;
|
||||
bool oam_in_high_written_;
|
||||
bool oam_second_write_;
|
||||
uint8_t oam_buffer_;
|
||||
|
||||
// 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 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
|
||||
uint8_t clip_mode_ = 0;
|
||||
uint8_t prevent_math_mode_ = 0;
|
||||
bool math_enabled_array_[6] = {false, false, false, false, false, false};
|
||||
bool add_subscreen_ = false;
|
||||
bool subtractColor;
|
||||
bool halfColor;
|
||||
uint8_t fixedColorR;
|
||||
uint8_t fixedColorG;
|
||||
uint8_t fixedColorB;
|
||||
bool subtract_color_;
|
||||
bool half_color_;
|
||||
uint8_t fixed_color_r_;
|
||||
uint8_t fixed_color_g_;
|
||||
uint8_t fixed_color_b_;
|
||||
|
||||
// layers
|
||||
Layer layer_[5];
|
||||
@@ -414,11 +413,10 @@ class Ppu : public SharedRom {
|
||||
std::array<BackgroundLayer, 4> bg_layers_;
|
||||
uint8_t mosaic_startline_ = 1;
|
||||
|
||||
BgLayer bgLayer[4];
|
||||
uint8_t scrollPrev;
|
||||
uint8_t scrollPrev2;
|
||||
uint8_t mosaicSize;
|
||||
uint8_t mosaicStartLine;
|
||||
BgLayer bg_layer_[4];
|
||||
uint8_t scroll_prev_;
|
||||
uint8_t scroll_prev2_;
|
||||
uint8_t mosaic_size_;
|
||||
|
||||
// pixel buffer (xbgr)
|
||||
// times 2 for even and odd frame
|
||||
@@ -426,13 +424,13 @@ class Ppu : public SharedRom {
|
||||
uint8_t pixelOutputFormat = 0;
|
||||
|
||||
// latching
|
||||
uint16_t hCount;
|
||||
uint16_t vCount;
|
||||
bool hCountSecond;
|
||||
bool vCountSecond;
|
||||
bool countersLatched;
|
||||
uint8_t ppu1openBus;
|
||||
uint8_t ppu2openBus;
|
||||
uint16_t h_count_;
|
||||
uint16_t v_count_;
|
||||
bool h_count_second_;
|
||||
bool v_count_second_;
|
||||
bool counters_latched_;
|
||||
uint8_t ppu1_open_bus_;
|
||||
uint8_t ppu2_open_bus_;
|
||||
|
||||
uint16_t tile_data_size_;
|
||||
uint16_t vram_base_address_;
|
||||
|
||||
Reference in New Issue
Block a user