Merge pull request #178 from mjbudd77/master
Added PPU Viewer Feature to Qt/SDL GUI
This commit is contained in:
commit
717967c4d9
2
TODO-SDL
2
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 |
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,609 @@
|
|||
// ppuViewer.cpp
|
||||
//
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QPainter>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#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 );
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
|
@ -0,0 +1,114 @@
|
|||
// ppuViewer.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QFrame>
|
||||
#include <QTimer>
|
||||
#include <QSlider>
|
||||
#include <QLineEdit>
|
||||
#include <QGroupBox>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#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 );
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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),\
|
||||
|
|
12
src/ppu.cpp
12
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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue