First successful viewing of pattern and palatte colors on Qt PPU Viewer.

This commit is contained in:
Matthew Budd 2020-10-04 09:54:51 -04:00
parent c21041e26e
commit cf2b43f31a
4 changed files with 336 additions and 7 deletions

View File

@ -1,11 +1,20 @@
// 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"
@ -13,7 +22,40 @@
#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 = 0;
static bool PPUView_maskUnusedGraphics = true;
static bool PPUView_invertTheMask = false;
static int PPUView_sprite16Mode = 0;
static int pindex0 = 0, pindex1 = 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
//pattern table bitmap arrays
struct patternTable_t
{
struct
{
struct
{
QColor color;
} pixel[16][8];
} tile[16][16];
};
static patternTable_t pattern0;
static patternTable_t pattern1;
//----------------------------------------------------
int openPPUViewWindow( QWidget *parent )
{
@ -31,11 +73,23 @@ int openPPUViewWindow( QWidget *parent )
ppuViewerDialog_t::ppuViewerDialog_t(QWidget *parent)
: QDialog( parent )
{
QVBoxLayout *mainLayout;
ppuViewWindow = this;
setWindowTitle( tr("PPU Viewer") );
//setLayout( mainLayout );
mainLayout = new QVBoxLayout();
setLayout( mainLayout );
patternView = new ppuPatternView_t(this);
paletteView = new ppuPalatteView_t(this);
mainLayout->addWidget( patternView, 10 );
mainLayout->addWidget( paletteView, 1 );
FCEUD_UpdatePPUView( -1, 1 );
}
//----------------------------------------------------
@ -61,3 +115,249 @@ void ppuViewerDialog_t::closeWindow(void)
deleteLater();
}
//----------------------------------------------------
ppuPatternView_t::ppuPatternView_t(QWidget *parent)
: QWidget(parent)
{
setMinimumWidth( 512 );
setMinimumHeight( 256 );
}
//----------------------------------------------------
ppuPatternView_t::~ppuPatternView_t(void)
{
}
//----------------------------------------------------
void ppuPatternView_t::paintEvent(QPaintEvent *event)
{
int i,j,x,y,w,h,w2,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 / 256;
h = viewHeight / 128;
w2= viewWidth / 2;
xx = 0; yy = 0;
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++)
{
painter.fillRect( xx, yy, w, h, pattern0.tile[j][i].pixel[y][x].color );
yy += h;
}
xx += w;
}
}
}
xx = w2; yy = 0;
for (i=0; i<16; i++) //Columns
{
for (j=0; j<16; j++) //Rows
{
xx = w2 + (i*8)*w;
for (x=0; x < 8; x++)
{
yy = (j*8)*h;
for (y=0; y < 8; y++)
{
painter.fillRect( xx, yy, w, h, pattern1.tile[j][i].pixel[y][x].color );
yy += h;
}
xx += w;
}
}
}
}
//----------------------------------------------------
static void DrawPatternTable( patternTable_t *pattern, uint8_t *table, uint8_t *log, uint8_t pal)
{
int i,j,k,x,y,index=0;
int p=0,tmp;
uint8_t chr0,chr1,logs,shift;
pal <<= 2;
for (i = 0; i < (16 >> PPUView_sprite16Mode); i++) //Columns
{
for (j = 0; j < 16; j++) //Rows
{
//index = (i<<4)|(j<<8);
//printf("Tile: %X%X index:%04X %04X\n", j,i,index, (i<<4)|(j<<8));
//-----------------------------------------------
for (k = 0; k < (PPUView_sprite16Mode + 1); k++)
{
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;
shift=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++;
//pbitmap += (PATTERNBITWIDTH-24);
}
index+=8;
}
//pbitmap -= ((PATTERNBITWIDTH<<(3+PPUView_sprite16Mode))-24);
//------------------------------------------------
}
//pbitmap += (PATTERNBITWIDTH*((8<<PPUView_sprite16Mode)-1));
}
}
//----------------------------------------------------
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)
//{
// return;
//}
// 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,pindex0);
DrawPatternTable( &pattern1,chrcache1,logcache1,pindex1);
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.setPen( pattern0.tile[j][i].pixel[y][x].color );
painter.fillRect( xx, yy, w, h, ppuv_palette[y][x] );
xx += w;
}
yy += h;
}
painter.drawLine( 0, viewHeight / 2, viewWidth, viewHeight / 2 );
}
//----------------------------------------------------

View File

@ -18,6 +18,30 @@
#include "Qt/main.h"
class ppuPatternView_t : public QWidget
{
Q_OBJECT
public:
ppuPatternView_t(QWidget *parent = 0);
~ppuPatternView_t(void);
protected:
void paintEvent(QPaintEvent *event);
};
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
@ -29,6 +53,9 @@ class ppuViewerDialog_t : public QDialog
protected:
//QTimer *inputTimer;
ppuPatternView_t *patternView;
ppuPalatteView_t *paletteView;
void closeEvent(QCloseEvent *bar);
private:

View File

@ -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),\

View File

@ -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
}