From: Shamus Hammons Date: Sat, 1 Dec 2012 21:27:58 +0000 (-0600) Subject: Added Object Processor browser window for debug mode. X-Git-Tag: 2.1.0~9^2~3 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=virtualjaguar;a=commitdiff_plain;h=cdc64706c10d3fe005fecff5d000fe60b3980a3b Added Object Processor browser window for debug mode. --- diff --git a/src/gui/debug/opbrowser.cpp b/src/gui/debug/opbrowser.cpp new file mode 100644 index 0000000..52f40ef --- /dev/null +++ b/src/gui/debug/opbrowser.cpp @@ -0,0 +1,308 @@ +// +// opbrowser.cpp - Jaguar Object Processor browser +// +// by James Hammons +// (C) 2012 Underground Software +// +// JLH = James Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------- +// JLH 12/01/2012 Created this file +// + +// STILL TO DO: +// + +#include "opbrowser.h" +#include "jaguar.h" +#include "memory.h" +#include "op.h" + + +OPBrowserWindow::OPBrowserWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Dialog), +// layout(new QVBoxLayout), text(new QTextBrowser), + layout(new QVBoxLayout), text(new QLabel), + refresh(new QPushButton(tr("Refresh")))//, +// memBase(0) +{ + setWindowTitle(tr("OP Browser")); + + // Need to set the size as well... +// resize(560, 480); + + QFont fixedFont("Lucida Console", 10, QFont::Normal); + text->setFont(fixedFont); +//// layout->setSizeConstraint(QLayout::SetFixedSize); + setLayout(layout); + + layout->addWidget(text); + layout->addWidget(refresh); + + connect(refresh, SIGNAL(clicked()), this, SLOT(RefreshContents())); +} + + +void OPBrowserWindow::RefreshContents(void) +{ + char string[1024];//, buf[64]; + QString opDump; + +#if 0 + for(uint32_t i=0; i<480; i+=16) + { + sprintf(string, "%s%06X: ", (i != 0 ? "
" : ""), memBase + i); + + for(uint32_t j=0; j<16; j++) + { + sprintf(buf, "%02X ", jaguarMainRAM[memBase + i + j]); + strcat(string, buf); + } + + sprintf(buf, "| "); + strcat(string, buf); + + for(uint32_t j=0; j<16; j++) + { + uint8_t c = jaguarMainRAM[memBase + i + j]; + sprintf(buf, "&#%i;", c); + + if (c == 0x20) + sprintf(buf, " "); + + if ((c < 0x20) || ((c > 0x7F) && (c < 0xA0))) + sprintf(buf, "."); + + strcat(string, buf); + } + + memDump += QString(string); + } +#endif + uint32_t olp = OPGetListPointer(); + sprintf(string, "OLP = $%08X

", olp); + opDump += QString(string); + + numberOfObjects = 0; + DiscoverObjects(olp); + DumpObjectList(opDump); + + text->clear(); + text->setText(opDump); +} + + +void OPBrowserWindow::keyPressEvent(QKeyEvent * e) +{ + if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Return) + hide(); +#if 0 + else if (e->key() == Qt::Key_PageUp) + { + memBase -= 480; + + if (memBase < 0) + memBase = 0; + + RefreshContents(); + } + else if (e->key() == Qt::Key_PageDown) + { + memBase += 480; + + if (memBase > (0x200000 - 480)) + memBase = 0x200000 - 480; + + RefreshContents(); + } + else if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Minus) + { + memBase -= 16; + + if (memBase < 0) + memBase = 0; + + RefreshContents(); + } + else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Equal) + { + memBase += 16; + + if (memBase > (0x200000 - 480)) + memBase = 0x200000 - 480; + + RefreshContents(); + } +#endif +} + + +bool OPBrowserWindow::ObjectExists(uint32_t address) +{ + // Yes, we really do a linear search, every time. :-/ + for(uint32_t i=0; i> 21)) & 0x3FFFF8; + + if (objectType == 3) + { + // Recursion needed to follow all links! This does depth-first recursion + // on the not-taken objects + DiscoverObjects(address + 8); + } + + // Get the next object... + address = link; + } + while (objectType != 4); +} + + +void OPBrowserWindow::DumpObjectList(QString & list) +{ + const char * opType[8] = { + "(BITMAP)", "(SCALED BITMAP)", "(GPU INT)", "(BRANCH)", + "(STOP)", "???", "???", "???" + }; + const char * ccType[8] = { + "==", "<", ">", "(opflag set)", + "(second half line)", "?", "?", "?" + }; + char buf[512]; + + for(uint32_t i=0; i> 21)) & 0x3FFFF8; +// WriteLog("%08X: %08X %08X %s", address, hi, lo, opType[objectType]); + sprintf(buf, "%08X: %08X %08X %s -> %08X", address, hi, lo, opType[objectType], link); + list += QString(buf); + + if (objectType == 3) + { + uint16_t ypos = (lo >> 3) & 0x7FF; + uint8_t cc = (lo >> 14) & 0x07; // Proper # of bits == 3 +// WriteLog(" YPOS=%u, CC=%s, link=$%08X", ypos, ccType[cc], link); +// sprintf(buf, " YPOS=%u, CC=%s, link=$%08X", ypos, ccType[cc], link); + sprintf(buf, " YPOS %s %u", ccType[cc], ypos); + list += QString(buf); + } + +// WriteLog("\n"); + list += "
"; + + if (objectType == 0) + DumpFixedObject(list, OPLoadPhrase(address + 0), OPLoadPhrase(address + 8)); + + if (objectType == 1) + DumpScaledObject(list, OPLoadPhrase(address + 0), OPLoadPhrase(address + 8), + OPLoadPhrase(address + 16)); + + if (address == link) // Ruh roh... + { + // Runaway recursive link is bad! +// WriteLog("***** SELF REFERENTIAL LINK *****\n\n"); + sprintf(buf, "***** SELF REFERENTIAL LINK *****

"); + list += QString(buf); + } + } + +// WriteLog("\n"); + list += "
"; +} + + +void OPBrowserWindow::DumpScaledObject(QString & list, uint64_t p0, uint64_t p1, uint64_t p2) +{ + char buf[512]; + +// WriteLog(" %08X %08X\n", (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF)); + sprintf(buf, "_________ %08X %08X
", (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF)); + list += QString(buf); +// WriteLog(" %08X %08X\n", (uint32)(p2>>32), (uint32)(p2&0xFFFFFFFF)); + sprintf(buf, "_________ %08X %08X
", (uint32)(p2>>32), (uint32)(p2&0xFFFFFFFF)); + list += QString(buf); + DumpBitmapCore(list, p0, p1); + uint32 hscale = p2 & 0xFF; + uint32 vscale = (p2 >> 8) & 0xFF; + uint32 remainder = (p2 >> 16) & 0xFF; +// WriteLog(" [hsc: %02X, vsc: %02X, rem: %02X]\n", hscale, vscale, remainder); + sprintf(buf, "[hsc: %02X, vsc: %02X, rem: %02X]
", hscale, vscale, remainder); + list += QString(buf); +} + + +void OPBrowserWindow::DumpFixedObject(QString & list, uint64_t p0, uint64_t p1) +{ + char buf[512]; + +// WriteLog(" %08X %08X\n", (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF)); + sprintf(buf, "          %08X %08X
", (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF)); + list += QString(buf); + DumpBitmapCore(list, p0, p1); +} + + +void OPBrowserWindow::DumpBitmapCore(QString & list, uint64_t p0, uint64_t p1) +{ + char buf[512]; + uint8_t op_bitmap_bit_depth[8] = { 1, 2, 4, 8, 16, 24, 32, 0 }; + + uint32_t bdMultiplier[8] = { 64, 32, 16, 8, 4, 2, 1, 1 }; + uint8_t bitdepth = (p1 >> 12) & 0x07; +//WAS: int16 ypos = ((p0 >> 3) & 0x3FF); // ??? What if not interlaced (/2)? + int16_t ypos = ((p0 >> 3) & 0x7FF); // ??? What if not interlaced (/2)? + int32_t xpos = p1 & 0xFFF; + xpos = (xpos & 0x800 ? xpos | 0xFFFFF000 : xpos); // Sign extend that mutha! + uint32_t iwidth = ((p1 >> 28) & 0x3FF); + uint32_t dwidth = ((p1 >> 18) & 0x3FF); // Unsigned! + uint16_t height = ((p0 >> 14) & 0x3FF); + uint32_t link = ((p0 >> 24) & 0x7FFFF) << 3; + uint32_t ptr = ((p0 >> 43) & 0x1FFFFF) << 3; + uint32_t firstPix = (p1 >> 49) & 0x3F; + uint8_t flags = (p1 >> 45) & 0x0F; + uint8_t idx = (p1 >> 38) & 0x7F; + uint32_t pitch = (p1 >> 15) & 0x07; +// WriteLog(" [%u x %u @ (%i, %u) (iw:%u, dw:%u) (%u bpp), l:%08X, p:%08X fp:%02X, fl:%s%s%s%s, idx:%02X, pt:%02X]\n", +// iwidth * bdMultiplier[bitdepth], +// height, xpos, ypos, iwidth, dwidth, op_bitmap_bit_depth[bitdepth], link, +// ptr, firstPix, (flags&OPFLAG_REFLECT ? "REFLECT " : ""), +// (flags&OPFLAG_RMW ? "RMW " : ""), (flags&OPFLAG_TRANS ? "TRANS " : ""), +// (flags&OPFLAG_RELEASE ? "RELEASE" : ""), idx, pitch); + sprintf(buf, " [%u x %u @ (%i, %u) (iw:%u, dw:%u) (%u bpp), p:%08X fp:%02X, fl:%s%s%s%s, idx:%02X, pt:%02X]
", + iwidth * bdMultiplier[bitdepth], + height, xpos, ypos, iwidth, dwidth, op_bitmap_bit_depth[bitdepth], + ptr, firstPix, (flags&OPFLAG_REFLECT ? "REFLECT " : ""), + (flags&OPFLAG_RMW ? "RMW " : ""), (flags&OPFLAG_TRANS ? "TRANS " : ""), + (flags&OPFLAG_RELEASE ? "RELEASE" : ""), idx, pitch); + list += QString(buf); +} diff --git a/src/gui/debug/opbrowser.h b/src/gui/debug/opbrowser.h new file mode 100644 index 0000000..b2a4028 --- /dev/null +++ b/src/gui/debug/opbrowser.h @@ -0,0 +1,46 @@ +// +// opbrowser.h: Jaguar memory browser +// +// by James Hammons +// (C) 2012 Underground Software +// + +#ifndef __OPBROWSER_H__ +#define __OPBROWSER_H__ + +#include +#include + +class OPBrowserWindow: public QWidget +{ + Q_OBJECT + + public: + OPBrowserWindow(QWidget * parent = 0); + + + public slots: + void RefreshContents(void); + + protected: + void keyPressEvent(QKeyEvent *); + + bool ObjectExists(uint32_t address); + void DiscoverObjects(uint32_t address); + void DumpObjectList(QString &); + void DumpScaledObject(QString &, uint64_t p0, uint64_t p1, uint64_t p2); + void DumpFixedObject(QString &, uint64_t p0, uint64_t p1); + void DumpBitmapCore(QString &, uint64_t p0, uint64_t p1); + + private: + QVBoxLayout * layout; +// QTextBrowser * text; + QLabel * text; + QPushButton * refresh; + +// int32_t memBase; + uint32_t object[8192]; + uint32_t numberOfObjects; +}; + +#endif // __OPBROWSER_H__ diff --git a/src/gui/mainwin.cpp b/src/gui/mainwin.cpp index ec3961c..72869fb 100644 --- a/src/gui/mainwin.cpp +++ b/src/gui/mainwin.cpp @@ -45,6 +45,7 @@ #include "version.h" #include "debug/memorybrowser.h" #include "debug/cpubrowser.h" +#include "debug/opbrowser.h" #include "dac.h" #include "jaguar.h" @@ -100,6 +101,7 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), filePickWin = new FilePickerWindow(this); memBrowseWin = new MemoryBrowserWindow(this); cpuBrowseWin = new CPUBrowserWindow(this); + opBrowseWin = new OPBrowserWindow(this); videoWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -216,6 +218,11 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), // memBrowseAct->setCheckable(true); connect(cpuBrowseAct, SIGNAL(triggered()), this, SLOT(ShowCPUBrowserWin())); + opBrowseAct = new QAction(QIcon(":/res/generic.png"), tr("OP Browser"), this); + opBrowseAct->setStatusTip(tr("Shows the Jaguar OP browser window")); +// memBrowseAct->setCheckable(true); + connect(opBrowseAct, SIGNAL(triggered()), this, SLOT(ShowOPBrowserWin())); + // Misc. connections... connect(filePickWin, SIGNAL(RequestLoad(QString)), this, SLOT(LoadSoftware(QString))); connect(filePickWin, SIGNAL(FilePickerHiding()), this, SLOT(Unpause())); @@ -236,6 +243,7 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), debugMenu = menuBar()->addMenu(tr("&Debug")); debugMenu->addAction(memBrowseAct); debugMenu->addAction(cpuBrowseAct); + debugMenu->addAction(opBrowseAct); } helpMenu = menuBar()->addMenu(tr("&Help")); @@ -263,6 +271,7 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), debugbar = addToolBar(tr("&Debug")); debugbar->addAction(memBrowseAct); debugbar->addAction(cpuBrowseAct); + debugbar->addAction(opBrowseAct); } // Create status bar @@ -872,6 +881,13 @@ void MainWin::ShowCPUBrowserWin(void) } +void MainWin::ShowOPBrowserWin(void) +{ + opBrowseWin->show(); + opBrowseWin->RefreshContents(); +} + + void MainWin::ResizeMainWindow(void) { // videoWidget->setFixedSize(zoomLevel * 320, zoomLevel * (vjs.hardwareTypeNTSC ? 240 : 256)); diff --git a/src/gui/mainwin.h b/src/gui/mainwin.h index fe88892..b1fb71d 100644 --- a/src/gui/mainwin.h +++ b/src/gui/mainwin.h @@ -18,6 +18,7 @@ class HelpWindow; class FilePickerWindow; class MemoryBrowserWindow; class CPUBrowserWindow; +class OPBrowserWindow; class MainWin: public QMainWindow { @@ -58,6 +59,7 @@ class MainWin: public QMainWindow void ShowMemoryBrowserWin(void); void ShowCPUBrowserWin(void); + void ShowOPBrowserWin(void); private: void HandleKeys(QKeyEvent *, bool); @@ -74,6 +76,7 @@ class MainWin: public QMainWindow FilePickerWindow * filePickWin; MemoryBrowserWindow * memBrowseWin; CPUBrowserWindow * cpuBrowseWin; + OPBrowserWindow * opBrowseWin; QTimer * timer; bool running; int zoomLevel; @@ -120,6 +123,7 @@ class MainWin: public QMainWindow QAction * memBrowseAct; QAction * cpuBrowseAct; + QAction * opBrowseAct; QIcon powerGreen; QIcon powerRed; diff --git a/src/jaguar.cpp b/src/jaguar.cpp index cff72cc..e80b356 100644 --- a/src/jaguar.cpp +++ b/src/jaguar.cpp @@ -376,8 +376,21 @@ CD_switch:: -> $306C WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC); uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7); WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack)); + uint32 address = topOfStack - (8 * 4 * 3); + for(int i=0; i<10; i++) - WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4))); + { + WriteLog("%06X:", address); + + for(int j=0; j<8; j++) + { + WriteLog(" %08X", JaguarReadLong(address); + address += 4; + } + + WriteLog("\n"); + } + WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VIDEO)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled"); M68K_show_context(); @@ -1977,7 +1990,7 @@ void JaguarExecuteNew(void) // it will be half this number for a half frame. BUT, since we're counting // HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL. // -// Scanline times are 63.5555... µs in NTSC and 64 µs in PAL +// Scanline times are 63.5555... s in NTSC and 64 s in PAL // Half line times are, naturally, half of this. :-P void HalflineCallback(void) { diff --git a/src/op.cpp b/src/op.cpp index 8708d9b..25322c9 100644 --- a/src/op.cpp +++ b/src/op.cpp @@ -42,10 +42,12 @@ #define CONDITION_OP_FLAG_SET 3 #define CONDITION_SECOND_HALF_LINE 4 +#if 0 #define OPFLAG_RELEASE 8 // Bus release bit #define OPFLAG_TRANS 4 // Transparency bit #define OPFLAG_RMW 2 // Read-Modify-Write bit #define OPFLAG_REFLECT 1 // Horizontal mirror bit +#endif // Private function prototypes @@ -125,6 +127,7 @@ void OPInit(void) OPReset(); } + // // Object Processor reset // @@ -134,6 +137,7 @@ void OPReset(void) objectp_running = 0; } + static const char * opType[8] = { "(BITMAP)", "(SCALED BITMAP)", "(GPU INT)", "(BRANCH)", "(STOP)", "???", "???", "???" }; static const char * ccType[8] = @@ -143,6 +147,7 @@ static uint32 numberOfObjects; //static uint32 objectLink[8192]; //static uint32 numberOfLinks; + void OPDone(void) { //#warning "!!! Fix OL dump so that it follows links !!!" @@ -180,31 +185,46 @@ void OPDone(void) WriteLog("\n"); #else -#warning "!!! Fix lockup in OPDiscoverObjects() !!!" +//#warning "!!! Fix lockup in OPDiscoverObjects() !!!" //temp, to keep the following function from locking up on bad/weird OLs -return; +//return; numberOfObjects = 0; +//printf("OPDiscoverObjects...\n"); OPDiscoverObjects(olp); +//printf("OPDumpObjectList...\n"); OPDumpObjectList(); #endif } -void OPDiscoverObjects(uint32 address) + +bool OPObjectExists(uint32 address) { - // Check to see if we've already seen this object + // Yes, we really do a linear search, every time. :-/ for(uint32 i=0; i> 3) & 0x7FF; - uint8 cc = (lo >> 14) & 0x07; // Proper # of bits == 3 - - // Recursion needed to follow all links! + // Recursion needed to follow all links! This does depth-first recursion + // on the not-taken objects OPDiscoverObjects(address + 8); } - if (address == link) // Ruh roh... - { - // Runaway recursive link is bad! - return; - } - + // Get the next object... address = link; - - // Check to see if we've already seen this object, and add it if not - bool seenObject = false; - - for(uint32 i=0; i>32), (uint32)(p1&0xFFFFFFFF)); DumpBitmapCore(p0, p1); } + void DumpBitmapCore(uint64 p0, uint64 p1) { uint32 bdMultiplier[8] = { 64, 32, 16, 8, 4, 2, 1, 1 }; @@ -427,6 +436,7 @@ void DumpBitmapCore(uint64 p0, uint64 p1) (flags&OPFLAG_RELEASE ? "RELEASE" : ""), idx, pitch); } + // // Object Processor main routine // @@ -865,6 +875,7 @@ OP: Scaled bitmap 4x? 4bpp at 34,? hscale=80 fpix=0 data=000756E8 pitch 1 hflipp } } + // // Store fixed size bitmap in line buffer // @@ -1329,6 +1340,7 @@ if (firstPix) } } + // // Store scaled bitmap in line buffer // diff --git a/src/op.h b/src/op.h index 20e7190..760f593 100644 --- a/src/op.h +++ b/src/op.h @@ -11,6 +11,8 @@ void OPInit(void); void OPReset(void); void OPDone(void); +uint64 OPLoadPhrase(uint32 offset); + void OPProcessList(int scanline, bool render); uint32 OPGetListPointer(void); void OPSetStatusRegister(uint32 data); @@ -22,6 +24,11 @@ void OPSetCurrentObject(uint64 object); //void OPWriteByte(uint32, uint8, uint32 who = UNKNOWN); //void OPWriteWord(uint32, uint16, uint32 who = UNKNOWN); +#define OPFLAG_RELEASE 8 // Bus release bit +#define OPFLAG_TRANS 4 // Transparency bit +#define OPFLAG_RMW 2 // Read-Modify-Write bit +#define OPFLAG_REFLECT 1 // Horizontal mirror bit + // Exported variables extern uint8 objectp_running; diff --git a/virtualjaguar.pro b/virtualjaguar.pro index 7a6992e..7d1164e 100644 --- a/virtualjaguar.pro +++ b/virtualjaguar.pro @@ -75,6 +75,7 @@ HEADERS = \ src/gui/mainwin.h \ src/gui/debug/cpubrowser.h \ src/gui/debug/memorybrowser.h \ + src/gui/debug/opbrowser.h \ # src/gui/sdljoystick.h SOURCES = \ @@ -95,4 +96,5 @@ SOURCES = \ src/gui/mainwin.cpp \ src/gui/debug/cpubrowser.cpp \ src/gui/debug/memorybrowser.cpp \ + src/gui/debug/opbrowser.cpp \ # src/gui/sdljoystick.cpp