From cf2b43f31a2da9b582fa532d12fb36c263bdb906 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sun, 4 Oct 2020 09:54:51 -0400 Subject: [PATCH] First successful viewing of pattern and palatte colors on Qt PPU Viewer. --- src/drivers/Qt/ppuViewer.cpp | 302 ++++++++++++++++++++++++++++++++++- src/drivers/Qt/ppuViewer.h | 27 ++++ src/palette.cpp | 2 +- src/ppu.cpp | 12 +- 4 files changed, 336 insertions(+), 7 deletions(-) diff --git a/src/drivers/Qt/ppuViewer.cpp b/src/drivers/Qt/ppuViewer.cpp index b1e75bb6..35b110f9 100644 --- a/src/drivers/Qt/ppuViewer.cpp +++ b/src/drivers/Qt/ppuViewer.cpp @@ -1,11 +1,20 @@ // 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" @@ -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<>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 ); +} +//---------------------------------------------------- diff --git a/src/drivers/Qt/ppuViewer.h b/src/drivers/Qt/ppuViewer.h index f8734424..b62f48d9 100644 --- a/src/drivers/Qt/ppuViewer.h +++ b/src/drivers/Qt/ppuViewer.h @@ -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: 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 }