bsnes-plus/bsnes/ui-qt/debugger/ppu/base-renderer.cpp
2018-05-07 18:21:53 +10:00

145 lines
3.8 KiB
C++

BaseRenderer::BaseRenderer()
{
customBackgroundColor = 0;
bitDepth = BitDepth::NONE;
overrideBackgroundColor = false;
}
BaseRenderer::BitDepth BaseRenderer::bitDepthForLayer(unsigned screenMode, unsigned layer) {
static const BitDepth map[8][4] = {
{ BPP2, BPP2, BPP2, BPP2},
{ BPP4, BPP4, BPP2, NONE},
{ BPP4, BPP4, NONE, NONE},
{ BPP8, BPP4, NONE, NONE},
{ BPP8, BPP2, NONE, NONE},
{ BPP4, BPP2, NONE, NONE},
{ BPP4, NONE, NONE, NONE},
{ MODE7, MODE7_EXTBG, NONE, NONE}
};
return map[screenMode & 7][layer & 3];
}
bool BaseRenderer::isMode7() const {
return bitDepth == BitDepth::MODE7 || bitDepth == BitDepth::MODE7_EXTBG;
}
unsigned BaseRenderer::bytesInbetweenTiles() const {
switch (bitDepth) {
case BitDepth::BPP8: return 64;
case BitDepth::BPP4: return 32;
case BitDepth::BPP2: return 16;
case BitDepth::MODE7: return 128;
case BitDepth::MODE7_EXTBG: return 128;
}
return 0;
}
unsigned BaseRenderer::colorsPerTile() const {
switch (bitDepth) {
case BitDepth::BPP8: return 256;
case BitDepth::BPP4: return 16;
case BitDepth::BPP2: return 4;
case BitDepth::MODE7: return 256;
case BitDepth::MODE7_EXTBG: return 256;
}
return 0;
}
void BaseRenderer::buildPalette() {
if(SNES::cartridge.loaded()) {
for(unsigned i = 0; i < 256; i++) {
palette[i] = rgbFromCgram(i);
}
}
}
void BaseRenderer::initImage(unsigned width, unsigned height)
{
QImage::Format format = QImage::Format_RGB32;
if(overrideBackgroundColor) {
if(qAlpha(customBackgroundColor) != 0xff) format = QImage::Format_ARGB32;
if(customBackgroundColor == 0) format = QImage::Format_ARGB32_Premultiplied;
}
if(image.width() != width || image.height() != height || image.format() != format) {
image = QImage(width, height, format);
}
if(overrideBackgroundColor) {
image.fill(customBackgroundColor);
} else {
image.fill(palette[0]);
}
}
void BaseRenderer::invalidateImage()
{
image = QImage();
}
void BaseRenderer::draw8pxTile(QRgb* imgBits, const unsigned wordsPerScanline, const uint8_t* tile, unsigned palOffset, bool hFlip, bool vFlip) {
uint8_t data[8];
for(unsigned py = 0; py < 8; py++) {
unsigned fpy = (vFlip == false) ? py : 7 - py;
const uint8_t *sliver = tile + fpy * 2;
switch(bitDepth) {
case BitDepth::BPP8:
data[4] = sliver[32];
data[5] = sliver[33];
data[6] = sliver[48];
data[7] = sliver[49];
//fall through
case BitDepth::BPP4:
data[2] = sliver[16];
data[3] = sliver[17];
//fall through
case BitDepth::BPP2:
data[0] = sliver[ 0];
data[1] = sliver[ 1];
}
for(unsigned px = 0; px < 8; px++) {
unsigned fpx = hFlip == false ? px : 7 - px;
uint8_t pixel = 0;
switch(bitDepth) {
case BitDepth::BPP8:
pixel |= (data[7] & (0x80 >> px)) ? 0x80 : 0;
pixel |= (data[6] & (0x80 >> px)) ? 0x40 : 0;
pixel |= (data[5] & (0x80 >> px)) ? 0x20 : 0;
pixel |= (data[4] & (0x80 >> px)) ? 0x10 : 0;
//fall through
case BitDepth::BPP4:
pixel |= (data[3] & (0x80 >> px)) ? 0x08 : 0;
pixel |= (data[2] & (0x80 >> px)) ? 0x04 : 0;
//fall through
case BitDepth::BPP2:
pixel |= (data[1] & (0x80 >> px)) ? 0x02 : 0;
pixel |= (data[0] & (0x80 >> px)) ? 0x01 : 0;
}
if (pixel != 0) {
imgBits[fpx] = palette[(palOffset + pixel) & 0xff];
}
}
imgBits += wordsPerScanline;
}
}
void BaseRenderer::drawMode7Tile(QRgb* imgBits, const unsigned wordsPerScanline, const uint8_t* tile) {
for(unsigned py = 0; py < 8; py++) {
for(unsigned px = 0; px < 8; px++) {
uint8_t pixel = *tile;
if(bitDepth == MODE7_EXTBG) pixel &= 0x7f;
if(pixel != 0) imgBits[px] = palette[pixel];
tile +=2;
}
imgBits += wordsPerScanline;
}
}