diff --git a/TODO-SDL b/TODO-SDL index 83f91b5c..335f41c3 100644 --- a/TODO-SDL +++ b/TODO-SDL @@ -43,7 +43,7 @@ RAM Watch Window | NO | YES Memory Watch Window | NO | NO | TAS Editor | NO | NO | 6502 Debugger Window | YES | YES | -PPU Viewer | NO | NO | +PPU Viewer | YES | NO | Name Table Viewer | NO | NO | Memory Hex Editor | YES | YES | Trace Logger | YES | NO | diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 41036c60..fcf5be14 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -441,6 +441,7 @@ set(SRC_DRIVERS_SDL ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TraceLogger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AboutWindow.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/fceuWrapper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ppuViewer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/config.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/input.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/nes_shm.cpp diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index d4f7e723..490566c4 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -33,6 +33,7 @@ #include "Qt/ConsoleVideoConf.h" #include "Qt/AboutWindow.h" #include "Qt/fceuWrapper.h" +#include "Qt/ppuViewer.h" #include "Qt/keyscan.h" #include "Qt/nes_shm.h" @@ -501,6 +502,14 @@ void consoleWin_t::createMainMenu(void) debugMenu->addAction(hexEditAct); + // Debug -> PPU Viewer + ppuViewAct = new QAction(tr("PPU Viewer..."), this); + //ppuViewAct->setShortcut( QKeySequence(tr("Shift+F7"))); + ppuViewAct->setStatusTip(tr("Open PPU Viewer")); + connect(ppuViewAct, SIGNAL(triggered()), this, SLOT(openPPUViewer(void)) ); + + debugMenu->addAction(ppuViewAct); + // Debug -> Trace Logger traceLogAct = new QAction(tr("Trace Logger..."), this); //traceLogAct->setShortcut( QKeySequence(tr("Shift+F7"))); @@ -1021,6 +1030,13 @@ void consoleWin_t::openHexEditor(void) hexEditWin->show(); } +void consoleWin_t::openPPUViewer(void) +{ + //printf("Open GUI PPU Viewer Window\n"); + + openPPUViewWindow(this); +} + void consoleWin_t::openCodeDataLogger(void) { CodeDataLoggerDialog_t *cdlWin; diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index a8d74264..7699b3ed 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -93,6 +93,7 @@ class consoleWin_t : public QMainWindow QAction *codeDataLogAct; QAction *traceLogAct; QAction *hexEditAct; + QAction *ppuViewAct; QAction *openMovAct; QAction *stopMovAct; QAction *recMovAct; @@ -162,6 +163,7 @@ class consoleWin_t : public QMainWindow void fdsSwitchDisk(void); void fdsEjectDisk(void); void fdsLoadBiosFile(void); + void openPPUViewer(void); void openCheats(void); void openMovie(void); void stopMovie(void); diff --git a/src/drivers/Qt/ppuViewer.cpp b/src/drivers/Qt/ppuViewer.cpp new file mode 100644 index 00000000..8ba27639 --- /dev/null +++ b/src/drivers/Qt/ppuViewer.cpp @@ -0,0 +1,609 @@ +// ppuViewer.cpp +// +#include +#include + +#include +#include +#include +#include + +#include "../../types.h" +#include "../../fceu.h" +#include "../../cart.h" +#include "../../ppu.h" +#include "../../debug.h" +#include "../../palette.h" + +#include "Qt/ppuViewer.h" +#include "Qt/main.h" +#include "Qt/dface.h" +#include "Qt/input.h" +#include "Qt/config.h" +#include "Qt/fceuWrapper.h" + +#define PATTERNWIDTH 128 +#define PATTERNHEIGHT 128 +#define PATTERNBITWIDTH PATTERNWIDTH*3 + +#define PALETTEWIDTH 16 +#define PALETTEHEIGHT 2 +#define PALETTEBITWIDTH PALETTEWIDTH*3 + +static ppuViewerDialog_t *ppuViewWindow = NULL; +static int PPUViewScanline = 0; +static int PPUViewSkip = 0; +static int PPUViewRefresh = 1; +static bool PPUView_maskUnusedGraphics = true; +static bool PPUView_invertTheMask = false; +static int PPUView_sprite16Mode[2] = { 0, 0 }; +static int pindex[2] = { 0, 0 }; +static QColor ppuv_palette[PALETTEHEIGHT][PALETTEWIDTH]; +static uint8_t pallast[32+3] = { 0 }; // palette cache for change comparison +static uint8_t palcache[36] = { 0 }; //palette cache for drawing +static uint8_t chrcache0[0x1000] = {0}, chrcache1[0x1000] = {0}, logcache0[0x1000] = {0}, logcache1[0x1000] = {0}; //cache CHR, fixes a refresh problem when right-clicking + +static void initPPUViewer(void); +static ppuPatternTable_t pattern0; +static ppuPatternTable_t pattern1; +//---------------------------------------------------- +int openPPUViewWindow( QWidget *parent ) +{ + if ( ppuViewWindow != NULL ) + { + return -1; + } + initPPUViewer(); + + ppuViewWindow = new ppuViewerDialog_t(parent); + + ppuViewWindow->show(); + + return 0; +} +//---------------------------------------------------- +ppuViewerDialog_t::ppuViewerDialog_t(QWidget *parent) + : QDialog( parent ) +{ + QVBoxLayout *mainLayout, *vbox; + QVBoxLayout *patternVbox[2]; + QHBoxLayout *hbox; + QGridLayout *grid; + char stmp[64]; + + ppuViewWindow = this; + + setWindowTitle( tr("PPU Viewer") ); + + mainLayout = new QVBoxLayout(); + + setLayout( mainLayout ); + + vbox = new QVBoxLayout(); + hbox = new QHBoxLayout(); + grid = new QGridLayout; + patternVbox[0] = new QVBoxLayout(); + patternVbox[1] = new QVBoxLayout(); + patternFrame[0] = new QGroupBox( tr("Pattern Table 0") ); + patternFrame[1] = new QGroupBox( tr("Pattern Table 1") ); + patternView[0] = new ppuPatternView_t( 0, this); + patternView[1] = new ppuPatternView_t( 1, this); + sprite8x16Cbox[0] = new QCheckBox( tr("Sprites 8x16 Mode") ); + sprite8x16Cbox[1] = new QCheckBox( tr("Sprites 8x16 Mode") ); + tileLabel[0] = new QLabel( tr("Tile:") ); + tileLabel[1] = new QLabel( tr("Tile:") ); + + sprite8x16Cbox[0]->setChecked( PPUView_sprite16Mode[0] ); + sprite8x16Cbox[1]->setChecked( PPUView_sprite16Mode[1] ); + + patternVbox[0]->addWidget( patternView[0], 10 ); + patternVbox[0]->addWidget( tileLabel[0], 1 ); + patternVbox[0]->addWidget( sprite8x16Cbox[0], 1 ); + patternVbox[1]->addWidget( patternView[1], 10 ); + patternVbox[1]->addWidget( tileLabel[1], 1 ); + patternVbox[1]->addWidget( sprite8x16Cbox[1], 1 ); + + patternFrame[0]->setLayout( patternVbox[0] ); + patternFrame[1]->setLayout( patternVbox[1] ); + + hbox->addWidget( patternFrame[0] ); + hbox->addWidget( patternFrame[1] ); + + mainLayout->addLayout( hbox, 10 ); + mainLayout->addLayout( grid, 1 ); + + maskUnusedCbox = new QCheckBox( tr("Mask unused Graphics (Code/Data Logger)") ); + invertMaskCbox = new QCheckBox( tr("Invert the Mask (Code/Data Logger)") ); + + maskUnusedCbox->setChecked( PPUView_maskUnusedGraphics ); + invertMaskCbox->setChecked( PPUView_invertTheMask ); + + connect( sprite8x16Cbox[0], SIGNAL(stateChanged(int)), this, SLOT(sprite8x16Changed0(int))); + connect( sprite8x16Cbox[1], SIGNAL(stateChanged(int)), this, SLOT(sprite8x16Changed1(int))); + + hbox = new QHBoxLayout(); + refreshSlider = new QSlider( Qt::Horizontal ); + hbox->addWidget( new QLabel( tr("Refresh: More") ) ); + hbox->addWidget( refreshSlider ); + hbox->addWidget( new QLabel( tr("Less") ) ); + + grid->addWidget( maskUnusedCbox, 0, 0, Qt::AlignLeft ); + grid->addWidget( invertMaskCbox, 1, 0, Qt::AlignLeft ); + grid->addLayout( hbox, 0, 1, Qt::AlignRight ); + + hbox = new QHBoxLayout(); + scanLineEdit = new QLineEdit(); + hbox->addWidget( new QLabel( tr("Display on Scanline:") ) ); + hbox->addWidget( scanLineEdit ); + grid->addLayout( hbox, 1, 1, Qt::AlignRight ); + + vbox = new QVBoxLayout(); + paletteFrame = new QGroupBox( tr("Palettes:") ); + paletteView = new ppuPalatteView_t(this); + + vbox->addWidget( paletteView, 1 ); + paletteFrame->setLayout( vbox ); + + mainLayout->addWidget( paletteFrame, 1 ); + + patternView[0]->setPattern( &pattern0 ); + patternView[1]->setPattern( &pattern1 ); + patternView[0]->setTileLabel( tileLabel[0] ); + patternView[1]->setTileLabel( tileLabel[1] ); + + scanLineEdit->setMaxLength( 3 ); + scanLineEdit->setInputMask( ">900;" ); + sprintf( stmp, "%i", PPUViewScanline ); + scanLineEdit->setText( tr(stmp) ); + + connect( scanLineEdit, SIGNAL(textEdited(const QString &)), this, SLOT(scanLineChanged(const QString &))); + + refreshSlider->setMinimum( 0); + refreshSlider->setMaximum(25); + refreshSlider->setValue(PPUViewRefresh); + + connect( refreshSlider, SIGNAL(valueChanged(int)), this, SLOT(refreshSliderChanged(int))); + + FCEUD_UpdatePPUView( -1, 1 ); +} + +//---------------------------------------------------- +ppuViewerDialog_t::~ppuViewerDialog_t(void) +{ + ppuViewWindow = NULL; + + printf("PPU Viewer Window Deleted\n"); +} +//---------------------------------------------------- +void ppuViewerDialog_t::closeEvent(QCloseEvent *event) +{ + printf("PPU Viewer Close Window Event\n"); + done(0); + deleteLater(); + event->accept(); +} +//---------------------------------------------------- +void ppuViewerDialog_t::closeWindow(void) +{ + printf("Close Window\n"); + done(0); + deleteLater(); +} +//---------------------------------------------------- +void ppuViewerDialog_t::scanLineChanged( const QString &txt ) +{ + std::string s; + + s = txt.toStdString(); + + if ( s.size() > 0 ) + { + PPUViewScanline = strtoul( s.c_str(), NULL, 10 ); + } + //printf("ScanLine: '%s' %i\n", s.c_str(), PPUViewScanline ); +} +//---------------------------------------------------- +void ppuViewerDialog_t::sprite8x16Changed0(int state) +{ + PPUView_sprite16Mode[0] = (state == Qt::Unchecked) ? 0 : 1; +} +//---------------------------------------------------- +void ppuViewerDialog_t::sprite8x16Changed1(int state) +{ + PPUView_sprite16Mode[1] = (state == Qt::Unchecked) ? 0 : 1; +} +//---------------------------------------------------- +void ppuViewerDialog_t::refreshSliderChanged(int value) +{ + PPUViewRefresh = value; +} +//---------------------------------------------------- +ppuPatternView_t::ppuPatternView_t( int patternIndexID, QWidget *parent) + : QWidget(parent) +{ + this->setFocusPolicy(Qt::StrongFocus); + this->setMouseTracking(true); + patternIndex = patternIndexID; + setMinimumWidth( 256 ); + setMinimumHeight( 256 ); + viewWidth = 256; + viewHeight = 256; + tileLabel = NULL; +} +//---------------------------------------------------- +void ppuPatternView_t::setPattern( ppuPatternTable_t *p ) +{ + pattern = p; +} +//---------------------------------------------------- +void ppuPatternView_t::setTileLabel( QLabel *l ) +{ + tileLabel = l; +} +//---------------------------------------------------- +ppuPatternView_t::~ppuPatternView_t(void) +{ + +} +//---------------------------------------------------- +QPoint ppuPatternView_t::convPixToTile( QPoint p ) +{ + QPoint t(0,0); + int x,y,w,h,i,j,ii,jj,rr; + + x = p.x(); y = p.y(); + + w = pattern->w; + h = pattern->h; + + i = x / (w*8); + j = y / (h*8); + + if ( PPUView_sprite16Mode[ patternIndex ] ) + { + rr = (j%2); + jj = j; + + if ( rr ) + { + jj--; + } + + ii = (i*2)+rr; + + if ( ii >= 16 ) + { + ii = ii % 16; + jj++; + } + } + else + { + ii = i; jj = j; + } + //printf("(x,y) = (%i,%i) w=%i h=%i $%X%X \n", x, y, w, h, jj, ii ); + + t.setX(ii); + t.setY(jj); + + return t; +} +//---------------------------------------------------- +void ppuPatternView_t::resizeEvent(QResizeEvent *event) +{ + viewWidth = event->size().width(); + viewHeight = event->size().height(); + + pattern->w = viewWidth / 128; + pattern->h = viewHeight / 128; +} +//---------------------------------------------------- +void ppuPatternView_t::mouseMoveEvent(QMouseEvent *event) +{ + char stmp[64]; + QPoint tile = convPixToTile( event->pos() ); + + sprintf( stmp, "Tile: $%X%X", tile.y(), tile.x() ); + + tileLabel->setText( tr(stmp) ); +} +//---------------------------------------------------------------------------- +void ppuPatternView_t::mousePressEvent(QMouseEvent * event) +{ + //QPoint tile = convPixToTile( event->pos() ); + + if ( event->button() == Qt::LeftButton ) + { + // TODO Load Tile Viewport + } + else if ( event->button() == Qt::RightButton ) + { + pindex[ patternIndex ] = (pindex[ patternIndex ] + 1) % 9; + PPUViewSkip = 100; + } +} +//---------------------------------------------------- +void ppuPatternView_t::paintEvent(QPaintEvent *event) +{ + int i,j,x,y,w,h,xx,yy,ii,jj,rr; + QPainter painter(this); + viewWidth = event->rect().width(); + viewHeight = event->rect().height(); + + //printf("PPU PatternView %ix%i \n", viewWidth, viewHeight ); + + w = viewWidth / 128; + h = viewHeight / 128; + + pattern->w = w; + pattern->h = h; + + xx = 0; yy = 0; + + if ( PPUView_sprite16Mode[ patternIndex ] ) + { + for (i=0; i<16; i++) //Columns + { + for (j=0; j<16; j++) //Rows + { + rr = (j%2); + jj = j; + + if ( rr ) + { + jj--; + } + + ii = (i*2)+rr; + + if ( ii >= 16 ) + { + ii = ii % 16; + jj++; + } + + xx = (i*8)*w; + + for (x=0; x < 8; x++) + { + yy = (j*8)*h; + + for (y=0; y < 8; y++) + { + pattern->tile[jj][ii].x = xx; + pattern->tile[jj][ii].y = yy; + painter.fillRect( xx, yy, w, h, pattern->tile[jj][ii].pixel[y][x].color ); + yy += h; + } + xx += w; + } + } + } + } + else + { + for (i=0; i<16; i++) //Columns + { + for (j=0; j<16; j++) //Rows + { + xx = (i*8)*w; + + for (x=0; x < 8; x++) + { + yy = (j*8)*h; + + for (y=0; y < 8; y++) + { + pattern->tile[j][i].x = xx; + pattern->tile[j][i].y = yy; + painter.fillRect( xx, yy, w, h, pattern->tile[j][i].pixel[y][x].color ); + yy += h; + } + xx += w; + } + } + } + } +} +//---------------------------------------------------- +static void initPPUViewer(void) +{ + memset( pallast , 0, sizeof(pallast) ); + memset( palcache , 0, sizeof(palcache) ); + memset( chrcache0, 0, sizeof(chrcache0) ); + memset( chrcache1, 0, sizeof(chrcache1) ); + memset( logcache0, 0, sizeof(logcache0) ); + memset( logcache1, 0, sizeof(logcache1) ); + + // forced palette (e.g. for debugging CHR when palettes are all-black) + palcache[(8*4)+0] = 0x0F; + palcache[(8*4)+1] = 0x00; + palcache[(8*4)+2] = 0x10; + palcache[(8*4)+3] = 0x20; + + pindex[0] = 0; + pindex[1] = 0; + +} +//---------------------------------------------------- +static void DrawPatternTable( ppuPatternTable_t *pattern, uint8_t *table, uint8_t *log, uint8_t pal) +{ + int i,j,x,y,index=0; + int p=0,tmp; + uint8_t chr0,chr1,logs,shift; + + pal <<= 2; + for (i = 0; i < 16; i++) //Columns + { + for (j = 0; j < 16; j++) //Rows + { + //printf("Tile: %X%X index:%04X %04X\n", j,i,index, (i<<4)|(j<<8)); + //----------------------------------------------- + for (y = 0; y < 8; y++) + { + chr0 = table[index]; + chr1 = table[index + 8]; + logs = log[index] & log[index + 8]; + tmp = 7; + shift=(PPUView_maskUnusedGraphics && debug_loggingCD && (((logs & 3) != 0) == PPUView_invertTheMask))?3:0; + for (x = 0; x < 8; x++) + { + p = (chr0 >> tmp) & 1; + p |= ((chr1 >> tmp) & 1) << 1; + p = palcache[p | pal]; + tmp--; + pattern->tile[i][j].pixel[y][x].color.setBlue( palo[p].b >> shift ); + pattern->tile[i][j].pixel[y][x].color.setGreen( palo[p].g >> shift ); + pattern->tile[i][j].pixel[y][x].color.setRed( palo[p].r >> shift ); + + //printf("Tile: %X%X Pixel: (%i,%i) P:%i RGB: (%i,%i,%i)\n", j, i, x, y, p, + // pattern->tile[j][i].pixel[y][x].color.red(), + // pattern->tile[j][i].pixel[y][x].color.green(), + // pattern->tile[j][i].pixel[y][x].color.blue() ); + } + index++; + } + index+=8; + //------------------------------------------------ + } + } +} +//---------------------------------------------------- +void FCEUD_UpdatePPUView(int scanline, int refreshchr) +{ + if ( ppuViewWindow == NULL ) + { + return; + } + if ( (scanline != -1) && (scanline != PPUViewScanline) ) + { + return; + } + int x,y,i; + + + if (refreshchr) + { + for (i = 0, x=0x1000; i < 0x1000; i++, x++) + { + chrcache0[i] = VPage[i>>10][i]; + chrcache1[i] = VPage[x>>10][x]; + if (debug_loggingCD) + { + if (cdloggerVideoDataSize) + { + int addr; + addr = &VPage[i >> 10][i] - CHRptr[0]; + if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize)) + logcache0[i] = cdloggervdata[addr]; + addr = &VPage[x >> 10][x] - CHRptr[0]; + if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize)) + logcache1[i] = cdloggervdata[addr]; + } + else + { + logcache0[i] = cdloggervdata[i]; + logcache1[i] = cdloggervdata[x]; + } + } + } + } + + if (PPUViewSkip < PPUViewRefresh) + { + PPUViewSkip++; + return; + } + PPUViewSkip = 0; + + // update palette only if required + if ((memcmp(pallast, PALRAM, 32) != 0) || (memcmp(pallast+32, UPALRAM, 3) != 0)) + { + //printf("Updated PPU View Palette\n"); + memcpy(pallast, PALRAM, 32); + memcpy(pallast+32, UPALRAM, 3); + + // cache palette content + memcpy(palcache,PALRAM,32); + palcache[0x10] = palcache[0x00]; + palcache[0x04] = palcache[0x14] = UPALRAM[0]; + palcache[0x08] = palcache[0x18] = UPALRAM[1]; + palcache[0x0C] = palcache[0x1C] = UPALRAM[2]; + + //draw palettes + for (y = 0; y < PALETTEHEIGHT; y++) + { + for (x = 0; x < PALETTEWIDTH; x++) + { + i = (y*PALETTEWIDTH) + x; + + ppuv_palette[y][x].setBlue( palo[palcache[i]].b ); + ppuv_palette[y][x].setGreen( palo[palcache[i]].g ); + ppuv_palette[y][x].setRed( palo[palcache[i]].r ); + } + } + } + + DrawPatternTable( &pattern0,chrcache0,logcache0,pindex[0]); + DrawPatternTable( &pattern1,chrcache1,logcache1,pindex[1]); + + if ( ppuViewWindow ) + { + ppuViewWindow->update(); + } +} +//---------------------------------------------------- +ppuPalatteView_t::ppuPalatteView_t(QWidget *parent) + : QWidget(parent) +{ + setMinimumWidth( 32 * PALETTEHEIGHT ); + setMinimumHeight( 32 * PALETTEHEIGHT ); + +} +//---------------------------------------------------- +ppuPalatteView_t::~ppuPalatteView_t(void) +{ + +} +//---------------------------------------------------- +void ppuPalatteView_t::paintEvent(QPaintEvent *event) +{ + int x,y,w,h,xx,yy; + QPainter painter(this); + int viewWidth = event->rect().width(); + int viewHeight = event->rect().height(); + + //printf("PPU PatternView %ix%i \n", viewWidth, viewHeight ); + + w = viewWidth / PALETTEWIDTH; + h = viewHeight / PALETTEHEIGHT; + + yy = 0; + for (y=0; y < PALETTEHEIGHT; y++) + { + xx = 0; + + for (x=0; x < PALETTEWIDTH; x++) + { + painter.fillRect( xx, yy, w, h, ppuv_palette[y][x] ); + xx += w; + } + yy += h; + } + + y = PALETTEHEIGHT*h; + for (int i=0; i<=PALETTEWIDTH; i++) + { + x = i*w; + painter.drawLine( x, 0 , x, y ); + } + + + x = PALETTEWIDTH*w; + for (int i=0; i<=PALETTEHEIGHT; i++) + { + y = i*h; + painter.drawLine( 0, y, x, y ); + } +} +//---------------------------------------------------- diff --git a/src/drivers/Qt/ppuViewer.h b/src/drivers/Qt/ppuViewer.h new file mode 100644 index 00000000..f73246bd --- /dev/null +++ b/src/drivers/Qt/ppuViewer.h @@ -0,0 +1,114 @@ +// ppuViewer.h +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Qt/main.h" + +struct ppuPatternTable_t +{ + struct + { + struct + { + QColor color; + } pixel[8][8]; + + int x; + int y; + + } tile[16][16]; + + int w; + int h; +}; + +class ppuPatternView_t : public QWidget +{ + Q_OBJECT + + public: + ppuPatternView_t( int patternIndex, QWidget *parent = 0); + ~ppuPatternView_t(void); + + void setPattern( ppuPatternTable_t *p ); + void setTileLabel( QLabel *l ); + QPoint convPixToTile( QPoint p ); + protected: + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent * event); + + int patternIndex; + int viewWidth; + int viewHeight; + QLabel *tileLabel; + ppuPatternTable_t *pattern; +}; + +class ppuPalatteView_t : public QWidget +{ + Q_OBJECT + + public: + ppuPalatteView_t(QWidget *parent = 0); + ~ppuPalatteView_t(void); + + protected: + void paintEvent(QPaintEvent *event); +}; + +class ppuViewerDialog_t : public QDialog +{ + Q_OBJECT + + public: + ppuViewerDialog_t(QWidget *parent = 0); + ~ppuViewerDialog_t(void); + + protected: + //QTimer *inputTimer; + + ppuPatternView_t *patternView[2]; + ppuPalatteView_t *paletteView; + + void closeEvent(QCloseEvent *bar); + private: + + QGroupBox *patternFrame[2]; + QGroupBox *paletteFrame; + QLabel *tileLabel[2]; + QCheckBox *sprite8x16Cbox[2]; + QCheckBox *maskUnusedCbox; + QCheckBox *invertMaskCbox; + QSlider *refreshSlider; + QLineEdit *scanLineEdit; + + public slots: + void closeWindow(void); + private slots: + //void updatePeriodic(void); + void sprite8x16Changed0(int state); + void sprite8x16Changed1(int state); + void refreshSliderChanged(int value); + void scanLineChanged( const QString &s ); +}; + +int openPPUViewWindow( QWidget *parent ); + diff --git a/src/drivers/sdl/debugger.cpp b/src/drivers/sdl/debugger.cpp index ea23deea..54d348cc 100644 --- a/src/drivers/sdl/debugger.cpp +++ b/src/drivers/sdl/debugger.cpp @@ -1714,6 +1714,11 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size) // Place holder to allow for compiling. GTK GUI doesn't support this. Qt Does. } +void FCEUD_UpdatePPUView(int scanline, int refreshchr) +{ + // Place holder to allow for compiling. GTK GUI doesn't support this. Qt Does. +} + static void closeDebuggerWindow (GtkWidget * w, GdkEvent * e, debuggerWin_t * dw) { std::list < debuggerWin_t * >::iterator it; diff --git a/src/palette.cpp b/src/palette.cpp index 5a9c2709..361d9671 100644 --- a/src/palette.cpp +++ b/src/palette.cpp @@ -72,7 +72,7 @@ static void ChoosePalette(void); static void WritePalette(void); //points to the actually selected current palette -pal *palo; +pal *palo = NULL; #define RGB_TO_YIQ( r, g, b, y, i ) (\ (y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\ diff --git a/src/ppu.cpp b/src/ppu.cpp index 0e667a43..712e72ee 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -1853,10 +1853,10 @@ int FCEUPPU_Loop(int skip) { for (scanline = 0; scanline < totalscanlines; ) { //scanline is incremented in DoLine. Evil. :/ deempcnt[deemp]++; -#ifdef WIN32 + if (scanline < 240) DEBUG(FCEUD_UpdatePPUView(scanline, 1)); -#endif + DoLine(); if (scanline < normalscanlines || scanline == totalscanlines) @@ -2137,7 +2137,8 @@ int FCEUX_PPU_Loop(int skip) { //int xscroll = ppur.fh; //render 241/291 scanlines (1 dummy at beginning, dendy's 50 at the end) //ignore overclocking! - for (int sl = 0; sl < normalscanlines; sl++) { + for (int sl = 0; sl < normalscanlines; sl++) + { spr_read.start_scanline(); g_rasterpos = 0; @@ -2148,9 +2149,10 @@ int FCEUX_PPU_Loop(int skip) { const int yp = sl - 1; ppuphase = PPUPHASE_BG; - if (sl != 0 && sl < 241) { // ignore the invisible -#ifdef WIN32 + if (sl != 0 && sl < 241) // ignore the invisible + { DEBUG(FCEUD_UpdatePPUView(scanline = yp, 1)); +#ifdef WIN32 DEBUG(FCEUD_UpdateNTView(scanline = yp, 1)); #endif }