Merge pull request #181 from mjbudd77/master
Added Name Table Viewer Feature for Qt GUI
This commit is contained in:
commit
c5e39608c9
2
TODO-SDL
2
TODO-SDL
|
@ -44,7 +44,7 @@ Memory Watch Window | NO | NO
|
|||
TAS Editor | NO | NO |
|
||||
6502 Debugger Window | YES | YES |
|
||||
PPU Viewer | YES | NO |
|
||||
Name Table Viewer | NO | NO |
|
||||
Name Table Viewer | YES | NO |
|
||||
Memory Hex Editor | YES | YES |
|
||||
Trace Logger | YES | NO |
|
||||
Code/Data Logger | YES | NO |
|
||||
|
|
|
@ -442,6 +442,7 @@ set(SRC_DRIVERS_SDL
|
|||
${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/NameTableViewer.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
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "Qt/AboutWindow.h"
|
||||
#include "Qt/fceuWrapper.h"
|
||||
#include "Qt/ppuViewer.h"
|
||||
#include "Qt/NameTableViewer.h"
|
||||
#include "Qt/keyscan.h"
|
||||
#include "Qt/nes_shm.h"
|
||||
|
||||
|
@ -510,6 +511,14 @@ void consoleWin_t::createMainMenu(void)
|
|||
|
||||
debugMenu->addAction(ppuViewAct);
|
||||
|
||||
// Debug -> Name Table Viewer
|
||||
ntViewAct = new QAction(tr("Name Table Viewer..."), this);
|
||||
//ntViewAct->setShortcut( QKeySequence(tr("Shift+F7")));
|
||||
ntViewAct->setStatusTip(tr("Open Name Table Viewer"));
|
||||
connect(ntViewAct, SIGNAL(triggered()), this, SLOT(openNTViewer(void)) );
|
||||
|
||||
debugMenu->addAction(ntViewAct);
|
||||
|
||||
// Debug -> Trace Logger
|
||||
traceLogAct = new QAction(tr("Trace Logger..."), this);
|
||||
//traceLogAct->setShortcut( QKeySequence(tr("Shift+F7")));
|
||||
|
@ -1037,6 +1046,13 @@ void consoleWin_t::openPPUViewer(void)
|
|||
openPPUViewWindow(this);
|
||||
}
|
||||
|
||||
void consoleWin_t::openNTViewer(void)
|
||||
{
|
||||
//printf("Open GUI Name Table Viewer Window\n");
|
||||
|
||||
openNameTableViewWindow(this);
|
||||
}
|
||||
|
||||
void consoleWin_t::openCodeDataLogger(void)
|
||||
{
|
||||
CodeDataLoggerDialog_t *cdlWin;
|
||||
|
|
|
@ -94,6 +94,7 @@ class consoleWin_t : public QMainWindow
|
|||
QAction *traceLogAct;
|
||||
QAction *hexEditAct;
|
||||
QAction *ppuViewAct;
|
||||
QAction *ntViewAct;
|
||||
QAction *openMovAct;
|
||||
QAction *stopMovAct;
|
||||
QAction *recMovAct;
|
||||
|
@ -164,6 +165,7 @@ class consoleWin_t : public QMainWindow
|
|||
void fdsEjectDisk(void);
|
||||
void fdsLoadBiosFile(void);
|
||||
void openPPUViewer(void);
|
||||
void openNTViewer(void);
|
||||
void openCheats(void);
|
||||
void openMovie(void);
|
||||
void stopMovie(void);
|
||||
|
|
|
@ -0,0 +1,776 @@
|
|||
// NameTableViewer.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 "../../ines.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../palette.h"
|
||||
|
||||
#include "Qt/NameTableViewer.h"
|
||||
#include "Qt/main.h"
|
||||
#include "Qt/dface.h"
|
||||
#include "Qt/input.h"
|
||||
#include "Qt/config.h"
|
||||
#include "Qt/fceuWrapper.h"
|
||||
|
||||
static ppuNameTableViewerDialog_t *nameTableViewWindow = NULL;
|
||||
static uint8_t palcache[36]; //palette cache
|
||||
static int NTViewScanline = 0;
|
||||
static int NTViewSkip = 100;
|
||||
static int NTViewRefresh = 1;
|
||||
static int chrchanged = 0;
|
||||
|
||||
static int xpos = 0, ypos = 0;
|
||||
static int attview = 0;
|
||||
static int hidepal = 0;
|
||||
static bool drawScrollLines = true;
|
||||
static bool redrawtables = true;
|
||||
|
||||
// checkerboard tile for attribute view
|
||||
static const uint8_t ATTRIBUTE_VIEW_TILE[16] = { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
|
||||
static class NTCache
|
||||
{
|
||||
public:
|
||||
NTCache(void)
|
||||
: curr_vnapage(0)
|
||||
{}
|
||||
|
||||
uint8_t* curr_vnapage;
|
||||
uint8_t cache[0x400];
|
||||
} cache[4];
|
||||
|
||||
static ppuNameTable_t nameTable[4];
|
||||
|
||||
enum NT_MirrorType
|
||||
{
|
||||
NT_NONE = -1,
|
||||
NT_HORIZONTAL, NT_VERTICAL, NT_FOUR_SCREEN,
|
||||
NT_SINGLE_SCREEN_TABLE_0, NT_SINGLE_SCREEN_TABLE_1,
|
||||
NT_SINGLE_SCREEN_TABLE_2, NT_SINGLE_SCREEN_TABLE_3,
|
||||
NT_NUM_MIRROR_TYPES
|
||||
};
|
||||
static NT_MirrorType ntmirroring = NT_NONE, oldntmirroring = NT_NONE;
|
||||
|
||||
static void initNameTableViewer(void);
|
||||
static void ChangeMirroring(void);
|
||||
//----------------------------------------------------
|
||||
int openNameTableViewWindow( QWidget *parent )
|
||||
{
|
||||
if ( nameTableViewWindow != NULL )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
initNameTableViewer();
|
||||
|
||||
nameTableViewWindow = new ppuNameTableViewerDialog_t(parent);
|
||||
|
||||
nameTableViewWindow->show();
|
||||
|
||||
return 0;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
ppuNameTableViewerDialog_t::ppuNameTableViewerDialog_t(QWidget *parent)
|
||||
: QDialog( parent )
|
||||
{
|
||||
QVBoxLayout *mainLayout, *vbox;
|
||||
QHBoxLayout *hbox;
|
||||
QGridLayout *grid;
|
||||
QGroupBox *frame;
|
||||
char stmp[64];
|
||||
|
||||
nameTableViewWindow = this;
|
||||
|
||||
setWindowTitle( tr("Name Table Viewer") );
|
||||
|
||||
mainLayout = new QVBoxLayout();
|
||||
|
||||
setLayout( mainLayout );
|
||||
|
||||
vbox = new QVBoxLayout();
|
||||
frame = new QGroupBox( tr("Name Tables") );
|
||||
ntView = new ppuNameTableView_t(this);
|
||||
grid = new QGridLayout();
|
||||
|
||||
vbox->addWidget( ntView );
|
||||
frame->setLayout( vbox );
|
||||
mainLayout->addWidget( frame, 100 );
|
||||
mainLayout->addLayout( grid , 1 );
|
||||
|
||||
showScrollLineCbox = new QCheckBox( tr("Show Scroll Lines") );
|
||||
showAttrbCbox = new QCheckBox( tr("Show Attributes") );
|
||||
ignorePaletteCbox = new QCheckBox( tr("Ignore Palette") );
|
||||
|
||||
showScrollLineCbox->setChecked( drawScrollLines );
|
||||
showAttrbCbox->setChecked( attview );
|
||||
ignorePaletteCbox->setChecked( hidepal );
|
||||
|
||||
grid->addWidget( showScrollLineCbox, 0, 0, Qt::AlignLeft );
|
||||
grid->addWidget( showAttrbCbox , 1, 0, Qt::AlignLeft );
|
||||
grid->addWidget( ignorePaletteCbox , 2, 0, Qt::AlignLeft );
|
||||
|
||||
connect( showScrollLineCbox, SIGNAL(stateChanged(int)), this, SLOT(showScrollLinesChanged(int)));
|
||||
connect( showAttrbCbox , SIGNAL(stateChanged(int)), this, SLOT(showAttrbChanged(int)));
|
||||
connect( ignorePaletteCbox , SIGNAL(stateChanged(int)), this, SLOT(ignorePaletteChanged(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->addLayout( hbox, 0, 1, Qt::AlignRight );
|
||||
|
||||
refreshSlider->setMinimum( 0);
|
||||
refreshSlider->setMaximum(25);
|
||||
refreshSlider->setValue(NTViewRefresh);
|
||||
|
||||
connect( refreshSlider, SIGNAL(valueChanged(int)), this, SLOT(refreshSliderChanged(int)));
|
||||
|
||||
hbox = new QHBoxLayout();
|
||||
scanLineEdit = new QLineEdit();
|
||||
hbox->addWidget( new QLabel( tr("Display on Scanline:") ) );
|
||||
hbox->addWidget( scanLineEdit );
|
||||
grid->addLayout( hbox, 1, 1, Qt::AlignRight );
|
||||
|
||||
scanLineEdit->setMaxLength( 3 );
|
||||
scanLineEdit->setInputMask( ">900;" );
|
||||
sprintf( stmp, "%i", NTViewScanline );
|
||||
scanLineEdit->setText( tr(stmp) );
|
||||
|
||||
connect( scanLineEdit, SIGNAL(textEdited(const QString &)), this, SLOT(scanLineChanged(const QString &)));
|
||||
|
||||
hbox = new QHBoxLayout();
|
||||
frame = new QGroupBox( tr("Current Mirroring") );
|
||||
grid = new QGridLayout();
|
||||
|
||||
mainLayout->addLayout( hbox, 1 );
|
||||
hbox->addWidget( frame );
|
||||
frame->setLayout( grid );
|
||||
|
||||
horzMirrorBtn = new QRadioButton( tr("Horizontal") );
|
||||
vertMirrorBtn = new QRadioButton( tr("Vertical") );
|
||||
fourScreenBtn = new QRadioButton( tr("Four Screen") );
|
||||
singleScreenBtn[0] = new QRadioButton( tr("Single Screen 0") );
|
||||
singleScreenBtn[1] = new QRadioButton( tr("Single Screen 1") );
|
||||
singleScreenBtn[2] = new QRadioButton( tr("Single Screen 2") );
|
||||
singleScreenBtn[3] = new QRadioButton( tr("Single Screen 3") );
|
||||
|
||||
grid->addWidget( horzMirrorBtn, 0, 0, Qt::AlignLeft );
|
||||
grid->addWidget( vertMirrorBtn, 1, 0, Qt::AlignLeft );
|
||||
grid->addWidget( fourScreenBtn, 2, 0, Qt::AlignLeft );
|
||||
grid->addWidget( singleScreenBtn[0], 0, 1, Qt::AlignLeft );
|
||||
grid->addWidget( singleScreenBtn[1], 1, 1, Qt::AlignLeft );
|
||||
grid->addWidget( singleScreenBtn[2], 2, 1, Qt::AlignLeft );
|
||||
grid->addWidget( singleScreenBtn[3], 3, 1, Qt::AlignLeft );
|
||||
|
||||
connect( horzMirrorBtn , SIGNAL(clicked(void)), this, SLOT(horzMirrorClicked(void)));
|
||||
connect( vertMirrorBtn , SIGNAL(clicked(void)), this, SLOT(vertMirrorClicked(void)));
|
||||
connect( fourScreenBtn , SIGNAL(clicked(void)), this, SLOT(fourScreenClicked(void)));
|
||||
connect( singleScreenBtn[0], SIGNAL(clicked(void)), this, SLOT(singleScreen0Clicked(void)));
|
||||
connect( singleScreenBtn[1], SIGNAL(clicked(void)), this, SLOT(singleScreen1Clicked(void)));
|
||||
connect( singleScreenBtn[2], SIGNAL(clicked(void)), this, SLOT(singleScreen2Clicked(void)));
|
||||
connect( singleScreenBtn[3], SIGNAL(clicked(void)), this, SLOT(singleScreen3Clicked(void)));
|
||||
|
||||
updateMirrorButtons();
|
||||
|
||||
vbox = new QVBoxLayout();
|
||||
frame = new QGroupBox( tr("Properties") );
|
||||
hbox->addWidget( frame );
|
||||
frame->setLayout( vbox );
|
||||
|
||||
tileID = new QLabel( tr("Tile ID:") );
|
||||
tileXY = new QLabel( tr("X/Y :") );
|
||||
ppuAddrLbl = new QLabel( tr("PPU Address:") );
|
||||
attrbLbl = new QLabel( tr("Attribute:") );
|
||||
|
||||
vbox->addWidget( tileID );
|
||||
vbox->addWidget( tileXY );
|
||||
vbox->addWidget( ppuAddrLbl );
|
||||
vbox->addWidget( attrbLbl );
|
||||
|
||||
FCEUD_UpdateNTView( -1, true);
|
||||
|
||||
updateTimer = new QTimer( this );
|
||||
|
||||
connect( updateTimer, &QTimer::timeout, this, &ppuNameTableViewerDialog_t::periodicUpdate );
|
||||
|
||||
updateTimer->start( 33 ); // 30hz
|
||||
}
|
||||
//----------------------------------------------------
|
||||
ppuNameTableViewerDialog_t::~ppuNameTableViewerDialog_t(void)
|
||||
{
|
||||
updateTimer->stop();
|
||||
nameTableViewWindow = NULL;
|
||||
|
||||
printf("Name Table Viewer Window Deleted\n");
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
printf("Name Table Viewer Close Window Event\n");
|
||||
done(0);
|
||||
deleteLater();
|
||||
event->accept();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::closeWindow(void)
|
||||
{
|
||||
printf("Close Window\n");
|
||||
done(0);
|
||||
deleteLater();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::periodicUpdate(void)
|
||||
{
|
||||
updateMirrorButtons();
|
||||
|
||||
if ( redrawtables )
|
||||
{
|
||||
this->update();
|
||||
redrawtables = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::setPropertyLabels( int TileID, int TileX, int TileY, int NameTable, int PPUAddress, int AttAddress, int Attrib )
|
||||
{
|
||||
char stmp[64];
|
||||
|
||||
sprintf( stmp, "Tile ID: %02X", TileID);
|
||||
|
||||
tileID->setText( tr(stmp) );
|
||||
|
||||
sprintf( stmp, "X/Y : %0d/%0d", TileX, TileY);
|
||||
|
||||
tileXY->setText( tr(stmp) );
|
||||
|
||||
sprintf(stmp,"PPU Address: %04X",PPUAddress);
|
||||
|
||||
ppuAddrLbl->setText( tr(stmp) );
|
||||
|
||||
sprintf(stmp,"Attribute: %1X (%04X)",Attrib,AttAddress);
|
||||
|
||||
attrbLbl->setText( tr(stmp) );
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::updateMirrorButtons(void)
|
||||
{
|
||||
switch ( ntmirroring )
|
||||
{
|
||||
default:
|
||||
case NT_NONE:
|
||||
break;
|
||||
case NT_HORIZONTAL:
|
||||
horzMirrorBtn->setChecked(true);
|
||||
break;
|
||||
case NT_VERTICAL:
|
||||
vertMirrorBtn->setChecked(true);
|
||||
break;
|
||||
case NT_FOUR_SCREEN:
|
||||
fourScreenBtn->setChecked(true);
|
||||
break;
|
||||
case NT_SINGLE_SCREEN_TABLE_0:
|
||||
case NT_SINGLE_SCREEN_TABLE_1:
|
||||
case NT_SINGLE_SCREEN_TABLE_2:
|
||||
case NT_SINGLE_SCREEN_TABLE_3:
|
||||
{
|
||||
int i = ntmirroring - NT_SINGLE_SCREEN_TABLE_0;
|
||||
|
||||
singleScreenBtn[i]->setChecked(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::horzMirrorClicked(void)
|
||||
{
|
||||
ntmirroring = NT_HORIZONTAL;
|
||||
ChangeMirroring();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::vertMirrorClicked(void)
|
||||
{
|
||||
ntmirroring = NT_VERTICAL;
|
||||
ChangeMirroring();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::fourScreenClicked(void)
|
||||
{
|
||||
ntmirroring = NT_FOUR_SCREEN;
|
||||
ChangeMirroring();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::singleScreen0Clicked(void)
|
||||
{
|
||||
ntmirroring = NT_SINGLE_SCREEN_TABLE_0;
|
||||
ChangeMirroring();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::singleScreen1Clicked(void)
|
||||
{
|
||||
ntmirroring = NT_SINGLE_SCREEN_TABLE_1;
|
||||
ChangeMirroring();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::singleScreen2Clicked(void)
|
||||
{
|
||||
ntmirroring = NT_SINGLE_SCREEN_TABLE_2;
|
||||
ChangeMirroring();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::singleScreen3Clicked(void)
|
||||
{
|
||||
ntmirroring = NT_SINGLE_SCREEN_TABLE_3;
|
||||
ChangeMirroring();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::scanLineChanged( const QString &txt )
|
||||
{
|
||||
std::string s;
|
||||
|
||||
s = txt.toStdString();
|
||||
|
||||
if ( s.size() > 0 )
|
||||
{
|
||||
NTViewScanline = strtoul( s.c_str(), NULL, 10 );
|
||||
}
|
||||
//printf("ScanLine: '%s' %i\n", s.c_str(), PPUViewScanline );
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::showScrollLinesChanged(int state)
|
||||
{
|
||||
drawScrollLines = (state != Qt::Unchecked);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::showAttrbChanged(int state)
|
||||
{
|
||||
attview = (state != Qt::Unchecked);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::ignorePaletteChanged(int state)
|
||||
{
|
||||
hidepal = (state != Qt::Unchecked);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableViewerDialog_t::refreshSliderChanged(int value)
|
||||
{
|
||||
NTViewRefresh = value;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
ppuNameTableView_t::ppuNameTableView_t(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
this->parent = (ppuNameTableViewerDialog_t*)parent;
|
||||
this->setFocusPolicy(Qt::StrongFocus);
|
||||
this->setMouseTracking(true);
|
||||
viewWidth = 256 * 2;
|
||||
viewHeight = 240 * 2;
|
||||
setMinimumWidth( viewWidth );
|
||||
setMinimumHeight( viewHeight );
|
||||
}
|
||||
//----------------------------------------------------
|
||||
ppuNameTableView_t::~ppuNameTableView_t(void)
|
||||
{
|
||||
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableView_t::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
viewWidth = event->size().width();
|
||||
viewHeight = event->size().height();
|
||||
|
||||
//printf("%ix%i\n", viewWidth, viewHeight );
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableView_t::computeNameTableProperties( int x, int y )
|
||||
{
|
||||
int i, xx, yy, w, h, TileID, TileX, TileY, NameTable, PPUAddress, AttAddress, Attrib;
|
||||
ppuNameTable_t *tbl = NULL;
|
||||
|
||||
NameTable = 0;
|
||||
|
||||
if ( vnapage[0] == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
xx = nameTable[i].x;
|
||||
yy = nameTable[i].y;
|
||||
w = (nameTable[i].w * 256);
|
||||
h = (nameTable[i].h * 240);
|
||||
|
||||
if ( (x >= xx) && (x < (xx+w) ) &&
|
||||
(y >= yy) && (y < (yy+h) ) )
|
||||
{
|
||||
tbl = &nameTable[i];
|
||||
NameTable = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tbl == NULL )
|
||||
{
|
||||
//printf("Mouse not over a tile\n");
|
||||
return;
|
||||
}
|
||||
xx = tbl->x; yy = tbl->y;
|
||||
w = tbl->w; h = tbl->h;
|
||||
|
||||
if ( (NameTable%2) == 1 )
|
||||
{
|
||||
TileX = ((x - xx) / (w*8)) + 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
TileX = (x - xx) / (w*8);
|
||||
}
|
||||
|
||||
if ( (NameTable/2) == 1 )
|
||||
{
|
||||
TileY = ((y - yy) / (h*8)) + 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
TileY = (y - yy) / (h*8);
|
||||
}
|
||||
|
||||
PPUAddress = 0x2000+(NameTable*0x400)+((TileY%30)*32)+(TileX%32);
|
||||
|
||||
TileID = vnapage[(PPUAddress>>10)&0x3][PPUAddress&0x3FF];
|
||||
|
||||
AttAddress = 0x23C0 | (PPUAddress & 0x0C00) | ((PPUAddress >> 4) & 0x38) | ((PPUAddress >> 2) & 0x07);
|
||||
Attrib = vnapage[(AttAddress>>10)&0x3][AttAddress&0x3FF];
|
||||
Attrib = (Attrib >> ((PPUAddress&2) | ((PPUAddress&64)>>4))) & 0x3;
|
||||
|
||||
//printf("NT:%i Tile X/Y : %i/%i \n", NameTable, TileX, TileY );
|
||||
|
||||
if ( parent )
|
||||
{
|
||||
parent->setPropertyLabels( TileID, TileX, TileY, NameTable, PPUAddress, AttAddress, Attrib );
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableView_t::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
computeNameTableProperties( event->pos().x(), event->pos().y() );
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void ppuNameTableView_t::mousePressEvent(QMouseEvent * event)
|
||||
{
|
||||
//QPoint tile = convPixToTile( event->pos() );
|
||||
|
||||
if ( event->button() == Qt::LeftButton )
|
||||
{
|
||||
}
|
||||
else if ( event->button() == Qt::RightButton )
|
||||
{
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuNameTableView_t::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
ppuNameTable_t *nt;
|
||||
int n,i,j,ii,jj,w,h,x,y,xx,yy,ww,hh;
|
||||
QPainter painter(this);
|
||||
QColor scanLineColor(255,255,255);
|
||||
viewWidth = event->rect().width();
|
||||
viewHeight = event->rect().height();
|
||||
|
||||
w = viewWidth / (256*2);
|
||||
h = viewHeight / (240*2);
|
||||
|
||||
//printf("%ix%i\n", viewWidth, viewHeight );
|
||||
|
||||
xx = 0; yy = 0;
|
||||
|
||||
for (n=0; n<4; n++)
|
||||
{
|
||||
nt = &nameTable[n];
|
||||
|
||||
nt->w = w; nt->h = h;
|
||||
|
||||
nt->x = xx = (n%2) * (viewWidth / 2);
|
||||
nt->y = yy = (n/2) * (viewHeight / 2);
|
||||
|
||||
for (j=0; j<30; j++)
|
||||
{
|
||||
jj = (j*8);
|
||||
|
||||
for (i=0; i<32; i++)
|
||||
{
|
||||
ii = (i*8);
|
||||
|
||||
nt->tile[j][i].x = xx+(ii*w);
|
||||
nt->tile[j][i].y = yy+(jj*h);
|
||||
|
||||
for (y=0; y<8; y++)
|
||||
{
|
||||
for (x=0; x<8; x++)
|
||||
{
|
||||
painter.fillRect( xx+(ii+x)*w, yy+(jj+y)*h, w, h, nt->tile[j][i].pixel[y][x].color );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( drawScrollLines )
|
||||
{
|
||||
ww = nt->w * 256;
|
||||
hh = nt->h * 240;
|
||||
|
||||
painter.setPen( scanLineColor );
|
||||
|
||||
if ( (xpos >= xx) && (xpos < (xx+ww)) )
|
||||
{
|
||||
painter.drawLine( xpos, yy, xpos, yy + hh );
|
||||
}
|
||||
|
||||
if ( (ypos >= yy) && (ypos < (yy+hh)) )
|
||||
{
|
||||
painter.drawLine( xx, ypos, xx + ww, ypos );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//----------------------------------------------------
|
||||
static void initNameTableViewer(void)
|
||||
{
|
||||
//clear cache
|
||||
memset(palcache,0,32);
|
||||
|
||||
// forced palette (e.g. for debugging nametables 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;
|
||||
|
||||
}
|
||||
//----------------------------------------------------
|
||||
static void ChangeMirroring(void)
|
||||
{
|
||||
switch (ntmirroring)
|
||||
{
|
||||
case NT_HORIZONTAL:
|
||||
vnapage[0] = vnapage[1] = &NTARAM[0x000];
|
||||
vnapage[2] = vnapage[3] = &NTARAM[0x400];
|
||||
break;
|
||||
case NT_VERTICAL:
|
||||
vnapage[0] = vnapage[2] = &NTARAM[0x000];
|
||||
vnapage[1] = vnapage[3] = &NTARAM[0x400];
|
||||
break;
|
||||
case NT_FOUR_SCREEN:
|
||||
vnapage[0] = &NTARAM[0x000];
|
||||
vnapage[1] = &NTARAM[0x400];
|
||||
if(ExtraNTARAM)
|
||||
{
|
||||
vnapage[2] = ExtraNTARAM;
|
||||
vnapage[3] = ExtraNTARAM + 0x400;
|
||||
}
|
||||
break;
|
||||
case NT_SINGLE_SCREEN_TABLE_0:
|
||||
vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = &NTARAM[0x000];
|
||||
break;
|
||||
case NT_SINGLE_SCREEN_TABLE_1:
|
||||
vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = &NTARAM[0x400];
|
||||
break;
|
||||
case NT_SINGLE_SCREEN_TABLE_2:
|
||||
if(ExtraNTARAM)
|
||||
vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = ExtraNTARAM;
|
||||
break;
|
||||
case NT_SINGLE_SCREEN_TABLE_3:
|
||||
if(ExtraNTARAM)
|
||||
vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = ExtraNTARAM + 0x400;
|
||||
break;
|
||||
default:
|
||||
case NT_NONE:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
inline void DrawChr( ppuNameTableTile_t *tile, const uint8_t *chr, int pal)
|
||||
{
|
||||
int y, x, tmp, index=0, p=0;
|
||||
uint8 chr0, chr1;
|
||||
//uint8 *table = &VPage[0][0]; //use the background table
|
||||
//pbitmap += 3*
|
||||
|
||||
for (y = 0; y < 8; y++) { //todo: use index for y?
|
||||
chr0 = chr[index];
|
||||
chr1 = chr[index+8];
|
||||
tmp=7;
|
||||
for (x = 0; x < 8; x++) { //todo: use tmp for x?
|
||||
p = (chr0>>tmp)&1;
|
||||
p |= ((chr1>>tmp)&1)<<1;
|
||||
p = palcache[p+(pal*4)];
|
||||
tmp--;
|
||||
|
||||
tile->pixel[y][x].color.setBlue( palo[p].b );
|
||||
tile->pixel[y][x].color.setGreen( palo[p].g );
|
||||
tile->pixel[y][x].color.setRed( palo[p].r );
|
||||
}
|
||||
index++;
|
||||
//pbitmap += (NTWIDTH*3)-24;
|
||||
}
|
||||
//index+=8;
|
||||
//pbitmap -= (((PALETTEBITWIDTH>>2)<<3)-24);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
static void DrawNameTable(int scanline, int ntnum, bool invalidateCache)
|
||||
{
|
||||
NTCache &c = cache[ntnum];
|
||||
uint8_t *tablecache = c.cache;
|
||||
|
||||
uint8_t *table = vnapage[ntnum];
|
||||
if (table == NULL)
|
||||
{
|
||||
table = vnapage[ntnum&1];
|
||||
}
|
||||
|
||||
int a, ptable=0;
|
||||
|
||||
if (PPU[0]&0x10){ //use the correct pattern table based on this bit
|
||||
ptable=0x1000;
|
||||
}
|
||||
|
||||
bool invalid = invalidateCache;
|
||||
//if we werent asked to invalidate the cache, maybe we need to invalidate it anyway due to vnapage changing
|
||||
if (!invalid)
|
||||
{
|
||||
invalid = (c.curr_vnapage != vnapage[ntnum]);
|
||||
}
|
||||
c.curr_vnapage = vnapage[ntnum];
|
||||
|
||||
//HACK: never cache anything
|
||||
invalid = true;
|
||||
|
||||
for (int y=0;y<30;y++)
|
||||
{
|
||||
for (int x=0;x<32;x++)
|
||||
{
|
||||
int ntaddr = (y*32)+x;
|
||||
int attraddr = 0x3C0+((y>>2)<<3)+(x>>2);
|
||||
if (invalid
|
||||
|| (table[ntaddr] != tablecache[ntaddr])
|
||||
|| (table[attraddr] != tablecache[attraddr]))
|
||||
{
|
||||
int temp = (((y&2)<<1)+(x&2));
|
||||
a = (table[attraddr] & (3<<temp)) >> temp;
|
||||
|
||||
//the commented out code below is all allegedly equivalent to the single line above:
|
||||
//tmpx = x>>2;
|
||||
//tmpy = y>>2;
|
||||
//a = 0x3C0+(tmpy*8)+tmpx;
|
||||
//if((((x>>1)&1) == 0) && (((y>>1)&1) == 0)) a = table[a]&0x3;
|
||||
//if((((x>>1)&1) == 1) && (((y>>1)&1) == 0)) a = (table[a]&0xC)>>2;
|
||||
//if((((x>>1)&1) == 0) && (((y>>1)&1) == 1)) a = (table[a]&0x30)>>4;
|
||||
//if((((x>>1)&1) == 1) && (((y>>1)&1) == 1)) a = (table[a]&0xC0)>>6;
|
||||
|
||||
int chr = table[ntaddr]*16;
|
||||
|
||||
extern int FCEUPPU_GetAttr(int ntnum, int xt, int yt);
|
||||
|
||||
//test.. instead of pretending that the nametable is a screen at 0,0 we pretend that it is at the current xscroll and yscroll
|
||||
//int xpos = ((RefreshAddr & 0x400) >> 2) | ((RefreshAddr & 0x1F) << 3) | XOffset;
|
||||
//int ypos = ((RefreshAddr & 0x3E0) >> 2) | ((RefreshAddr & 0x7000) >> 12);
|
||||
//if(RefreshAddr & 0x800) ypos += 240;
|
||||
//int refreshaddr = (xpos/8+x)+(ypos/8+y)*32;
|
||||
|
||||
int refreshaddr = (x)+(y)*32;
|
||||
|
||||
a = FCEUPPU_GetAttr(ntnum,x,y);
|
||||
if (hidepal) a = 8;
|
||||
|
||||
const uint8* chrp = FCEUPPU_GetCHR(ptable+chr,refreshaddr);
|
||||
if (attview) chrp = ATTRIBUTE_VIEW_TILE;
|
||||
|
||||
//a good way to do it:
|
||||
DrawChr( &nameTable[ntnum].tile[y][x], chrp, a);
|
||||
|
||||
tablecache[ntaddr] = table[ntaddr];
|
||||
tablecache[attraddr] = table[attraddr];
|
||||
//one could comment out the line above...
|
||||
//since there are so many fewer attribute values than NT values, it might be best just to refresh the whole attr table below with the memcpy
|
||||
|
||||
//obviously this whole scheme of nt cache doesnt work if an mmc5 game is playing tricks with the attribute table
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void FCEUD_UpdateNTView(int scanline, bool drawall)
|
||||
{
|
||||
if (nameTableViewWindow == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ( (scanline != -1) && (scanline != NTViewScanline) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ppu_getScroll(xpos,ypos);
|
||||
|
||||
if (NTViewSkip < NTViewRefresh)
|
||||
{
|
||||
NTViewSkip++;
|
||||
return;
|
||||
}
|
||||
NTViewSkip = 0;
|
||||
|
||||
if (chrchanged)
|
||||
{
|
||||
drawall = 1;
|
||||
}
|
||||
|
||||
//update palette only if required
|
||||
if (memcmp(palcache,PALRAM,32) != 0)
|
||||
{
|
||||
memcpy(palcache,PALRAM,32);
|
||||
drawall = 1; //palette has changed, so redraw all
|
||||
}
|
||||
|
||||
if ( vnapage[0] == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ntmirroring = NT_NONE;
|
||||
if (vnapage[0] == vnapage[1])ntmirroring = NT_HORIZONTAL;
|
||||
if (vnapage[0] == vnapage[2])ntmirroring = NT_VERTICAL;
|
||||
if ((vnapage[0] != vnapage[1]) && (vnapage[0] != vnapage[2]))ntmirroring = NT_FOUR_SCREEN;
|
||||
|
||||
if ((vnapage[0] == vnapage[1]) && (vnapage[1] == vnapage[2]) && (vnapage[2] == vnapage[3]))
|
||||
{
|
||||
if(vnapage[0] == &NTARAM[0x000])ntmirroring = NT_SINGLE_SCREEN_TABLE_0;
|
||||
if(vnapage[0] == &NTARAM[0x400])ntmirroring = NT_SINGLE_SCREEN_TABLE_1;
|
||||
if(vnapage[0] == ExtraNTARAM)ntmirroring = NT_SINGLE_SCREEN_TABLE_2;
|
||||
if(vnapage[0] == ExtraNTARAM+0x400)ntmirroring = NT_SINGLE_SCREEN_TABLE_3;
|
||||
}
|
||||
|
||||
if (oldntmirroring != ntmirroring)
|
||||
{
|
||||
//UpdateMirroringButtons();
|
||||
oldntmirroring = ntmirroring;
|
||||
}
|
||||
|
||||
for (int i=0;i<4;i++)
|
||||
{
|
||||
DrawNameTable(scanline,i,drawall);
|
||||
}
|
||||
|
||||
chrchanged = 0;
|
||||
redrawtables = true;
|
||||
return;
|
||||
}
|
||||
//----------------------------------------------------
|
|
@ -0,0 +1,114 @@
|
|||
// NameTableViewer.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
#include <QLabel>
|
||||
#include <QFrame>
|
||||
#include <QTimer>
|
||||
#include <QSlider>
|
||||
#include <QLineEdit>
|
||||
#include <QGroupBox>
|
||||
#include <QCloseEvent>
|
||||
|
||||
struct ppuNameTablePixel_t
|
||||
{
|
||||
QColor color;
|
||||
};
|
||||
|
||||
struct ppuNameTableTile_t
|
||||
{
|
||||
struct ppuNameTablePixel_t pixel[8][8];
|
||||
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct ppuNameTable_t
|
||||
{
|
||||
struct ppuNameTableTile_t tile[30][32];
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
class ppuNameTableViewerDialog_t;
|
||||
|
||||
class ppuNameTableView_t : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ppuNameTableView_t( QWidget *parent = 0);
|
||||
~ppuNameTableView_t(void);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mousePressEvent(QMouseEvent * event);
|
||||
void computeNameTableProperties( int x, int y );
|
||||
|
||||
ppuNameTableViewerDialog_t *parent;
|
||||
int viewWidth;
|
||||
int viewHeight;
|
||||
};
|
||||
|
||||
class ppuNameTableViewerDialog_t : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ppuNameTableViewerDialog_t(QWidget *parent = 0);
|
||||
~ppuNameTableViewerDialog_t(void);
|
||||
|
||||
void setPropertyLabels( int TileID, int TileX, int TileY, int NameTable, int PPUAddress, int AttAddress, int Attrib );
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *bar);
|
||||
|
||||
ppuNameTableView_t *ntView;
|
||||
QCheckBox *showScrollLineCbox;
|
||||
QCheckBox *showAttrbCbox;
|
||||
QCheckBox *ignorePaletteCbox;
|
||||
QSlider *refreshSlider;
|
||||
QLineEdit *scanLineEdit;
|
||||
QTimer *updateTimer;
|
||||
QRadioButton *horzMirrorBtn;
|
||||
QRadioButton *vertMirrorBtn;
|
||||
QRadioButton *fourScreenBtn;
|
||||
QRadioButton *singleScreenBtn[4];
|
||||
QLabel *tileID;
|
||||
QLabel *tileXY;
|
||||
QLabel *ppuAddrLbl;
|
||||
QLabel *attrbLbl;
|
||||
|
||||
public slots:
|
||||
void closeWindow(void);
|
||||
private slots:
|
||||
void periodicUpdate(void);
|
||||
void updateMirrorButtons(void);
|
||||
void horzMirrorClicked(void);
|
||||
void vertMirrorClicked(void);
|
||||
void fourScreenClicked(void);
|
||||
void singleScreen0Clicked(void);
|
||||
void singleScreen1Clicked(void);
|
||||
void singleScreen2Clicked(void);
|
||||
void singleScreen3Clicked(void);
|
||||
void showAttrbChanged(int state);
|
||||
void ignorePaletteChanged(int state);
|
||||
void showScrollLinesChanged(int state);
|
||||
void refreshSliderChanged(int value);
|
||||
void scanLineChanged( const QString &txt );
|
||||
};
|
||||
|
||||
int openNameTableViewWindow( QWidget *parent );
|
||||
|
|
@ -42,6 +42,7 @@ 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 bool redrawWindow = true;
|
||||
|
||||
static void initPPUViewer(void);
|
||||
static ppuPatternTable_t pattern0;
|
||||
|
@ -166,11 +167,18 @@ ppuViewerDialog_t::ppuViewerDialog_t(QWidget *parent)
|
|||
connect( refreshSlider, SIGNAL(valueChanged(int)), this, SLOT(refreshSliderChanged(int)));
|
||||
|
||||
FCEUD_UpdatePPUView( -1, 1 );
|
||||
|
||||
updateTimer = new QTimer( this );
|
||||
|
||||
connect( updateTimer, &QTimer::timeout, this, &ppuViewerDialog_t::periodicUpdate );
|
||||
|
||||
updateTimer->start( 33 ); // 30hz
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
ppuViewerDialog_t::~ppuViewerDialog_t(void)
|
||||
{
|
||||
updateTimer->stop();
|
||||
ppuViewWindow = NULL;
|
||||
|
||||
printf("PPU Viewer Window Deleted\n");
|
||||
|
@ -191,6 +199,15 @@ void ppuViewerDialog_t::closeWindow(void)
|
|||
deleteLater();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuViewerDialog_t::periodicUpdate(void)
|
||||
{
|
||||
if ( redrawWindow )
|
||||
{
|
||||
this->update();
|
||||
redrawWindow = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ppuViewerDialog_t::scanLineChanged( const QString &txt )
|
||||
{
|
||||
std::string s;
|
||||
|
@ -493,19 +510,28 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr)
|
|||
|
||||
if (refreshchr)
|
||||
{
|
||||
int i10, x10;
|
||||
for (i = 0, x=0x1000; i < 0x1000; i++, x++)
|
||||
{
|
||||
chrcache0[i] = VPage[i>>10][i];
|
||||
chrcache1[i] = VPage[x>>10][x];
|
||||
i10 = i>>10;
|
||||
x10 = x>>10;
|
||||
|
||||
if ( VPage[i10] == NULL )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
chrcache0[i] = VPage[i10][i];
|
||||
chrcache1[i] = VPage[x10][x];
|
||||
|
||||
if (debug_loggingCD)
|
||||
{
|
||||
if (cdloggerVideoDataSize)
|
||||
{
|
||||
int addr;
|
||||
addr = &VPage[i >> 10][i] - CHRptr[0];
|
||||
addr = &VPage[i10][i] - CHRptr[0];
|
||||
if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize))
|
||||
logcache0[i] = cdloggervdata[addr];
|
||||
addr = &VPage[x >> 10][x] - CHRptr[0];
|
||||
addr = &VPage[x10][x] - CHRptr[0];
|
||||
if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize))
|
||||
logcache1[i] = cdloggervdata[addr];
|
||||
}
|
||||
|
@ -556,10 +582,7 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr)
|
|||
DrawPatternTable( &pattern0,chrcache0,logcache0,pindex[0]);
|
||||
DrawPatternTable( &pattern1,chrcache1,logcache1,pindex[1]);
|
||||
|
||||
if ( ppuViewWindow )
|
||||
{
|
||||
ppuViewWindow->update();
|
||||
}
|
||||
redrawWindow = true;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
ppuPalatteView_t::ppuPalatteView_t(QWidget *parent)
|
||||
|
|
|
@ -108,10 +108,12 @@ class ppuViewerDialog_t : public QDialog
|
|||
QCheckBox *invertMaskCbox;
|
||||
QSlider *refreshSlider;
|
||||
QLineEdit *scanLineEdit;
|
||||
QTimer *updateTimer;
|
||||
|
||||
public slots:
|
||||
void closeWindow(void);
|
||||
private slots:
|
||||
void periodicUpdate(void);
|
||||
void sprite8x16Changed0(int state);
|
||||
void sprite8x16Changed1(int state);
|
||||
void refreshSliderChanged(int value);
|
||||
|
|
|
@ -1719,6 +1719,11 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr)
|
|||
// Place holder to allow for compiling. GTK GUI doesn't support this. Qt Does.
|
||||
}
|
||||
|
||||
void FCEUD_UpdateNTView(int scanline, bool drawall)
|
||||
{
|
||||
// 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;
|
||||
|
|
|
@ -1375,9 +1375,7 @@ static void DoLine(void) {
|
|||
GameHBIRQHook();
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
DEBUG(FCEUD_UpdateNTView(scanline, 0));
|
||||
#endif
|
||||
|
||||
if (SpriteON)
|
||||
RefreshSprites();
|
||||
|
@ -2152,9 +2150,7 @@ int FCEUX_PPU_Loop(int skip) {
|
|||
if (sl != 0 && sl < 241) // ignore the invisible
|
||||
{
|
||||
DEBUG(FCEUD_UpdatePPUView(scanline = yp, 1));
|
||||
#ifdef WIN32
|
||||
DEBUG(FCEUD_UpdateNTView(scanline = yp, 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
//hack to fix SDF ship intro screen with split. is it right?
|
||||
|
|
Loading…
Reference in New Issue