#include "oam-viewer.moc" OamViewer *oamViewer; void OamViewer::show() { Window::show(); refresh(); } void OamViewer::refresh() { canvas->image->fill(0x000000); QList items = list->findItems("", Qt::MatchContains); for(unsigned v = 0; v < items.count(); v++) { QTreeWidgetItem *item = items[v]; unsigned i = item->data(0, Qt::UserRole).toUInt(); uint8_t d0 = SNES::memory::oam[(i << 2) + 0]; uint8_t d1 = SNES::memory::oam[(i << 2) + 1]; uint8_t d2 = SNES::memory::oam[(i << 2) + 2]; uint8_t d3 = SNES::memory::oam[(i << 2) + 3]; uint8_t d4 = SNES::memory::oam[512 + (i >> 2)]; bool x = d4 & (1 << ((i & 3) << 1)); bool size = d4 & (2 << ((i & 3) << 1)); //TODO: create method to expose ChipDebugger::property values by name unsigned width, height; switch(0 /*SNES::ppu.oam_base_size()*/) { default: case 0: width = !size ? 8 : 16; height = !size ? 8 : 16; break; case 1: width = !size ? 8 : 32; height = !size ? 8 : 32; break; case 2: width = !size ? 8 : 64; height = !size ? 8 : 64; break; case 3: width = !size ? 16 : 32; height = !size ? 16 : 32; break; case 4: width = !size ? 16 : 64; height = !size ? 16 : 64; break; case 5: width = !size ? 32 : 64; height = !size ? 32 : 64; break; case 6: width = !size ? 16 : 32; height = !size ? 32 : 64; break; case 7: width = !size ? 16 : 32; height = !size ? 32 : 32; break; } signed xpos = (x << 8) + d0; if(xpos > 256) xpos = sclip<9>(xpos); unsigned ypos = d1; unsigned character = d2; unsigned priority = (d3 >> 4) & 3; unsigned palette = (d3 >> 1) & 7; string flags; if(d3 & 0x80) flags << "V"; if(d3 & 0x40) flags << "H"; if(d3 & 0x01) flags << "N"; item->setText(1, string() << width << "x" << height); item->setText(2, string() << xpos); item->setText(3, string() << ypos); item->setText(4, string() << character); item->setText(5, string() << priority); item->setText(6, string() << palette); item->setText(7, flags); } for(unsigned i = 0; i <= 7; i++) list->resizeColumnToContents(i); canvas->update(); } void OamViewer::autoUpdate() { if(autoUpdateBox->isChecked()) refresh(); } OamViewer::OamViewer() { setObjectName("oam-viewer"); setWindowTitle("Sprite Viewer"); setGeometryString(&config().geometry.oamViewer); application.windowList.append(this); layout = new QHBoxLayout; layout->setAlignment(Qt::AlignLeft); layout->setMargin(Style::WindowMargin); layout->setSpacing(Style::WidgetSpacing); setLayout(layout); list = new QTreeWidget; list->setColumnCount(8); list->setHeaderLabels(QStringList() << "#" << "Size" << "X" << "Y" << "Char" << "Pri" << "Pal" << "Flags"); list->setAllColumnsShowFocus(true); list->setAlternatingRowColors(true); list->setRootIsDecorated(false); list->setSortingEnabled(false); layout->addWidget(list); for(unsigned i = 0; i < 128; i++) { QTreeWidgetItem *item = new QTreeWidgetItem(list); item->setData(0, Qt::UserRole, QVariant(i)); item->setTextAlignment(0, Qt::AlignHCenter); item->setTextAlignment(1, Qt::AlignHCenter); item->setTextAlignment(2, Qt::AlignRight); item->setTextAlignment(3, Qt::AlignRight); item->setTextAlignment(4, Qt::AlignRight); item->setTextAlignment(5, Qt::AlignRight); item->setTextAlignment(6, Qt::AlignRight); item->setTextAlignment(7, Qt::AlignLeft); item->setText(0, string() << i); } controlLayout = new QVBoxLayout; controlLayout->setAlignment(Qt::AlignTop); controlLayout->setSpacing(0); layout->addLayout(controlLayout); canvas = new Canvas; canvas->setFixedSize(128, 128); controlLayout->addWidget(canvas); autoUpdateBox = new QCheckBox("Auto update"); controlLayout->addWidget(autoUpdateBox); refreshButton = new QPushButton("Refresh"); controlLayout->addWidget(refreshButton); connect(refreshButton, SIGNAL(released()), this, SLOT(refresh())); } void OamViewer::Canvas::paintEvent(QPaintEvent*) { QPainter painter(this); painter.drawImage(0, 0, *image); } OamViewer::Canvas::Canvas() { image = new QImage(128, 128, QImage::Format_RGB32); image->fill(0x000000); }