#include "vram-viewer.moc" VramViewer *vramViewer; VramViewer::VramViewer() { setObjectName("vram-viewer"); setWindowTitle("Video RAM Viewer"); setGeometryString(&config().geometry.vramViewer); application.windowList.append(this); layout = new QVBoxLayout; layout->setSizeConstraint(QLayout::SetFixedSize); layout->setAlignment(Qt::AlignCenter); layout->setMargin(Style::WindowMargin); layout->setSpacing(Style::WidgetSpacing); setLayout(layout); controlLayout = new QHBoxLayout; controlLayout->setSizeConstraint(QLayout::SetMinimumSize); controlLayout->setAlignment(Qt::AlignRight); layout->addLayout(controlLayout); depth2bpp = new QRadioButton("2 BPP"); controlLayout->addWidget(depth2bpp); depth4bpp = new QRadioButton("4 BPP"); controlLayout->addWidget(depth4bpp); depth8bpp = new QRadioButton("8 BPP"); controlLayout->addWidget(depth8bpp); depthMode7 = new QRadioButton("Mode 7"); controlLayout->addWidget(depthMode7); autoUpdateBox = new QCheckBox("Auto update"); controlLayout->addWidget(autoUpdateBox); refreshButton = new QPushButton("Refresh"); controlLayout->addWidget(refreshButton); canvas = new Canvas; canvas->setFixedSize(512, 512); layout->addWidget(canvas); bpp = 2; depth2bpp->setChecked(true); connect(refreshButton, SIGNAL(released()), this, SLOT(refresh())); connect(depth2bpp, SIGNAL(pressed()), this, SLOT(setDepth2bpp())); connect(depth4bpp, SIGNAL(pressed()), this, SLOT(setDepth4bpp())); connect(depth8bpp, SIGNAL(pressed()), this, SLOT(setDepth8bpp())); connect(depthMode7, SIGNAL(pressed()), this, SLOT(setDepthMode7())); } void VramViewer::autoUpdate() { if(autoUpdateBox->isChecked()) refresh(); } void VramViewer::show() { Window::show(); refresh(); } void VramViewer::refresh() { canvas->image->fill(0x800000); if(SNES::cartridge.loaded()) { const uint8_t *source = SNES::memory::vram.data(); uint32_t *dest = (uint32_t*)canvas->image->bits(); if(bpp == 2) refresh2bpp (source, dest); if(bpp == 4) refresh4bpp (source, dest); if(bpp == 8) refresh8bpp (source, dest); if(bpp == 7) refreshMode7(source, dest); } canvas->update(); } void VramViewer::refresh2bpp(const uint8_t *source, uint32_t *dest) { for(unsigned ty = 0; ty < 64; ty++) { for(unsigned tx = 0; tx < 64; tx++) { for(unsigned py = 0; py < 8; py++) { uint8_t d0 = source[0]; uint8_t d1 = source[1]; for(unsigned px = 0; px < 8; px++) { uint8_t pixel = 0; pixel |= (d0 & (0x80 >> px)) ? 1 : 0; pixel |= (d1 & (0x80 >> px)) ? 2 : 0; pixel *= 0x55; dest[(ty * 8 + py) * 512 + (tx * 8 + px)] = (pixel << 16) + (pixel << 8) + pixel; } source += 2; } } } } void VramViewer::refresh4bpp(const uint8_t *source, uint32_t *dest) { for(unsigned ty = 0; ty < 32; ty++) { for(unsigned tx = 0; tx < 64; tx++) { for(unsigned py = 0; py < 8; py++) { uint8_t d0 = source[ 0]; uint8_t d1 = source[ 1]; uint8_t d2 = source[16]; uint8_t d3 = source[17]; for(unsigned px = 0; px < 8; px++) { uint8_t pixel = 0; pixel |= (d0 & (0x80 >> px)) ? 1 : 0; pixel |= (d1 & (0x80 >> px)) ? 2 : 0; pixel |= (d2 & (0x80 >> px)) ? 4 : 0; pixel |= (d3 & (0x80 >> px)) ? 8 : 0; pixel *= 0x11; dest[(ty * 8 + py) * 512 + (tx * 8 + px)] = (pixel << 16) + (pixel << 8) + pixel; } source += 2; } source += 16; } } } void VramViewer::refresh8bpp(const uint8_t *source, uint32_t *dest) { for(unsigned ty = 0; ty < 16; ty++) { for(unsigned tx = 0; tx < 64; tx++) { for(unsigned py = 0; py < 8; py++) { uint8_t d0 = source[ 0]; uint8_t d1 = source[ 1]; uint8_t d2 = source[16]; uint8_t d3 = source[17]; uint8_t d4 = source[32]; uint8_t d5 = source[33]; uint8_t d6 = source[48]; uint8_t d7 = source[49]; for(unsigned px = 0; px < 8; px++) { uint8_t pixel = 0; pixel |= (d0 & (0x80 >> px)) ? 0x01 : 0; pixel |= (d1 & (0x80 >> px)) ? 0x02 : 0; pixel |= (d2 & (0x80 >> px)) ? 0x04 : 0; pixel |= (d3 & (0x80 >> px)) ? 0x08 : 0; pixel |= (d4 & (0x80 >> px)) ? 0x10 : 0; pixel |= (d5 & (0x80 >> px)) ? 0x20 : 0; pixel |= (d6 & (0x80 >> px)) ? 0x40 : 0; pixel |= (d7 & (0x80 >> px)) ? 0x80 : 0; dest[(ty * 8 + py) * 512 + (tx * 8 + px)] = (pixel << 16) + (pixel << 8) + pixel; } source += 2; } source += 48; } } } void VramViewer::refreshMode7(const uint8_t *source, uint32_t *dest) { for(unsigned ty = 0; ty < 16; ty++) { for(unsigned tx = 0; tx < 16; tx++) { for(unsigned py = 0; py < 8; py++) { for(unsigned px = 0; px < 8; px++) { uint8_t pixel = source[1]; dest[(ty * 8 + py) * 512 + (tx * 8 + px)] = (pixel << 16) + (pixel << 8) + pixel; source += 2; } } } } } void VramViewer::setDepth2bpp() { bpp = 2; refresh(); } void VramViewer::setDepth4bpp() { bpp = 4; refresh(); } void VramViewer::setDepth8bpp() { bpp = 8; refresh(); } void VramViewer::setDepthMode7() { bpp = 7; refresh(); } void VramViewer::Canvas::paintEvent(QPaintEvent*) { QPainter painter(this); painter.drawImage(0, 0, *image); } VramViewer::Canvas::Canvas() { image = new QImage(512, 512, QImage::Format_RGB32); image->fill(0x800000); }