From cb1ad9c2c55f96cb8e622de338ef0de91a39301e Mon Sep 17 00:00:00 2001 From: Romulo Fernandes Date: Tue, 23 Oct 2018 21:19:38 -0300 Subject: [PATCH 01/17] Add a label to VDP1 debug window containing the number of draw commands of each type (if any). --- yabause/src/qt/ui/UIDebugVDP1.cpp | 96 +++++++++++++++++++++++++++++++ yabause/src/qt/ui/UIDebugVDP1.ui | 19 ++++++ yabause/src/vdp1.c | 15 +++++ yabause/src/vdp1.h | 20 +++++++ 4 files changed, 150 insertions(+) diff --git a/yabause/src/qt/ui/UIDebugVDP1.cpp b/yabause/src/qt/ui/UIDebugVDP1.cpp index 5c06b7226c..05cc6adc3d 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.cpp +++ b/yabause/src/qt/ui/UIDebugVDP1.cpp @@ -21,6 +21,94 @@ #include #include +#include + + +namespace { + + +struct Vdp1CommandsCount +{ + size_t distortedSprites; + size_t polygons; + size_t polylines; + size_t normalSprites; + size_t scaledSprites; + size_t lines; +}; + +void Vdp1CountCommands(u32 index, Vdp1CommandsCount& cmdCount) +{ + Vdp1CommandType commandType = Vdp1DebugGetCommandType(index); + switch (commandType) { + case VDPCT_DISTORTED_SPRITE: + case VDPCT_DISTORTED_SPRITEN: + cmdCount.distortedSprites++; + break; + case VDPCT_NORMAL_SPRITE: + cmdCount.normalSprites++; + break; + case VDPCT_SCALED_SPRITE: + cmdCount.scaledSprites++; + break; + case VDPCT_POLYGON: + cmdCount.polygons++; + break; + case VDPCT_POLYLINE: + case VDPCT_POLYLINEN: + cmdCount.polylines++; + break; + case VDPCT_LINE: + cmdCount.lines++; + break; + } +} + +std::string buildInfoLabel(Vdp1CommandsCount& cmdCount) +{ + bool previous = false; + std::stringstream infoLabel; + + if (cmdCount.distortedSprites > 0) { + infoLabel << "DistortedSprites: " << cmdCount.distortedSprites; + previous = true; + } + + if (cmdCount.polygons > 0) { + infoLabel << (previous ? ", " : "") << "Polygons: " << cmdCount.polygons; + previous = true; + } + + if (cmdCount.polylines > 0) { + infoLabel << (previous ? ", " : "") << "PolyLines: " << + cmdCount.polylines; + previous = true; + } + + if (cmdCount.normalSprites > 0) { + infoLabel << (previous ? ", " : "") << "Normal Sprites: " << + cmdCount.normalSprites; + previous = true; + } + + if (cmdCount.scaledSprites > 0) { + infoLabel << (previous ? ", " : "") << "Scaled Sprites: " << + cmdCount.scaledSprites; + previous = true; + } + + if (cmdCount.lines > 0) { + infoLabel << (previous ? ", " : "") << "Lines: " << + cmdCount.lines; + previous = true; + } + + return infoLabel.str(); +} + + +} // namespace '' + UIDebugVDP1::UIDebugVDP1( QWidget* p ) : QDialog( p ) @@ -33,6 +121,9 @@ UIDebugVDP1::UIDebugVDP1( QWidget* p ) lwCommandList->clear(); + Vdp1CommandsCount cmdCount; + memset(&cmdCount, 0, sizeof(Vdp1CommandsCount)); + if (Vdp1Ram) { for (int i=0;;i++) @@ -43,6 +134,7 @@ UIDebugVDP1::UIDebugVDP1( QWidget* p ) if (*outstring == '\0') break; + Vdp1CountCommands(i, cmdCount); lwCommandList->addItem(QtYabause::translate(outstring)); } } @@ -51,6 +143,10 @@ UIDebugVDP1::UIDebugVDP1( QWidget* p ) vdp1texturew = vdp1textureh = 1; pbSaveBitmap->setEnabled(vdp1texture ? true : false); + QString infoLabelText(QString::fromStdString(buildInfoLabel(cmdCount))); + lVDP1Info->setText(infoLabelText); + lVDP1Info->setToolTip(infoLabelText); + // retranslate widgets QtYabause::retranslateWidget( this ); } diff --git a/yabause/src/qt/ui/UIDebugVDP1.ui b/yabause/src/qt/ui/UIDebugVDP1.ui index 370f2ead3b..88606ba035 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.ui +++ b/yabause/src/qt/ui/UIDebugVDP1.ui @@ -78,6 +78,18 @@ 0 + + background-color: transparent; + + + + + 0 + 0 + 0 + + + @@ -139,6 +151,13 @@ + + + + TextLabel + + + diff --git a/yabause/src/vdp1.c b/yabause/src/vdp1.c index ab3b375e31..c05ca86cff 100644 --- a/yabause/src/vdp1.c +++ b/yabause/src/vdp1.c @@ -785,6 +785,21 @@ static u32 Vdp1DebugGetCommandNumberAddr(u32 number) ////////////////////////////////////////////////////////////////////////////// +Vdp1CommandType Vdp1DebugGetCommandType(u32 number) +{ + u32 addr; + if ((addr = Vdp1DebugGetCommandNumberAddr(number)) != 0xFFFFFFFF) + { + const u16 command = T1ReadWord(Vdp1Ram, addr); + if (command & 0x8000) + return VDPCT_DRAW_END; + else if ((command & 0x000F) < VDPCT_INVALID) + return (Vdp1CommandType) (command & 0x000F); + } + + return VDPCT_INVALID; +} + void Vdp1DebugGetCommandNumberName(u32 number, char *outstring) { u32 addr; diff --git a/yabause/src/vdp1.h b/yabause/src/vdp1.h index 954318a3f5..a06878f433 100644 --- a/yabause/src/vdp1.h +++ b/yabause/src/vdp1.h @@ -134,6 +134,25 @@ typedef struct { extern Vdp1External_struct Vdp1External; +typedef enum { + VDPCT_NORMAL_SPRITE = 0, + VDPCT_SCALED_SPRITE = 1, + VDPCT_DISTORTED_SPRITE = 2, + VDPCT_DISTORTED_SPRITEN = 3, + VDPCT_POLYGON = 4, + VDPCT_POLYLINE = 5, + VDPCT_LINE = 6, + VDPCT_POLYLINEN = 7, + VDPCT_USER_CLIPPING_COORDINATES = 8, + VDPCT_SYSTEM_CLIPPING_COORDINATES = 9, + VDPCT_LOCAL_COORDINATES = 10, + VDPCT_USER_CLIPPING_COORDINATESN = 11, + + VDPCT_INVALID = 12, + VDPCT_DRAW_END + +} Vdp1CommandType; + typedef struct { u16 CMDCTRL; @@ -182,6 +201,7 @@ int Vdp1SaveState(FILE *fp); int Vdp1LoadState(FILE *fp, int version, int size); void Vdp1DebugGetCommandNumberName(u32 number, char *outstring); +Vdp1CommandType Vdp1DebugGetCommandType(u32 number); void Vdp1DebugCommand(u32 number, char *outstring); u32 *Vdp1DebugTexture(u32 number, int *w, int *h); void ToggleVDP1(void); From 116ceac2bfc84eda49a2e53eefc9b0e689300fd3 Mon Sep 17 00:00:00 2001 From: Romulo Fernandes Date: Tue, 23 Oct 2018 21:27:34 -0300 Subject: [PATCH 02/17] Add missing space on "Distorted Sprites" --- yabause/src/qt/ui/UIDebugVDP1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yabause/src/qt/ui/UIDebugVDP1.cpp b/yabause/src/qt/ui/UIDebugVDP1.cpp index 05cc6adc3d..72d5be60ba 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.cpp +++ b/yabause/src/qt/ui/UIDebugVDP1.cpp @@ -70,7 +70,7 @@ std::string buildInfoLabel(Vdp1CommandsCount& cmdCount) std::stringstream infoLabel; if (cmdCount.distortedSprites > 0) { - infoLabel << "DistortedSprites: " << cmdCount.distortedSprites; + infoLabel << "Distorted Sprites: " << cmdCount.distortedSprites; previous = true; } From 96d5204242f3005b8320b3ef26530615d27ed9ad Mon Sep 17 00:00:00 2001 From: Romulo Fernandes Date: Sun, 10 Mar 2019 01:27:10 -0300 Subject: [PATCH 03/17] Add a button to save raw sprite data. --- yabause/src/qt/ui/UIDebugVDP1.cpp | 38 ++++++++++++ yabause/src/qt/ui/UIDebugVDP1.h | 3 + yabause/src/qt/ui/UIDebugVDP1.ui | 7 +++ yabause/src/vdp1.c | 99 +++++++++++++++++++++++++++++++ yabause/src/vdp1.h | 1 + 5 files changed, 148 insertions(+) diff --git a/yabause/src/qt/ui/UIDebugVDP1.cpp b/yabause/src/qt/ui/UIDebugVDP1.cpp index 72d5be60ba..32e43ed1f5 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.cpp +++ b/yabause/src/qt/ui/UIDebugVDP1.cpp @@ -140,8 +140,11 @@ UIDebugVDP1::UIDebugVDP1( QWidget* p ) } vdp1texture = NULL; + vdp1RawTexture = NULL; + vdp1RawNumBytes = 0; vdp1texturew = vdp1textureh = 1; pbSaveBitmap->setEnabled(vdp1texture ? true : false); + pbSaveRawSprite->setEnabled(vdp1RawTexture ? true : false); QString infoLabelText(QString::fromStdString(buildInfoLabel(cmdCount))); lVDP1Info->setText(infoLabelText); @@ -155,6 +158,9 @@ UIDebugVDP1::~UIDebugVDP1() { if (vdp1texture) free(vdp1texture); + + if (vdp1RawTexture) + free(vdp1RawTexture); } void UIDebugVDP1::on_lwCommandList_itemSelectionChanged () @@ -170,8 +176,14 @@ void UIDebugVDP1::on_lwCommandList_itemSelectionChanged () if (vdp1texture) free(vdp1texture); + if (vdp1RawTexture) + free(vdp1RawTexture); + vdp1texture = Vdp1DebugTexture(cursel, &vdp1texturew, &vdp1textureh); + vdp1RawTexture = Vdp1DebugRawTexture(cursel, &vdp1texturew, &vdp1textureh, &vdp1RawNumBytes); + pbSaveBitmap->setEnabled(vdp1texture ? true : false); + pbSaveRawSprite->setEnabled(vdp1RawTexture ? true : false); // Redraw texture QGraphicsScene *scene = gvTexture->scene(); @@ -205,3 +217,29 @@ void UIDebugVDP1::on_pbSaveBitmap_clicked () if ( !img.save( s ) ) CommonDialogs::information( QtYabause::translate( "An error occured while writing file." ) ); } + +void UIDebugVDP1::on_pbSaveRawSprite_clicked () +{ + QStringList filters( QString::fromUtf8( "*.bin" ) ); + + // request a file to save to to user + const QString answer = CommonDialogs::getSaveFileName( QString(), + QtYabause::translate( "Choose a location for your raw data" ), filters.join( ";;" ) ); + + // write image if ok + if ( !answer.isEmpty() ) { + bool fileWritten = false; + + QFile outputFile(answer); + if (outputFile.open(QIODevice::OpenModeFlag::WriteOnly | QIODevice::OpenModeFlag::Unbuffered)) + { + if (outputFile.write(reinterpret_cast(vdp1RawTexture), vdp1RawNumBytes) == vdp1RawNumBytes) + fileWritten = true; + + outputFile.close(); + } + + if (!fileWritten) + CommonDialogs::information( QtYabause::translate( "An error occured while writing file." ) ); + } +} diff --git a/yabause/src/qt/ui/UIDebugVDP1.h b/yabause/src/qt/ui/UIDebugVDP1.h index a99608588b..142bbb010c 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.h +++ b/yabause/src/qt/ui/UIDebugVDP1.h @@ -31,11 +31,14 @@ class UIDebugVDP1 : public QDialog, public Ui::UIDebugVDP1 protected: u32 *vdp1texture; + u8 *vdp1RawTexture; + int vdp1RawNumBytes; int vdp1texturew, vdp1textureh; protected slots: void on_lwCommandList_itemSelectionChanged (); void on_pbSaveBitmap_clicked (); + void on_pbSaveRawSprite_clicked (); }; diff --git a/yabause/src/qt/ui/UIDebugVDP1.ui b/yabause/src/qt/ui/UIDebugVDP1.ui index 88606ba035..c8800f4836 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.ui +++ b/yabause/src/qt/ui/UIDebugVDP1.ui @@ -127,6 +127,13 @@ + + + + Save RAW + + + diff --git a/yabause/src/vdp1.c b/yabause/src/vdp1.c index c05ca86cff..b0255ee2dd 100644 --- a/yabause/src/vdp1.c +++ b/yabause/src/vdp1.c @@ -1496,6 +1496,105 @@ u32 *Vdp1DebugTexture(u32 number, int *w, int *h) return texture; } +u8 *Vdp1DebugRawTexture(u32 cmdNumber, int *width, int *height, int *numBytes) +{ + u16 cmdRaw; + vdp1cmd_struct cmd; + u32 cmdAddress; + u8 *texture = NULL; + + // Initial number of bytes written to texture + *numBytes = 0; + + if ((cmdAddress = Vdp1DebugGetCommandNumberAddr(cmdNumber)) == 0xFFFFFFFF) + return NULL; + + cmdRaw = T1ReadWord(Vdp1Ram, cmdAddress); + + if (cmdRaw & 0x8000) + // Draw End + return NULL; + + if (cmdRaw & 0x4000) + // Command Skipped + return NULL; + + Vdp1ReadCommand(&cmd, cmdAddress, Vdp1Ram); + + const int spriteCmdType = ((cmd.CMDPMOD >> 3) & 0x7); + switch (cmd.CMDCTRL & 0x000F) + { + case 0: // Normal Sprite + case 1: // Scaled Sprite + case 2: // Distorted Sprite + case 3: // Distorted Sprite * + width[0] = (cmd.CMDSIZE & 0x3F00) >> 5; + height[0] = cmd.CMDSIZE & 0xFF; + + switch (spriteCmdType) { + // 0: 4 bpp Bank mode + // 1: 4 bpp LUT mode + case 0: + case 1: + numBytes[0] = 0.5 * width[0] * height[0]; + texture = (u8*) malloc(numBytes[0]); + break; + // 2: 8 bpp(64 color) Bank mode + // 3: 8 bpp(128 color) Bank mode + // 4: 8 bpp(256 color) Bank mode + case 2: + case 3: + case 4: + numBytes[0] = width[0] * height[0]; + texture = (u8*) malloc(numBytes[0]); + break; + // 5: 16 bpp Bank mode + case 5: + numBytes[0] = 2 * width[0] * height[0]; + texture = (u8*) malloc(numBytes[0]); + break; + default: + texture = NULL; + break; + } + + if (texture == NULL) + return NULL; + + break; + case 4: // Polygon + case 5: // Polyline + case 6: // Line + case 7: // Polyline * + // Do 1x1 pixel + width[0] = 1; + height[0] = 1; + texture = (u8*) malloc(sizeof(u16)); + + if (texture == NULL) + return NULL; + + *numBytes = 2; + memcpy(texture, &cmd.CMDCOLR, sizeof(u16)); + return texture; + case 8: // User Clipping + case 9: // System Clipping + case 10: // Local Coordinates + case 11: // User Clipping * + return NULL; + default: // Invalid command + return NULL; + } + + // Read texture data directly from VRAM. + for (u32 i = 0; i < *numBytes; ++i) + { + texture[ i ] = T1ReadByte(Vdp1Ram, ((cmd.CMDSRCA * 8) + i) & 0x7FFFF); + } + + return texture; +} + ////////////////////////////////////////////////////////////////////////////// void ToggleVDP1(void) diff --git a/yabause/src/vdp1.h b/yabause/src/vdp1.h index a06878f433..6c4c4422e0 100644 --- a/yabause/src/vdp1.h +++ b/yabause/src/vdp1.h @@ -204,6 +204,7 @@ void Vdp1DebugGetCommandNumberName(u32 number, char *outstring); Vdp1CommandType Vdp1DebugGetCommandType(u32 number); void Vdp1DebugCommand(u32 number, char *outstring); u32 *Vdp1DebugTexture(u32 number, int *w, int *h); +u8 *Vdp1DebugRawTexture(u32 number, int *w, int *h, int *numBytes); void ToggleVDP1(void); void VideoDisableGL(void); From a47b187e5bc858d6c85ea238cc79aca8f3847a53 Mon Sep 17 00:00:00 2001 From: Romulo Fernandes Date: Sun, 10 Mar 2019 01:27:38 -0300 Subject: [PATCH 04/17] Increase memory editor default window size to 800x600 --- yabause/src/qt/ui/UIMemoryEditor.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yabause/src/qt/ui/UIMemoryEditor.ui b/yabause/src/qt/ui/UIMemoryEditor.ui index c5bebf8df8..3fe0de778b 100644 --- a/yabause/src/qt/ui/UIMemoryEditor.ui +++ b/yabause/src/qt/ui/UIMemoryEditor.ui @@ -6,8 +6,8 @@ 0 0 - 518 - 363 + 800 + 600 From c840cc8285990a60102fc9a5b1a874aa34904492 Mon Sep 17 00:00:00 2001 From: Romulo Fernandes Date: Sun, 10 Mar 2019 01:27:51 -0300 Subject: [PATCH 05/17] Auto select text when opening the hex input dialog --- yabause/src/qt/ui/UIHexInput.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yabause/src/qt/ui/UIHexInput.cpp b/yabause/src/qt/ui/UIHexInput.cpp index 34d72a8491..fc746a14c7 100644 --- a/yabause/src/qt/ui/UIHexInput.cpp +++ b/yabause/src/qt/ui/UIHexInput.cpp @@ -34,8 +34,10 @@ UIHexInput::UIHexInput( u32 value, int size, QWidget* p ) this->value = value; this->size = size; - leValue->setValidator(new HexValidator(0x00000000, 0xFFFFFFFF >> (4-size * 8) , leValue)); - leValue->setText(text); + leValue->setValidator(new HexValidator(0x00000000, 0xFFFFFFFF >> (4 - size * 8), leValue)); + leValue->setText(text); + leValue->setSelection(0, text.size()); + leValue->setFocus(); // retranslate widgets QtYabause::retranslateWidget( this ); From 37d3cc9b15d69c2d45585561d2e4629df4c15151 Mon Sep 17 00:00:00 2001 From: Romulo Fernandes Date: Wed, 26 May 2021 19:58:58 +0200 Subject: [PATCH 06/17] Fixed reading cdblock data transfer register as a word Keep last rendered image when paused vdp1 draw commands now highlight on framebuffer --- yabause/ChangeLog | 6 + yabause/src/Makefile.dc | 2 +- yabause/src/cocoa/Yabause-Info.plist | 2 +- .../cocoa/Yabause.xcodeproj/project.pbxproj | 4 +- yabause/src/cs2.c | 63 ++++++++++ yabause/src/gtk/doc/yabause.1 | 2 +- yabause/src/qt/YabauseGL.cpp | 75 +++++++++++- yabause/src/qt/YabauseGL.h | 14 +++ yabause/src/qt/YabauseGLProxy.cpp | 26 +++- yabause/src/qt/YabauseGLProxy.h | 2 + yabause/src/qt/YabauseSoftGL.cpp | 12 ++ yabause/src/qt/YabauseSoftGL.h | 3 + yabause/src/qt/doc/yabause.1 | 2 +- yabause/src/qt/ui/UIDebugVDP1.cpp | 113 +++++++++++++----- yabause/src/qt/ui/UIDebugVDP1.h | 4 +- yabause/src/qt/ui/UIYabause.cpp | 7 +- yabause/src/vdp1.c | 63 ++++++++++ yabause/src/vdp1.h | 2 + 18 files changed, 364 insertions(+), 38 deletions(-) diff --git a/yabause/ChangeLog b/yabause/ChangeLog index e5c945d9db..620f23d435 100644 --- a/yabause/ChangeLog +++ b/yabause/ChangeLog @@ -1,3 +1,9 @@ +0.9.15 -> 0.9.16 + general: + - Fixed reading cdblock data transfer register as a word + qt: + - Keep last rendered image when paused + - vdp1 draw commands now highlight on framebuffer 0.9.14 -> 0.9.15 general: - Added CCD (CloneCD) file format support (CyberWarriorX) diff --git a/yabause/src/Makefile.dc b/yabause/src/Makefile.dc index 0cfc623756..bed235aaed 100644 --- a/yabause/src/Makefile.dc +++ b/yabause/src/Makefile.dc @@ -22,7 +22,7 @@ all: yabause.bin include $(KOS_BASE)/Makefile.rules -KOS_CFLAGS += -I. -DDEBUG -DNO_CLI -DVERSION="0.9.15" +KOS_CFLAGS += -I. -DDEBUG -DNO_CLI -DVERSION="0.9.16" KOS_ASFLAGS += -g OBJS = bios.o cdbase.o cheat.o cs0.o cs1.o cs2.o debug.o error.o m68kd.o \ diff --git a/yabause/src/cocoa/Yabause-Info.plist b/yabause/src/cocoa/Yabause-Info.plist index 60130e58d1..748530aaa8 100644 --- a/yabause/src/cocoa/Yabause-Info.plist +++ b/yabause/src/cocoa/Yabause-Info.plist @@ -19,7 +19,7 @@ CFBundleSignature ???? CFBundleShortVersionString - 0.9.15 + 0.9.16 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} CFBundleVersion diff --git a/yabause/src/cocoa/Yabause.xcodeproj/project.pbxproj b/yabause/src/cocoa/Yabause.xcodeproj/project.pbxproj index df57f6199d..0e40e583f3 100644 --- a/yabause/src/cocoa/Yabause.xcodeproj/project.pbxproj +++ b/yabause/src/cocoa/Yabause.xcodeproj/project.pbxproj @@ -750,7 +750,7 @@ HAVE_STRCASECMP, "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1)", ); - GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "VERSION=\\\"0.9.15\\\""; + GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "VERSION=\\\"0.9.16\\\""; GCC_VERSION = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; @@ -779,7 +779,7 @@ HAVE_STRCASECMP, "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1)", ); - GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "VERSION=\\\"0.9.15\\\""; + GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "VERSION=\\\"0.9.16\\\""; GCC_VERSION = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; diff --git a/yabause/src/cs2.c b/yabause/src/cs2.c index f8e4e3fe22..7f38e758e4 100644 --- a/yabause/src/cs2.c +++ b/yabause/src/cs2.c @@ -147,6 +147,7 @@ void FASTCALL Cs2WriteByte(SH2_struct *sh, u32 addr, u8 val) * \bug Mapping isn't quite correct(as noted in source) */ u16 FASTCALL Cs2ReadWord(SH2_struct *sh, u32 addr) { + s32 i; u16 val = 0; addr &= 0xFFFFF; // fix me(I should really have proper mapping) @@ -187,6 +188,68 @@ u16 FASTCALL Cs2ReadWord(SH2_struct *sh, u32 addr) { return Cs2Area->reg.CR4; case 0x90028: case 0x9002A: return Cs2Area->reg.MPEGRGB; + case 0x90000: + // transfer data + if (Cs2Area->datatranstype != CDB_DATATRANSTYPE_INVALID) + { + // get sector + + // Make sure we still have sectors to transfer + if (Cs2Area->datanumsecttrans < Cs2Area->datasectstotrans) + { + // Transfer Data + const u8 *ptr = &Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans]->data[Cs2Area->datatransoffset]; + + if (Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans] == NULL) + { + CDLOG("cs2\t: datatranspartition->block[Cs2Area->datanumsecttrans] was NULL"); + return 0; + } +#ifdef WORDS_BIGENDIAN + val = *((const u16 *) ptr); +#else + val = BSWAP16(*((const u16 *) ptr)); +#endif + + // increment datatransoffset/cdwnum + Cs2Area->cdwnum += 2; + Cs2Area->datatransoffset += 2; + + // Make sure we're not beyond the sector size boundary + if (Cs2Area->datatransoffset >= Cs2Area->datatranspartition->block[Cs2Area->datanumsecttrans]->size) + { + Cs2Area->datatransoffset = 0; + Cs2Area->datanumsecttrans++; + } + } + else + { + if (Cs2Area->datatranstype == CDB_DATATRANSTYPE_GETDELSECTOR) + { + // Ok, so we don't have any more sectors to + // transfer, might as well delete them all. + + Cs2Area->datatranstype = CDB_DATATRANSTYPE_INVALID; + + // free blocks + for (i = Cs2Area->datatranssectpos; i < (Cs2Area->datatranssectpos+Cs2Area->datasectstotrans); i++) + { + Cs2FreeBlock(Cs2Area->datatranspartition->block[i]); + Cs2Area->datatranspartition->block[i] = NULL; + Cs2Area->datatranspartition->blocknum[i] = 0xFF; + } + + // sort remaining blocks + Cs2SortBlocks(Cs2Area->datatranspartition); + + Cs2Area->datatranspartition->size -= Cs2Area->cdwnum; + Cs2Area->datatranspartition->numblocks -= Cs2Area->datasectstotrans; + + CDLOG("cs2\t: datatranspartition->size = %x\n", Cs2Area->datatranspartition->size); + } + } + } + break; case 0x98000: // transfer info switch (Cs2Area->infotranstype) { diff --git a/yabause/src/gtk/doc/yabause.1 b/yabause/src/gtk/doc/yabause.1 index 3e7d55e0dc..e20c09c6ce 100644 --- a/yabause/src/gtk/doc/yabause.1 +++ b/yabause/src/gtk/doc/yabause.1 @@ -1,4 +1,4 @@ -.TH YABAUSE 1 "July 13, 2016" "yabause-0.9.15" +.TH YABAUSE 1 "May 26, 2021" "yabause-0.9.16" .SH NAME yabause \- Yet Another Buggy And Uncomplete Saturn Emulator .SH SYNOPSIS diff --git a/yabause/src/qt/YabauseGL.cpp b/yabause/src/qt/YabauseGL.cpp index 3d3cb75d5d..31386b06b8 100644 --- a/yabause/src/qt/YabauseGL.cpp +++ b/yabause/src/qt/YabauseGL.cpp @@ -20,9 +20,12 @@ */ #include "YabauseGL.h" #include "QtYabause.h" +#include YabauseGL::YabauseGL( QWidget* p ) - : QGLWidget( p ) + : QGLWidget( p ), + lastRenderedScreen(nullptr), + overlayPauseImage(nullptr) { setFocusPolicy( Qt::StrongFocus ); @@ -30,6 +33,20 @@ YabauseGL::YabauseGL( QWidget* p ) p->setFocusPolicy( Qt::StrongFocus ); setFocusProxy( p ); } + + constexpr size_t arraySizes = 704 * 512 * sizeof(uint32_t); + lastRenderedScreen = new uint32_t[ arraySizes ]; + overlayPauseImage = new uint32_t[ arraySizes ]; + memset(lastRenderedScreen, 0, arraySizes); + memset(overlayPauseImage, 0, arraySizes); + + paused = false; +} + +YabauseGL::~YabauseGL() +{ + delete [] lastRenderedScreen; + delete [] overlayPauseImage; } void YabauseGL::showEvent( QShowEvent* e ) @@ -44,10 +61,66 @@ void YabauseGL::showEvent( QShowEvent* e ) void YabauseGL::resizeGL( int w, int h ) { updateView( QSize( w, h ) ); } +void YabauseGL::snapshotView() +{ + int width, height, interlace; + VIDCore->GetNativeResolution( &width, &height, &interlace ); + + const size_t totalSize = static_cast(width) * static_cast(height) * + sizeof(uint32_t); + + memcpy( lastRenderedScreen, dispbuffer, totalSize ); + memset( overlayPauseImage, 0, totalSize ); +} + +void YabauseGL::updatePausedView( const QSize& s ) +{ + // Paint static image + int width, height, interlace; + VIDCore->GetNativeResolution( &width, &height, &interlace ); + + glViewport( 0, 0, s.width(), s.height() ); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, + lastRenderedScreen); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + QMutexLocker lock(&overlayMutex); + + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, + overlayPauseImage); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisable(GL_BLEND); + + swapBuffers(); +} + +void YabauseGL::paintGL() +{ + if (paused) + updatePausedView( size() ); +} + +void YabauseGL::setPaused( bool isPaused ) +{ paused = isPaused; } + +QPair YabauseGL::getOverlayPausedImage() +{ + return QPair(overlayPauseImage, &overlayMutex); +} + void YabauseGL::updateView( const QSize& s ) { const QSize size = s.isValid() ? s : this->size(); glViewport( 0, 0, size.width(), size.height() ); if ( VIDCore ) VIDCore->Resize( size.width(), size.height(), 0 ); + + if ( paused ) + updatePausedView( s ); } diff --git a/yabause/src/qt/YabauseGL.h b/yabause/src/qt/YabauseGL.h index 7b3f52f159..c4310f613b 100644 --- a/yabause/src/qt/YabauseGL.h +++ b/yabause/src/qt/YabauseGL.h @@ -22,6 +22,8 @@ #define YABAUSEGL_H #include +#include +#include class YabauseGL : public QGLWidget { @@ -29,10 +31,22 @@ class YabauseGL : public QGLWidget public: YabauseGL( QWidget* parent = 0 ); + ~YabauseGL(); + void updatePausedView( const QSize& size = QSize() ); void updateView( const QSize& size = QSize() ); + void snapshotView(); + + void paintGL() override; + void setPaused(bool isPaused); + QPair getOverlayPausedImage(); protected: + bool paused; + uint32_t* lastRenderedScreen; + uint32_t* overlayPauseImage; + QMutex overlayMutex; + virtual void showEvent( QShowEvent* event ); virtual void resizeGL( int w, int h ); }; diff --git a/yabause/src/qt/YabauseGLProxy.cpp b/yabause/src/qt/YabauseGLProxy.cpp index 12706f1ff7..a402aa0d0a 100644 --- a/yabause/src/qt/YabauseGLProxy.cpp +++ b/yabause/src/qt/YabauseGLProxy.cpp @@ -32,11 +32,33 @@ YabauseGLProxy::YabauseGLProxy( QWidget* parent, int impl ) mImpl = -1; select( parent, impl ); } + +void YabauseGLProxy::snapshotView() +{ + if (mImpl == YabauseGLProxy::SOFTWARE) + mYabauseSoft->snapshotView(); + else + mYabauseGL->snapshotView(); +} + +void YabauseGLProxy::setPaused(bool isPaused) +{ + if (mImpl == YabauseGLProxy::SOFTWARE) + mYabauseSoft->setPaused( isPaused ); + else + mYabauseGL->setPaused( isPaused ); +} void YabauseGLProxy::updateView( const QSize& size ) { - if (mImpl == YabauseGLProxy::SOFTWARE) mYabauseSoft->updateView(size); - else mYabauseGL->updateView(size); + if (mImpl == YabauseGLProxy::SOFTWARE) + { + mYabauseSoft->updateView(size); + } + else + { + mYabauseGL->updateView(size); + } } void YabauseGLProxy::swapBuffers() diff --git a/yabause/src/qt/YabauseGLProxy.h b/yabause/src/qt/YabauseGLProxy.h index 2e1bf7af09..c6201ac151 100644 --- a/yabause/src/qt/YabauseGLProxy.h +++ b/yabause/src/qt/YabauseGLProxy.h @@ -39,7 +39,9 @@ class YabauseGLProxy : public QObject static const int SOFTWARE; YabauseGLProxy( QWidget* parent = 0, int impl = DEFAULT ); + void setPaused(bool paused); + void snapshotView(); void updateView( const QSize& size = QSize() ); virtual void swapBuffers(); QImage grabFrameBuffer(bool withAlpha = false); diff --git a/yabause/src/qt/YabauseSoftGL.cpp b/yabause/src/qt/YabauseSoftGL.cpp index afaa59ed79..eecabbf1e2 100644 --- a/yabause/src/qt/YabauseSoftGL.cpp +++ b/yabause/src/qt/YabauseSoftGL.cpp @@ -42,6 +42,18 @@ void YabauseSoftGL::showEvent( QShowEvent* e ) void YabauseSoftGL::resizeGL( int w, int h ) { updateView( QSize( w, h ) ); } +void YabauseSoftGL::snapshotView() +{ +} + +void YabauseSoftGL::setPaused( bool isPaused ) +{ +} + +void YabauseSoftGL::updatePausedView( const QSize& s ) +{ +} + void YabauseSoftGL::updateView( const QSize& s ) { } diff --git a/yabause/src/qt/YabauseSoftGL.h b/yabause/src/qt/YabauseSoftGL.h index a1673e7fd6..430b0b16d0 100644 --- a/yabause/src/qt/YabauseSoftGL.h +++ b/yabause/src/qt/YabauseSoftGL.h @@ -31,6 +31,9 @@ class YabauseSoftGL : public QWidget public: YabauseSoftGL( QWidget* parent = 0 ); + void setPaused(bool isPaused); + void updatePausedView( const QSize& s ); + void snapshotView(); void updateView( const QSize& size = QSize() ); virtual void swapBuffers(); QImage grabFrameBuffer(bool withAlpha = false); diff --git a/yabause/src/qt/doc/yabause.1 b/yabause/src/qt/doc/yabause.1 index 53329c039f..9ae78c394a 100644 --- a/yabause/src/qt/doc/yabause.1 +++ b/yabause/src/qt/doc/yabause.1 @@ -1,4 +1,4 @@ -.TH YABAUSE 1 "July 13, 2016" "yabause-0.9.15" +.TH YABAUSE 1 "May 26, 2021" "yabause-0.9.16" .SH NAME yabause \- Yet Another Buggy And Uncomplete Saturn Emulator .SH SYNOPSIS diff --git a/yabause/src/qt/ui/UIDebugVDP1.cpp b/yabause/src/qt/ui/UIDebugVDP1.cpp index 32e43ed1f5..1e65562ae5 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.cpp +++ b/yabause/src/qt/ui/UIDebugVDP1.cpp @@ -36,6 +36,37 @@ struct Vdp1CommandsCount size_t scaledSprites; size_t lines; }; + +// +// Bresenham implementation from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#C +// +void drawLine(uint32_t color, uint32_t* buffer, int width, int height, + int x0, int y0, int x1, int y1) +{ + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = (dx > dy ? dx : -dy) / 2, e2; + + for(;;) + { + buffer[y0 * width + x0] = color; + if (x0 == x1 && y0 == y1) + break; + + e2 = err; + if (e2 > -dx) + { + err -= dy; + x0 += sx; + } + + if (e2 < dy) + { + err += dx; + y0 += sy; + } + } +} void Vdp1CountCommands(u32 index, Vdp1CommandsCount& cmdCount) { @@ -110,45 +141,46 @@ std::string buildInfoLabel(Vdp1CommandsCount& cmdCount) } // namespace '' -UIDebugVDP1::UIDebugVDP1( QWidget* p ) +UIDebugVDP1::UIDebugVDP1( QWidget* p, QWidget* glWidget ) : QDialog( p ) { // setup dialog setupUi( this ); + yabauseGL = dynamic_cast(glWidget); - QGraphicsScene *scene=new QGraphicsScene(this); - gvTexture->setScene(scene); + QGraphicsScene *scene=new QGraphicsScene(this); + gvTexture->setScene(scene); - lwCommandList->clear(); + lwCommandList->clear(); - Vdp1CommandsCount cmdCount; - memset(&cmdCount, 0, sizeof(Vdp1CommandsCount)); + Vdp1CommandsCount cmdCount; + memset(&cmdCount, 0, sizeof(Vdp1CommandsCount)); - if (Vdp1Ram) - { - for (int i=0;;i++) - { - char outstring[256]; + if (Vdp1Ram) + { + for (int i=0;;i++) + { + char outstring[256]; - Vdp1DebugGetCommandNumberName(i, outstring); - if (*outstring == '\0') - break; + Vdp1DebugGetCommandNumberName(i, outstring); + if (*outstring == '\0') + break; - Vdp1CountCommands(i, cmdCount); - lwCommandList->addItem(QtYabause::translate(outstring)); - } - } + Vdp1CountCommands(i, cmdCount); + lwCommandList->addItem(QtYabause::translate(outstring)); + } + } - vdp1texture = NULL; - vdp1RawTexture = NULL; - vdp1RawNumBytes = 0; - vdp1texturew = vdp1textureh = 1; - pbSaveBitmap->setEnabled(vdp1texture ? true : false); - pbSaveRawSprite->setEnabled(vdp1RawTexture ? true : false); + vdp1texture = NULL; + vdp1RawTexture = NULL; + vdp1RawNumBytes = 0; + vdp1texturew = vdp1textureh = 1; + pbSaveBitmap->setEnabled(vdp1texture ? true : false); + pbSaveRawSprite->setEnabled(vdp1RawTexture ? true : false); - QString infoLabelText(QString::fromStdString(buildInfoLabel(cmdCount))); - lVDP1Info->setText(infoLabelText); - lVDP1Info->setToolTip(infoLabelText); + QString infoLabelText(QString::fromStdString(buildInfoLabel(cmdCount))); + lVDP1Info->setText(infoLabelText); + lVDP1Info->setToolTip(infoLabelText); // retranslate widgets QtYabause::retranslateWidget( this ); @@ -194,6 +226,33 @@ void UIDebugVDP1::on_lwCommandList_itemSelectionChanged () scene->setSceneRect(scene->itemsBoundingRect()); gvTexture->fitInView(scene->sceneRect()); gvTexture->invalidateScene(); + + // Paint overlay if possible + if (yabauseGL != nullptr) + { + int width, height, interlace; + VIDCore->GetNativeResolution(&width, &height, &interlace); + + auto overlayPair = yabauseGL->getOverlayPausedImage(); + QMutexLocker lock(overlayPair.second); + + uint32_t* pauseImage = overlayPair.first; + memset( pauseImage, 0, width * height * sizeof(uint32_t) ); + + int x0, y0, x1, y1, x2, y2, x3, y3; + if (Vdp1DebugCommandVertices(cursel, &x0, &y0, &x1, &y1, &x2, &y2, &x3, &y3) == 0) + { + const uint32_t color = 0xff0000dd; + drawLine(color, pauseImage, width, height, x0, y0, x1, y1); + drawLine(color, pauseImage, width, height, x1, y1, x2, y2); + drawLine(color, pauseImage, width, height, x2, y2, x3, y3); + drawLine(color, pauseImage, width, height, x3, y3, x0, y0); + + lock.unlock(); + yabauseGL->repaint(); + yabauseGL->updatePausedView(yabauseGL->size()); + } + } } void UIDebugVDP1::on_pbSaveBitmap_clicked () diff --git a/yabause/src/qt/ui/UIDebugVDP1.h b/yabause/src/qt/ui/UIDebugVDP1.h index 142bbb010c..893e8d009f 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.h +++ b/yabause/src/qt/ui/UIDebugVDP1.h @@ -21,15 +21,17 @@ #include "ui_UIDebugVDP1.h" #include "../QtYabause.h" +#include "YabauseGL.h" class UIDebugVDP1 : public QDialog, public Ui::UIDebugVDP1 { Q_OBJECT public: - UIDebugVDP1( QWidget* parent = 0 ); + UIDebugVDP1( QWidget* parent, QWidget* glWidget ); ~UIDebugVDP1(); protected: + YabauseGL* yabauseGL; u32 *vdp1texture; u8 *vdp1RawTexture; int vdp1RawNumBytes; diff --git a/yabause/src/qt/ui/UIYabause.cpp b/yabause/src/qt/ui/UIYabause.cpp index 7431cb4e5d..3c4fa704e0 100644 --- a/yabause/src/qt/ui/UIYabause.cpp +++ b/yabause/src/qt/ui/UIYabause.cpp @@ -1141,7 +1141,7 @@ void UIYabause::on_aViewDebugSSH2_triggered() void UIYabause::on_aViewDebugVDP1_triggered() { YabauseLocker locker( mYabauseThread ); - UIDebugVDP1( this ).exec(); + UIDebugVDP1( this, mYabauseGL->getWidget() ).exec(); } void UIYabause::on_aViewDebugVDP2_triggered() @@ -1273,6 +1273,11 @@ void UIYabause::on_cbVideoDriver_currentIndexChanged( int id ) void UIYabause::pause( bool paused ) { + // Store last visible buffer + if (paused) + mYabauseGL->snapshotView(); + + mYabauseGL->setPaused( paused ); mYabauseGL->updateView(); aEmulationRun->setEnabled( paused ); diff --git a/yabause/src/vdp1.c b/yabause/src/vdp1.c index b0255ee2dd..13cfbfe25d 100644 --- a/yabause/src/vdp1.c +++ b/yabause/src/vdp1.c @@ -1496,6 +1496,69 @@ u32 *Vdp1DebugTexture(u32 number, int *w, int *h) return texture; } +u8 Vdp1DebugCommandVertices(u32 number, int *x0, int *y0, int *x1, int *y1, + int *x2, int *y2, int *x3, int *y3) +{ + u16 command; + vdp1cmd_struct cmd; + u32 addr; + u32 i; + + if ((addr = Vdp1DebugGetCommandNumberAddr(number)) == 0xFFFFFFFF) + return -1; + + command = T1ReadWord(Vdp1Ram, addr); + if (command & 0x8000) + // Draw End + return -1; + + if (command & 0x4000) + // Command Skipped + return -1; + + Vdp1ReadCommand(&cmd, addr, Vdp1Ram); + if ((cmd.CMDCTRL & 0x000F) <= 5) + { + // Find user local coordinates first + vdp1cmd_struct tmpCmd; + s16 coordX = 0; + s16 coordY = 0; + for (i = 0; ; ++i) + { + if ((addr = Vdp1DebugGetCommandNumberAddr(i)) == 0xFFFFFFFF) + break; + + Vdp1ReadCommand(&tmpCmd, addr, Vdp1Ram); + if ((tmpCmd.CMDCTRL & 0x000F) != 10) + continue; + + coordX = tmpCmd.CMDXA; + coordY = tmpCmd.CMDYA; + break; + } + + // 0: Normal Sprite + // 1: Scaled Sprite + // 2: Distorted Sprite + // 3: Distorted Sprite * + // 4: Polygon + // 5: Polyline + *x0 = coordX + cmd.CMDXA; + *y0 = coordY + cmd.CMDYA; + *x1 = coordX + cmd.CMDXB; + *y1 = coordY + cmd.CMDYB; + *x2 = coordX + cmd.CMDXC; + *y2 = coordY + cmd.CMDYC; + *x3 = coordX + cmd.CMDXD; + *y3 = coordY + cmd.CMDYD; + return 0; + } + else + { + return -1; + } +} + u8 *Vdp1DebugRawTexture(u32 cmdNumber, int *width, int *height, int *numBytes) { u16 cmdRaw; diff --git a/yabause/src/vdp1.h b/yabause/src/vdp1.h index 6c4c4422e0..757f72a568 100644 --- a/yabause/src/vdp1.h +++ b/yabause/src/vdp1.h @@ -204,6 +204,8 @@ void Vdp1DebugGetCommandNumberName(u32 number, char *outstring); Vdp1CommandType Vdp1DebugGetCommandType(u32 number); void Vdp1DebugCommand(u32 number, char *outstring); u32 *Vdp1DebugTexture(u32 number, int *w, int *h); +u8 Vdp1DebugCommandVertices(u32 number, int *x0, int *y0, int *x1, int *y1, + int *x2, int *y2, int *x3, int *y3); u8 *Vdp1DebugRawTexture(u32 number, int *w, int *h, int *numBytes); void ToggleVDP1(void); From fab3e6135a2da2613e032eac052a0e03137ff679 Mon Sep 17 00:00:00 2001 From: Romulo Fernandes Date: Wed, 26 May 2021 20:11:31 +0200 Subject: [PATCH 07/17] Do bounds checking on line drawLine --- yabause/src/qt/ui/UIDebugVDP1.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yabause/src/qt/ui/UIDebugVDP1.cpp b/yabause/src/qt/ui/UIDebugVDP1.cpp index 1e65562ae5..9ddd3656b1 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.cpp +++ b/yabause/src/qt/ui/UIDebugVDP1.cpp @@ -49,6 +49,9 @@ void drawLine(uint32_t color, uint32_t* buffer, int width, int height, for(;;) { + if ( x0 < 0 || x0 >= width || y0 < 0 || y0 >= height ) + break; + buffer[y0 * width + x0] = color; if (x0 == x1 && y0 == y1) break; From d6688c378ce4029eaf4f3d95cd8a075daba46161 Mon Sep 17 00:00:00 2001 From: Romulo Fernandes Date: Wed, 26 May 2021 20:13:37 +0200 Subject: [PATCH 08/17] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ffe6212ca2..7dd2eda24a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Yabause - A Saturn Emulator +This is my personal fork of Yabause with development updates. [Documentation](http://wiki.yabause.org/index.php5?title=Documentations) | [Homepage](https://yabause.org/) | [Development Builds](https://yabause.org/download/) From af4f24f7b709ca4f2cd438bca0636d9a48b6121d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Thu, 27 May 2021 00:51:50 +0200 Subject: [PATCH 09/17] Fixed drawing bounds for real Optimized the local coordinates search on debug Support for debugging normal and scaled sprites --- yabause/CMakeLists.txt | 2 +- yabause/src/qt/ui/UIDebugVDP1.cpp | 17 +++-- yabause/src/vdp1.c | 115 +++++++++++++++++++++++++++--- 3 files changed, 118 insertions(+), 16 deletions(-) diff --git a/yabause/CMakeLists.txt b/yabause/CMakeLists.txt index eddc81be9b..4ff713e99f 100644 --- a/yabause/CMakeLists.txt +++ b/yabause/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 2.8) set(YAB_PACKAGE yabause) set(YAB_VERSION_MAJOR 0) set(YAB_VERSION_MINOR 9) -set(YAB_VERSION_PATCH 15) +set(YAB_VERSION_PATCH 16) set(YAB_VERSION "${YAB_VERSION_MAJOR}.${YAB_VERSION_MINOR}.${YAB_VERSION_PATCH}") set(CPACK_SOURCE_GENERATOR TGZ) diff --git a/yabause/src/qt/ui/UIDebugVDP1.cpp b/yabause/src/qt/ui/UIDebugVDP1.cpp index 9ddd3656b1..0189e467ce 100644 --- a/yabause/src/qt/ui/UIDebugVDP1.cpp +++ b/yabause/src/qt/ui/UIDebugVDP1.cpp @@ -49,10 +49,19 @@ void drawLine(uint32_t color, uint32_t* buffer, int width, int height, for(;;) { - if ( x0 < 0 || x0 >= width || y0 < 0 || y0 >= height ) - break; - - buffer[y0 * width + x0] = color; + int writeX = x0; + int writeY = y0; + if ( writeX < 0 ) + writeX = 0; + else if ( writeX >= width ) + writeX = width - 1; + + if ( writeY < 0 ) + writeY = 0; + else if ( writeY >= height ) + writeY = height - 1; + + buffer[writeY * width + writeX] = color; if (x0 == x1 && y0 == y1) break; diff --git a/yabause/src/vdp1.c b/yabause/src/vdp1.c index 13cfbfe25d..ad47ca4379 100644 --- a/yabause/src/vdp1.c +++ b/yabause/src/vdp1.c @@ -1502,7 +1502,8 @@ u8 Vdp1DebugCommandVertices(u32 number, int *x0, int *y0, int *x1, int *y1, u16 command; vdp1cmd_struct cmd; u32 addr; - u32 i; + s32 i; + u8 cmdType; if ((addr = Vdp1DebugGetCommandNumberAddr(number)) == 0xFFFFFFFF) return -1; @@ -1517,13 +1518,14 @@ u8 Vdp1DebugCommandVertices(u32 number, int *x0, int *y0, int *x1, int *y1, return -1; Vdp1ReadCommand(&cmd, addr, Vdp1Ram); - if ((cmd.CMDCTRL & 0x000F) <= 5) + cmdType = cmd.CMDCTRL & 0x000F; + if (cmdType <= 5) { // Find user local coordinates first vdp1cmd_struct tmpCmd; s16 coordX = 0; s16 coordY = 0; - for (i = 0; ; ++i) + for (i = number; i >= 0; --i) { if ((addr = Vdp1DebugGetCommandNumberAddr(i)) == 0xFFFFFFFF) break; @@ -1543,14 +1545,105 @@ u8 Vdp1DebugCommandVertices(u32 number, int *x0, int *y0, int *x1, int *y1, // 3: Distorted Sprite * // 4: Polygon // 5: Polyline - *x0 = coordX + cmd.CMDXA; - *y0 = coordY + cmd.CMDYA; - *x1 = coordX + cmd.CMDXB; - *y1 = coordY + cmd.CMDYB; - *x2 = coordX + cmd.CMDXC; - *y2 = coordY + cmd.CMDYC; - *x3 = coordX + cmd.CMDXD; - *y3 = coordY + cmd.CMDYD; + if (cmdType == 0 || cmdType == 1) + { + s16 i0, j0; + s16 i1, j1; + if (cmdType == 0) + { + i0 = cmd.CMDXA; + i1 = i0 + (((cmd.CMDSIZE & 0x3F00) >> 5) & 0xFF); + j0 = cmd.CMDYA; + j1 = j0 + (cmd.CMDSIZE & 0xFF); + } + else + { + switch ((cmd.CMDCTRL >> 8) & 0xF) + { + default: + case 0x0: + i0 = cmd.CMDXA; + i1 = i0 + cmd.CMDXC; + j0 = cmd.CMDYA; + j1 = j0 + cmd.CMDYC; + break; + case 0x5: // Upper-Left + i0 = cmd.CMDXA; + i1 = i0 + cmd.CMDXB; + j0 = cmd.CMDYA; + j1 = j0 + cmd.CMDYB; + break; + case 0x6: // Upper-Center + i0 = cmd.CMDXA - cmd.CMDXB / 2; + i1 = cmd.CMDXA + cmd.CMDXB / 2; + j0 = cmd.CMDYA; + j1 = j0 + cmd.CMDYB; + break; + case 0x7: // Upper-Right + i0 = cmd.CMDXA - cmd.CMDXB; + i1 = cmd.CMDXA; + j0 = cmd.CMDYA; + j1 = j0 + cmd.CMDYB; + break; + case 0x9: // Center-Left + i0 = cmd.CMDXA; + i1 = cmd.CMDXA + cmd.CMDXB; + j0 = cmd.CMDYA - cmd.CMDYB / 2; + j1 = cmd.CMDYA + cmd.CMDYB / 2; + break; + case 0xA: // Center-Center + i0 = cmd.CMDXA - cmd.CMDXB / 2; + i1 = cmd.CMDXA + cmd.CMDXB / 2; + j0 = cmd.CMDYA - cmd.CMDYB / 2; + j1 = cmd.CMDYA + cmd.CMDYB / 2; + break; + case 0xB: // Center-Right + i0 = cmd.CMDXA - cmd.CMDXB; + i1 = cmd.CMDXA; + j0 = cmd.CMDYA - cmd.CMDYB / 2; + j1 = cmd.CMDYA + cmd.CMDYB / 2; + break; + case 0xD: // Lower-Left + i0 = cmd.CMDXA; + i1 = cmd.CMDXA + cmd.CMDXB; + j0 = cmd.CMDYA - cmd.CMDYB; + j1 = cmd.CMDYA; + break; + case 0xE: // Lower-Center + i0 = cmd.CMDXA - cmd.CMDXB / 2; + i1 = cmd.CMDXA + cmd.CMDXB / 2; + j0 = cmd.CMDYA - cmd.CMDYB; + j1 = cmd.CMDYA; + break; + case 0xF: // Lower-Right + i0 = cmd.CMDXA - cmd.CMDXB; + i1 = cmd.CMDXA; + j0 = cmd.CMDYA - cmd.CMDYB; + j1 = cmd.CMDYA; + break; + } + } + + *x0 = coordX + i0; + *y0 = coordY + j0; + *x1 = coordX + i1; + *y1 = coordY + j0; + *x2 = coordX + i1; + *y2 = coordY + j1; + *x3 = coordX + i0; + *y3 = coordY + j1; + } + else + { + *x0 = coordX + cmd.CMDXA; + *y0 = coordY + cmd.CMDYA; + *x1 = coordX + cmd.CMDXB; + *y1 = coordY + cmd.CMDYB; + *x2 = coordX + cmd.CMDXC; + *y2 = coordY + cmd.CMDYC; + *x3 = coordX + cmd.CMDXD; + *y3 = coordY + cmd.CMDYD; + } return 0; } else From 1e3691491bff0c6c2f047ed72d817fc3399330d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Tue, 14 Sep 2021 22:17:00 +0200 Subject: [PATCH 10/17] Allow more than 2000 commands and add cycle pattern data to vdp2 debug --- yabause/src/vdp1.c | 4 ++-- yabause/src/vdp2debug.c | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/yabause/src/vdp1.c b/yabause/src/vdp1.c index ad47ca4379..9afe7743ef 100644 --- a/yabause/src/vdp1.c +++ b/yabause/src/vdp1.c @@ -467,7 +467,7 @@ void Vdp1DrawCommands(u8 * ram, Vdp1 * regs, u8* back_framebuffer) u32 commandCounter = 0; u32 returnAddr = 0xffffffff; - while (!(command & 0x8000) && commandCounter < 2000) { // fix me + while (!(command & 0x8000) && commandCounter < 5000) { // fix me // First, process the command if (!(command & 0x4000)) { // if (!skip) switch (command & 0x000F) { @@ -548,7 +548,7 @@ void Vdp1FakeDrawCommands(u8 * ram, Vdp1 * regs) u32 commandCounter = 0; u32 returnAddr = 0xffffffff; - while (!(command & 0x8000) && commandCounter < 2000) { // fix me + while (!(command & 0x8000) && commandCounter < 5000) { // fix me // First, process the command if (!(command & 0x4000)) { // if (!skip) switch (command & 0x000F) { diff --git a/yabause/src/vdp2debug.c b/yabause/src/vdp2debug.c index 4a9f49e7fa..e213d36ea7 100644 --- a/yabause/src/vdp2debug.c +++ b/yabause/src/vdp2debug.c @@ -1534,6 +1534,13 @@ void Vdp2DebugStatsGeneral(char *outstring, int *isenabled) AddString(outstring, "\r\n"); // Cycle patterns here + AddString(outstring, "Cycle Pattern\r\n"); + AddString(outstring, "-----------------\r\n"); + AddString(outstring, "A0 = %08X\r\n", (Vdp2Regs->CYCA0L << 16) | (Vdp2Regs->CYCA0U)); + AddString(outstring, "A1 = %08X\r\n", (Vdp2Regs->CYCA1L << 16) | (Vdp2Regs->CYCA1U)); + AddString(outstring, "B0 = %08X\r\n", (Vdp2Regs->CYCB0L << 16) | (Vdp2Regs->CYCB0U)); + AddString(outstring, "B1 = %08X\r\n", (Vdp2Regs->CYCB1L << 16) | (Vdp2Regs->CYCB1U)); + AddString(outstring, "\r\n"); // Sprite stuff AddString(outstring, "Sprite Stuff\r\n"); From d0a8915d101e623b01393e70d96360f31ef649d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Sat, 18 Sep 2021 21:12:00 +0200 Subject: [PATCH 11/17] Add code debug support by using addr2line --- yabause/src/qt/ui/UIDebugCPU.cpp | 10 +- yabause/src/qt/ui/UIDebugCPU.h | 1 + yabause/src/qt/ui/UIDebugCPU.ui | 683 +++++++++++++++------------ yabause/src/qt/ui/UIDebugSH2.cpp | 175 ++++++- yabause/src/qt/ui/UIDebugSH2.h | 5 + yabause/src/qt/ui/UIHexEditor.cpp | 29 +- yabause/src/qt/ui/UIHexEditor.h | 4 + yabause/src/qt/ui/UIMemoryEditor.cpp | 29 +- yabause/src/qt/ui/UIMemoryEditor.h | 6 + yabause/src/qt/ui/UISettings.cpp | 8 + yabause/src/qt/ui/UISettings.ui | 56 ++- 11 files changed, 685 insertions(+), 321 deletions(-) diff --git a/yabause/src/qt/ui/UIDebugCPU.cpp b/yabause/src/qt/ui/UIDebugCPU.cpp index 0fad51f287..75139fd71f 100644 --- a/yabause/src/qt/ui/UIDebugCPU.cpp +++ b/yabause/src/qt/ui/UIDebugCPU.cpp @@ -29,7 +29,7 @@ UIDebugCPU::UIDebugCPU( PROCTYPE proc, YabauseThread *mYabauseThread, QWidget* p // set up dialog setupUi( this ); if ( p && !p->isFullScreen() ) - setWindowFlags( Qt::Sheet ); + setWindowFlags( Qt::Sheet | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint ); // Disable unimplemented functions gbBackTrace->setVisible( false ); @@ -40,6 +40,7 @@ UIDebugCPU::UIDebugCPU( PROCTYPE proc, YabauseThread *mYabauseThread, QWidget* p pbReserved3->setVisible( false ); pbReserved4->setVisible( false ); pbReserved5->setVisible( false ); + pbLoadCode->setVisible( false ); pbAddCodeBreakpoint->setEnabled( false ); pbDelCodeBreakpoint->setEnabled( false ); @@ -80,6 +81,7 @@ void UIDebugCPU::on_lwRegisters_itemDoubleClicked ( QListWidgetItem * item ) void UIDebugCPU::on_lwBackTrace_itemDoubleClicked ( QListWidgetItem * item ) { updateCodeList(item->text().toUInt(NULL, 16)); + updateCodePage(item->text().toUInt(NULL, 16)); } void UIDebugCPU::on_twTrackInfLoop_itemDoubleClicked ( QTableWidgetItem * item ) @@ -295,6 +297,10 @@ void UIDebugCPU::updateRegList() void UIDebugCPU::updateCodeList(u32 addr) { } + +void UIDebugCPU::updateCodePage(u32 addr) +{ +} u32 UIDebugCPU::getRegister(int index, int *size) { @@ -310,7 +316,7 @@ bool UIDebugCPU::addCodeBreakpoint(u32 addr) { return true; } - + void UIDebugCPU::toggleCodeBreakpoint(u32 addr) { QString text; diff --git a/yabause/src/qt/ui/UIDebugCPU.h b/yabause/src/qt/ui/UIDebugCPU.h index 2502c09250..b3d10a8f1f 100644 --- a/yabause/src/qt/ui/UIDebugCPU.h +++ b/yabause/src/qt/ui/UIDebugCPU.h @@ -41,6 +41,7 @@ class UIDebugCPU : public QDialog, public Ui::UIDebugCPU UIDebugCPU( PROCTYPE proc, YabauseThread *mYabauseThread, QWidget* parent = 0 ); virtual void updateRegList(); virtual void updateCodeList(u32 addr); + virtual void updateCodePage(u32 addr); virtual u32 getRegister(int index, int *size); virtual void setRegister(int index, u32 value); virtual bool addCodeBreakpoint(u32 addr); diff --git a/yabause/src/qt/ui/UIDebugCPU.ui b/yabause/src/qt/ui/UIDebugCPU.ui index 7a2dbcc6c6..43ddc6783b 100644 --- a/yabause/src/qt/ui/UIDebugCPU.ui +++ b/yabause/src/qt/ui/UIDebugCPU.ui @@ -6,18 +6,33 @@ 0 0 - 927 - 483 + 1503 + 672 Debug CPU + + true + + + + 0 + 0 + + + + + 350 + 16777215 + + Registers @@ -171,326 +186,369 @@ - - - - - - 0 - 0 - - - - Code Breakpoints - - - - - - + + + + 0 + 0 + + + + 1 + + + true + + + true + + + + Breakpoints + + + + + + + + + 0 + 0 + + + + Code Breakpoints + + - + - - - - 0 - 0 - - - - - - + + + + + + + + 0 + 0 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + + - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + + 0 + 0 + + + + Add + + + + + + + Del + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + - - - - - 0 - 0 - - - - - - - - - - - - 0 - 0 - - - - Add - - - - - - - Del - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 40 - - - - - - - - - - - - - - - - 0 - 0 - - - - Memory Breakpoints - - - - - - + + + + + + + 0 + 0 + + + + Memory Breakpoints + + - + - - - - - + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + + - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + Add + + + + + + + Del + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + - - - - 0 - 0 - - - - - - - - - - - - Add - - - - - - - Del - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 40 - - - - - - - - - - - - - - - - Read - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Write - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - true - - - Byte - - - true - - - true - - - - - - - true - - - Word - - - false - - - - - - - true - - - Long - - - - - - - false - - - Byte - - - - - - - false - - - Word - - - - - - - false - - - Long - - + + + + + + + Read + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Write + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + true + + + Byte + + + true + + + true + + + + + + + true + + + Word + + + false + + + + + + + true + + + Long + + + + + + + false + + + Byte + + + + + + + false + + + Word + + + + + + + false + + + Long + + + + + + - - - - - - - + + + + + + + + + Code + + + + + + QTextEdit::NoWrap + + + false + + + + + + @@ -532,11 +590,11 @@ - - - Trace Logging - - + + + Trace Logging + + @@ -573,6 +631,13 @@ + + + + Load Code + + + diff --git a/yabause/src/qt/ui/UIDebugSH2.cpp b/yabause/src/qt/ui/UIDebugSH2.cpp index 6df13a4e8c..6868038eb4 100644 --- a/yabause/src/qt/ui/UIDebugSH2.cpp +++ b/yabause/src/qt/ui/UIDebugSH2.cpp @@ -17,9 +17,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "Settings.h" #include "UIDebugSH2.h" #include "../CommonDialogs.h" #include "UIYabause.h" +#include "VolatileSettings.h" +#include +#include +#include +#include +#include +#include +#include +#include int SH2Dis(SH2_struct *context, u32 addr, char *string) { @@ -109,14 +119,24 @@ UIDebugSH2::UIDebugSH2(UIDebugCPU::PROCTYPE proc, YabauseThread *mYabauseThread, pbReserved1->setText(QtYabause::translate("Loop Track Stop")); else pbReserved1->setText(QtYabause::translate("Loop Track Start")); - pbReserved2->setText(QtYabause::translate("Loop Track Clear")); + pbReserved2->setText(QtYabause::translate("Loop Track Clear")); pbReserved3->setText(QtYabause::translate("Inline Assembly")); - pbStepOver->setVisible( true ); - pbStepOut->setVisible( true ); - pbReserved1->setVisible( true ); - pbReserved2->setVisible( true ); + pbStepOver->setVisible( true ); + pbStepOut->setVisible( true ); + pbReserved1->setVisible( true ); + pbReserved2->setVisible( true ); pbReserved3->setVisible( true ); + pbLoadCode->setVisible( true ); + connect( pbLoadCode, SIGNAL( clicked() ), this, SLOT( loadCodeAddress() ) ); + + restoreAddr2line(); +} + +void UIDebugSH2::restoreAddr2line() +{ + Settings* settings = QtYabause::settings(); + addr2line = settings->value( "Debug/Addr2Line" ).toString(); } void UIDebugSH2::updateRegList() @@ -207,6 +227,150 @@ void UIDebugSH2::updateTrackInfLoop() } } +void UIDebugSH2::loadCodeAddress() +{ + sh2regs_struct sh2regs; + SH2GetRegisters(debugSH2, &sh2regs); + + std::stringstream currentAddress; + currentAddress << std::hex << sh2regs.PC; + + bool ok = false; + const std::string newAddress = QInputDialog::getText(this, tr("Input code address"), + tr("Address (hex):"), QLineEdit::Normal, + QString::fromStdString(currentAddress.str()), &ok).toStdString(); + + if (ok) + updateCodePage(static_cast(std::stoull(newAddress, nullptr, 16))); +} + +void UIDebugSH2::updateCodePage(u32 evaluateAddress) +{ + DebugPrintf(MainLog, __FILE__, __LINE__, "Address to inspect %x\n", evaluateAddress); + if (addr2line.isEmpty()) + restoreAddr2line(); + + const QString program{ addr2line }; + std::filesystem::path elfPath; + + VolatileSettings *vs = QtYabause::volatileSettings(); + if ( vs->value( "General/CdRom" ) != CDCORE_ISO ) + { + DebugPrintf(MainLog, __FILE__, __LINE__, "Not using ISO, ignoring code\n"); + return; + } + else + { + const QString isoPathString{ vs->value( "General/CdRomISO" ).toString() }; + const std::filesystem::path isoPath{ isoPathString.toStdString() }; + + // Search first at the './build/' directory + const std::filesystem::path folder{ isoPath.parent_path() }; + const std::string elfFilename{ isoPath.filename().stem().string() + ".elf" }; + const std::filesystem::path atBuildFolder{ folder / "build" / elfFilename }; + const std::filesystem::path atLocalFolder{ folder / elfFilename }; + + if ( std::filesystem::exists( atBuildFolder ) ) + elfPath = atBuildFolder; + else if ( std::filesystem::exists( atLocalFolder ) ) + elfPath = atLocalFolder; + } + + if ( elfPath.empty() ) + { + DebugPrintf(MainLog, __FILE__, __LINE__, "Could not find elf file, ignoring code\n"); + return; + } + + std::stringstream hexAddress; + hexAddress << std::setfill('0') << std::setw(8) << std::hex + << evaluateAddress; + + QStringList arguments; + arguments.push_back("-a"); + arguments.push_back(QString::fromStdString(hexAddress.str())); + arguments.push_back("-p"); + arguments.push_back("-i"); + arguments.push_back("-f"); + arguments.push_back("-C"); + arguments.push_back("-e"); + arguments.push_back(QString::fromStdString(elfPath.string())); + + QProcess addr2lineProgram; + addr2lineProgram.start(program, arguments); + addr2lineProgram.waitForFinished(); + + std::string commandString; + commandString += program.toStdString() + " " + arguments.join(" ").toStdString(); + + const QByteArray pstdout = addr2lineProgram.readAllStandardOutput(); + if (addr2lineProgram.exitCode() != 0) { + const QByteArray pstderr = addr2lineProgram.readAllStandardError(); + const std::string outputString = + pstdout.toStdString() + " / " + pstderr.toStdString(); + + DebugPrintf(MainLog, __FILE__, __LINE__, "Cmd: %s\n", + commandString.c_str()); + DebugPrintf(MainLog, __FILE__, __LINE__, "Output (%d): %s\n", + addr2lineProgram.exitCode(), outputString.c_str()); + + codeBrowser->setText(QString::fromStdString(outputString)); + } else { + + // QRegularExpression re("(0x[0-9a-fA-F]+):\\s*(.+?(?= at )) at (.+?(?=:[0-9]+)):([0-9]+)"); + QRegularExpression re("(0x[0-9a-fA-F]+):\\s*(.+?(?= at )) at (.+?(?=:[0-9]+)):([0-9]+)" + "(\\s*\\(inlined by\\)\\s*(.+?(?= at )) at (.+?(?=:[0-9]+)):([0-9]+))?"); + + QRegularExpressionMatch match = re.match(pstdout); + bool hasMatch = match.hasMatch(); + + if (match.hasMatch()) + { + const int filenameGroup = match.lastCapturedIndex() == 8 ? 7 : 3; + const int lineGroup = match.lastCapturedIndex() == 8 ? 8 : 4; + + const std::filesystem::path filename{match.captured(filenameGroup).toStdString()}; + const int line{ std::stoi(match.captured(lineGroup).toStdString()) }; + + std::ifstream inputFile(filename, std::ios_base::in); + inputFile.seekg(0, std::ios_base::end); + const size_t fileSize = inputFile.tellg(); + inputFile.seekg(0, std::ios_base::beg); + + std::string tmpString(fileSize, '\0'); + inputFile.read(&tmpString[0], fileSize); + + const std::string tooltip{ filename.string() + ":" + std::to_string(line) }; + + codeTab->setTabText(1, QString::fromStdString(filename.filename().string())); + codeTab->setTabToolTip(1, QString::fromStdString(tooltip)); + codeBrowser->setText(QString::fromStdString(tmpString)); + + QTextBlock lineBlock = codeBrowser->document()->findBlockByLineNumber(line - 1); + codeBrowser->moveCursor(QTextCursor::End); + codeBrowser->setTextCursor(QTextCursor(lineBlock)); + + QTextBlockFormat highlightFormat; + highlightFormat.setBackground(Qt::yellow); + highlightFormat.setNonBreakableLines(true); + highlightFormat.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore); + + QTextCursor newCursor(codeBrowser->textCursor()); + newCursor.setPosition(lineBlock.position()); + newCursor.select(QTextCursor::LineUnderCursor); + newCursor.setBlockFormat(highlightFormat); + } + else + { + codeTab->setTabText(1, "Source"); + if (addr2line.isEmpty()) + codeBrowser->setText("addr2line utility is not configured properly, source not available."); + else + codeBrowser->setText("Source not found or available."); + } + } +} + void UIDebugSH2::updateAll() { updateRegList(); @@ -218,6 +382,7 @@ void UIDebugSH2::updateAll() updateCodeList(sh2regs.PC); updateBackTrace(); updateTrackInfLoop(); + updateCodePage(sh2regs.PC); } } diff --git a/yabause/src/qt/ui/UIDebugSH2.h b/yabause/src/qt/ui/UIDebugSH2.h index 217384510f..a864f1cf34 100644 --- a/yabause/src/qt/ui/UIDebugSH2.h +++ b/yabause/src/qt/ui/UIDebugSH2.h @@ -27,10 +27,14 @@ class UIDebugSH2 : public UIDebugCPU Q_OBJECT private: SH2_struct *debugSH2; + QString addr2line; + void restoreAddr2line(); + public: UIDebugSH2( UIDebugCPU::PROCTYPE proc, YabauseThread *mYabauseThread, QWidget* parent = 0 ); void updateRegList(); void updateCodeList(u32 addr); + void updateCodePage(u32 evaluateAddress) override; void updateBackTrace(); void updateTrackInfLoop(); void updateAll(); @@ -49,6 +53,7 @@ class UIDebugSH2 : public UIDebugCPU protected: protected slots: + void loadCodeAddress(); }; #endif // UIDEBUGSH2_H diff --git a/yabause/src/qt/ui/UIHexEditor.cpp b/yabause/src/qt/ui/UIHexEditor.cpp index 4d452c7c4e..c43e0e661f 100644 --- a/yabause/src/qt/ui/UIHexEditor.cpp +++ b/yabause/src/qt/ui/UIHexEditor.cpp @@ -17,6 +17,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "UIHexEditor.h" +#include "Settings.h" #include #include #include @@ -74,6 +75,18 @@ void UIHexEditor::goToAddress( u32 address, bool setCursor ) UIHexEditorWnd *hexEditorWnd=(UIHexEditorWnd *)currentWidget(); hexEditorWnd->goToAddress(address, setCursor); } + +void UIHexEditor::saveCursorPosition() +{ + UIHexEditorWnd *hexEditorWnd=(UIHexEditorWnd *)currentWidget(); + hexEditorWnd->saveCursorPosition(); +} + +void UIHexEditor::restoreCursorPosition() +{ + UIHexEditorWnd *hexEditorWnd=(UIHexEditorWnd *)currentWidget(); + hexEditorWnd->restoreCursorPosition(); +} u32 UIHexEditor::getStartAddress() { @@ -132,7 +145,7 @@ UIHexEditorWnd::UIHexEditorWnd( QWidget* p ) connect(&autoScrollTimer, SIGNAL(timeout()), this, SLOT(autoScroll())); autoScrollTimer.setInterval(5); - setMouseTracking(true); + setMouseTracking(true); } void UIHexEditorWnd::sliderUpdate(int value) @@ -198,6 +211,20 @@ void UIHexEditorWnd::goToAddress(u32 address, bool setCursor) viewport()->update(); } +void UIHexEditorWnd::saveCursorPosition() +{ + Settings *settings = QtYabause::settings(); + settings->setValue("Debug/MemoryEditorCaretPosition", + QVariant(verticalScrollBar()->value())); +} + +void UIHexEditorWnd::restoreCursorPosition() +{ + Settings* settings = QtYabause::settings(); + verticalScrollBar()->setValue( + settings->value("Debug/MemoryEditorCaretPosition", QVariant(0)).toInt()); +} + u8 UIHexEditorWnd::readByte(u32 addr) { if (proc == UIDebugCPU::PROC_MSH2 || proc == UIDebugCPU::PROC_SSH2) diff --git a/yabause/src/qt/ui/UIHexEditor.h b/yabause/src/qt/ui/UIHexEditor.h index 9691fea9f6..6f22e8e73e 100644 --- a/yabause/src/qt/ui/UIHexEditor.h +++ b/yabause/src/qt/ui/UIHexEditor.h @@ -41,6 +41,8 @@ class UIHexEditorWnd : public QAbstractScrollArea u32 getAddress(); void setProc( UIDebugCPU::PROCTYPE proc ); void goToAddress(u32 address, bool setCursor=true); + void saveCursorPosition(); + void restoreCursorPosition(); virtual void setFont(const QFont &font); bool saveSelected(QString filename); bool saveTab(QString filename); @@ -125,6 +127,8 @@ class UIHexEditor : public QTabWidget UIHexEditor( QWidget* parent = 0 ); void goToAddress(u32 address, bool setCursor=true); + void saveCursorPosition(); + void restoreCursorPosition(); u32 getStartAddress(); u32 getEndAddress(); void setProc( UIDebugCPU::PROCTYPE proc ); diff --git a/yabause/src/qt/ui/UIMemoryEditor.cpp b/yabause/src/qt/ui/UIMemoryEditor.cpp index 7cf3198ea2..a899dcb653 100644 --- a/yabause/src/qt/ui/UIMemoryEditor.cpp +++ b/yabause/src/qt/ui/UIMemoryEditor.cpp @@ -22,6 +22,7 @@ #include "UIMemorySearch.h" #include "Settings.h" #include "../CommonDialogs.h" +#include MemorySearch::MemorySearch(UIMemorySearch *memorySearch, QObject *parent) : QObject(parent) @@ -123,7 +124,7 @@ UIMemoryEditor::UIMemoryEditor( enum UIDebugCPU::PROCTYPE proc, YabauseThread *m saMemoryEditor->setEnabled(false); pbGotoAddress->setEnabled(false); pbSaveSelected->setEnabled(false); - pbSaveTab->setEnabled(false); + pbSaveTab->setEnabled(false); pbSearchMemory->setEnabled(false); } else @@ -134,6 +135,32 @@ UIMemoryEditor::UIMemoryEditor( enum UIDebugCPU::PROCTYPE proc, YabauseThread *m // retranslate widgets QtYabause::retranslateWidget( this ); + + saMemoryEditor->restoreCursorPosition(); +} + +void UIMemoryEditor::closeEvent(QCloseEvent* evt) +{ + saMemoryEditor->saveCursorPosition(); + QDialog::closeEvent(evt); +} + +void UIMemoryEditor::accept() +{ + saMemoryEditor->saveCursorPosition(); + QDialog::accept(); +} + +void UIMemoryEditor::reject() +{ + saMemoryEditor->saveCursorPosition(); + QDialog::reject(); +} + +void UIMemoryEditor::done(int r) +{ + saMemoryEditor->saveCursorPosition(); + QDialog::done(r); } void UIMemoryEditor::on_pbGotoAddress_clicked() diff --git a/yabause/src/qt/ui/UIMemoryEditor.h b/yabause/src/qt/ui/UIMemoryEditor.h index 5e5c448c22..ddeb4baaea 100644 --- a/yabause/src/qt/ui/UIMemoryEditor.h +++ b/yabause/src/qt/ui/UIMemoryEditor.h @@ -70,6 +70,12 @@ class UIMemoryEditor : public QDialog, public Ui::UIMemoryEditor void killProgressDialog(); protected: + void closeEvent(QCloseEvent *e) override; + +public slots: + void accept() Q_DECL_OVERRIDE; + void reject() Q_DECL_OVERRIDE; + void done(int r) Q_DECL_OVERRIDE; protected slots: void on_pbGotoAddress_clicked(); diff --git a/yabause/src/qt/ui/UISettings.cpp b/yabause/src/qt/ui/UISettings.cpp index 1dead65deb..f9d0eb1ccf 100755 --- a/yabause/src/qt/ui/UISettings.cpp +++ b/yabause/src/qt/ui/UISettings.cpp @@ -238,6 +238,8 @@ void UISettings::tbBrowse_clicked() requestFile( QtYabause::translate( "Choose a sh1 rom" ), leSH1ROM ); else if ( tb == tbMpegROM ) requestFile( QtYabause::translate( "Choose a mpeg rom" ), leMpegROM ); + else if ( tb == tbAddr2Line ) + requestFile( QtYabause::translate( "Choose the location of the addr2line executable" ), leAddr2Line ); } void UISettings::on_cbInput_currentIndexChanged( int id ) @@ -520,6 +522,9 @@ void UISettings::loadSettings() bgShowLogWindow->setId( rbLogWindowNever, 0 ); bgShowLogWindow->setId( rbLogWindowMessage, 1 ); bgShowLogWindow->button( s->value( "View/LogWindow", 0 ).toInt() )->setChecked( true ); + + // debug + leAddr2Line->setText( s->value( "Debug/Addr2Line" ).toString() ); } void UISettings::saveSettings() @@ -625,6 +630,9 @@ void UISettings::saveSettings() s->setValue(action->text(), accelText); } s->endGroup(); + + // debug + s->setValue( "Debug/Addr2Line", leAddr2Line->text() ); } void UISettings::accept() diff --git a/yabause/src/qt/ui/UISettings.ui b/yabause/src/qt/ui/UISettings.ui index 43b052bf30..17dcd23f88 100644 --- a/yabause/src/qt/ui/UISettings.ui +++ b/yabause/src/qt/ui/UISettings.ui @@ -6,8 +6,8 @@ 0 0 - 513 - 523 + 522 + 716 @@ -1027,6 +1027,56 @@ + + + Debug + + + + + + + 75 + true + + + + addr2line Executable + + + Qt::PlainText + + + + + + + + + + + + ... + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + @@ -1090,8 +1140,8 @@ + - From eb901ae071df822645866ec5473c3716acb4f068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Sat, 18 Sep 2021 21:12:36 +0200 Subject: [PATCH 12/17] Fix DSP end termination handling (JIT still missing) and also clearing the E/V bits when acessing the DSP control register --- yabause/src/scu.c | 56 ++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/yabause/src/scu.c b/yabause/src/scu.c index dd0107fd87..84fca0c731 100644 --- a/yabause/src/scu.c +++ b/yabause/src/scu.c @@ -2179,9 +2179,10 @@ void ScuExec(u32 cycles) { #endif // is dsp executing? + DebugPrintf(MainLog, __FILE__, __LINE__, "EX: %d\n", ScuDsp->ProgControlPort.part.EX); if (ScuDsp->ProgControlPort.part.EX) { while (timing > 0) { - u32 instruction; + u32 instruction; // Make sure it isn't one of our breakpoints for (i=0; i < ScuBP->numcodebreakpoints; i++) { @@ -2425,7 +2426,8 @@ void ScuExec(u32 cycles) { default: break; } - switch (instruction >> 30) { + switch (instruction >> 30) + { case 0x00: // Operation Commands // X-bus @@ -2703,18 +2705,20 @@ void ScuExec(u32 cycles) { case 0x0F: // End Commands ScuDsp->ProgControlPort.part.EX = 0; - if (instruction & 0x8000000) { + if (instruction == 0xF8000000) { // End with Interrupt ScuDsp->ProgControlPort.part.E = 1; ScuSendDSPEnd(); } LOG("dsp has ended\n"); - //dsp_trace_log("END\n"); - ScuDsp->ProgControlPort.part.P = ScuDsp->PC+1; + ScuDsp->ProgControlPort.part.P = ScuDsp->PC + 1; + ScuDsp->PC++; timing = 1; break; - default: break; + + default: + break; } break; } @@ -2722,27 +2726,25 @@ void ScuExec(u32 cycles) { LOG("scu\t: Invalid DSP opcode %08X at offset %02X\n", instruction, ScuDsp->PC); break; } + + if (ScuDsp->ProgControlPort.part.EX) { + ScuDsp->MUL.all = (s64)ScuDsp->RX * (s64)ScuDsp->RY; + ScuDsp->PC++; - ScuDsp->MUL.all = (s64)ScuDsp->RX * (s64)ScuDsp->RY; - - - //LOG("RX=%08X,RY=%08X,MUL=%16X\n", ScuDsp->RX, ScuDsp->RY, ScuDsp->MUL.all); - //LOG("RX=%08X,RY=%08X,MUL=%16X\n", ScuDsp->RX, ScuDsp->RY, ScuDsp->MUL.all); - //dsp_trace_log("RX=%08X,RY=%08X,MUL=%16X\n", ScuDsp->RX, ScuDsp->RY, ScuDsp->MUL.all); - - - ScuDsp->PC++; - - // Handle delayed jumps - if (ScuDsp->jmpaddr != 0xFFFFFFFF) - { - if (ScuDsp->delayed) + // Handle delayed jumps + if (ScuDsp->jmpaddr != 0xFFFFFFFF) { - ScuDsp->PC = (unsigned char)ScuDsp->jmpaddr; - ScuDsp->jmpaddr = 0xFFFFFFFF; + if (ScuDsp->delayed) + { + ScuDsp->PC = (unsigned char)ScuDsp->jmpaddr; + ScuDsp->jmpaddr = 0xFFFFFFFF; + } + else + ScuDsp->delayed = 1; } - else - ScuDsp->delayed = 1; + } else { + // If the program is not executing anymore, quit loop. + break; } timing--; @@ -3513,7 +3515,11 @@ void scu_dsp_int_set_program_control(u32 val) } u32 scu_dsp_int_get_program_control() { - return (ScuDsp->ProgControlPort.all & 0x00FD00FF); + // Must clear (E - End flag) and (V - Overflow flag) on readout. + const u32 portCopy = ScuDsp->ProgControlPort.all; + ScuDsp->ProgControlPort.part.E = 0; + ScuDsp->ProgControlPort.part.V = 0; + return (portCopy & 0x00FD00FF); } u32 scu_dsp_int_get_data_ram() From 1281eb913c8b0c3a70932d8bf71e732eab13ed7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Sat, 18 Sep 2021 21:47:38 +0200 Subject: [PATCH 13/17] Bump version and add C++17 requirement --- yabause/CMakeLists.txt | 2 +- yabause/ChangeLog | 6 +++++ yabause/src/CMakeLists.txt | 24 ++++++++++--------- yabause/src/Makefile.dc | 2 +- yabause/src/cocoa/Yabause-Info.plist | 2 +- .../cocoa/Yabause.xcodeproj/project.pbxproj | 4 ++-- yabause/src/gtk/doc/yabause.1 | 2 +- yabause/src/qt/doc/yabause.1 | 2 +- 8 files changed, 26 insertions(+), 18 deletions(-) diff --git a/yabause/CMakeLists.txt b/yabause/CMakeLists.txt index 4ff713e99f..833c2f7de7 100644 --- a/yabause/CMakeLists.txt +++ b/yabause/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 2.8) set(YAB_PACKAGE yabause) set(YAB_VERSION_MAJOR 0) set(YAB_VERSION_MINOR 9) -set(YAB_VERSION_PATCH 16) +set(YAB_VERSION_PATCH 17) set(YAB_VERSION "${YAB_VERSION_MAJOR}.${YAB_VERSION_MINOR}.${YAB_VERSION_PATCH}") set(CPACK_SOURCE_GENERATOR TGZ) diff --git a/yabause/ChangeLog b/yabause/ChangeLog index 620f23d435..56e2ba1093 100644 --- a/yabause/ChangeLog +++ b/yabause/ChangeLog @@ -1,3 +1,9 @@ +0.9.16 -> 0.9.17 + general: + - Fixed DSP end termination handling (JIT still missing) + - Fixed DSP reset of V/E bits when acessing the control register + qt: + - Add experimental code debugging support with addr2line 0.9.15 -> 0.9.16 general: - Fixed reading cdblock data transfer register as a word diff --git a/yabause/src/CMakeLists.txt b/yabause/src/CMakeLists.txt index 4bd7730d40..fd9cc1bcd0 100755 --- a/yabause/src/CMakeLists.txt +++ b/yabause/src/CMakeLists.txt @@ -711,38 +711,40 @@ add_definitions(-DVERSION=\"${YAB_VERSION}\") include(CheckCXXCompilerFlag) if (MSVC) if(NOT (MSVC_VERSION LESS 1800)) - set(COMPILER_SUPPORTS_CXX11 ON) + set(COMPILER_SUPPORTS_CXX17 ON) else() - message(STATUS "Not enough C++11 support for dynarecs.") + message(STATUS "Not enough C++17 support for dynarecs.") endif() elseif(ANDROID) message(STATUS "CodeGen needs exceptions and rtti. Dynarecs disabled.") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(STATUS "CodeGen doesn't build in Clang yet. Dynarecs disabled.") else() - CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11) + CHECK_CXX_COMPILER_FLAG(-std=c++17 COMPILER_SUPPORTS_CXX17) check_cxx_source_compiles(" #include + #include int main() { std::list list; list.erase(list.cbegin()); + std::filesystem::path myPath; } - " CXX11_ERASE_CONST) + " CXX17_ERASE_CONST) - if(NOT CXX11_ERASE_CONST) - set(COMPILER_SUPPORTS_CXX11 OFF) + if(NOT CXX17_ERASE_CONST) + set(COMPILER_SUPPORTS_CXX17 OFF) endif() - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + if(COMPILER_SUPPORTS_CXX17) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") else() - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} doesn't have enough C++11 support. Dynarecs disabled.") + message(STATUS "The compiler ${CMAKE_CXX_COMPILER} doesn't have enough C++17 support. Dynarecs disabled.") endif() endif() option(YAB_USE_PLAY_JIT "Enable Play codegen and dynarecs." ON) -if (YAB_USE_PLAY_JIT AND COMPILER_SUPPORTS_CXX11) +if (YAB_USE_PLAY_JIT AND COMPILER_SUPPORTS_CXX17) add_subdirectory(play) add_definitions(-DHAVE_PLAY_JIT=1) set(yabause_SOURCES ${yabause_SOURCES} scsp_dsp_jit.cpp scu_dsp_jit.cpp sh2_jit.cpp) @@ -751,7 +753,7 @@ endif() add_library(yabause ${yabause_SOURCES} ${yabause_HEADERS}) -if (YAB_USE_PLAY_JIT AND COMPILER_SUPPORTS_CXX11) +if (YAB_USE_PLAY_JIT AND COMPILER_SUPPORTS_CXX17) target_link_libraries(yabause CodeGen) endif() diff --git a/yabause/src/Makefile.dc b/yabause/src/Makefile.dc index bed235aaed..2b5a76f073 100644 --- a/yabause/src/Makefile.dc +++ b/yabause/src/Makefile.dc @@ -22,7 +22,7 @@ all: yabause.bin include $(KOS_BASE)/Makefile.rules -KOS_CFLAGS += -I. -DDEBUG -DNO_CLI -DVERSION="0.9.16" +KOS_CFLAGS += -I. -DDEBUG -DNO_CLI -DVERSION="0.9.17" KOS_ASFLAGS += -g OBJS = bios.o cdbase.o cheat.o cs0.o cs1.o cs2.o debug.o error.o m68kd.o \ diff --git a/yabause/src/cocoa/Yabause-Info.plist b/yabause/src/cocoa/Yabause-Info.plist index 748530aaa8..1cb7ac7d65 100644 --- a/yabause/src/cocoa/Yabause-Info.plist +++ b/yabause/src/cocoa/Yabause-Info.plist @@ -19,7 +19,7 @@ CFBundleSignature ???? CFBundleShortVersionString - 0.9.16 + 0.9.17 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} CFBundleVersion diff --git a/yabause/src/cocoa/Yabause.xcodeproj/project.pbxproj b/yabause/src/cocoa/Yabause.xcodeproj/project.pbxproj index 0e40e583f3..604c8d7af9 100644 --- a/yabause/src/cocoa/Yabause.xcodeproj/project.pbxproj +++ b/yabause/src/cocoa/Yabause.xcodeproj/project.pbxproj @@ -750,7 +750,7 @@ HAVE_STRCASECMP, "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1)", ); - GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "VERSION=\\\"0.9.16\\\""; + GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "VERSION=\\\"0.9.17\\\""; GCC_VERSION = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; @@ -779,7 +779,7 @@ HAVE_STRCASECMP, "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1)", ); - GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "VERSION=\\\"0.9.16\\\""; + GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "VERSION=\\\"0.9.17\\\""; GCC_VERSION = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; diff --git a/yabause/src/gtk/doc/yabause.1 b/yabause/src/gtk/doc/yabause.1 index e20c09c6ce..ba9efdede9 100644 --- a/yabause/src/gtk/doc/yabause.1 +++ b/yabause/src/gtk/doc/yabause.1 @@ -1,4 +1,4 @@ -.TH YABAUSE 1 "May 26, 2021" "yabause-0.9.16" +.TH YABAUSE 1 "Sep 18, 2021" "yabause-0.9.17" .SH NAME yabause \- Yet Another Buggy And Uncomplete Saturn Emulator .SH SYNOPSIS diff --git a/yabause/src/qt/doc/yabause.1 b/yabause/src/qt/doc/yabause.1 index 9ae78c394a..5e1c67424f 100644 --- a/yabause/src/qt/doc/yabause.1 +++ b/yabause/src/qt/doc/yabause.1 @@ -1,4 +1,4 @@ -.TH YABAUSE 1 "May 26, 2021" "yabause-0.9.16" +.TH YABAUSE 1 "Sep 18, 2021" "yabause-0.9.17" .SH NAME yabause \- Yet Another Buggy And Uncomplete Saturn Emulator .SH SYNOPSIS From b57271d8e2a54b1f7bc9c66956b2814eb75ce128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Sun, 19 Sep 2021 00:10:58 +0200 Subject: [PATCH 14/17] Add required flag for compiling on linux systems --- yabause/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/yabause/src/CMakeLists.txt b/yabause/src/CMakeLists.txt index fd9cc1bcd0..771e8e339a 100755 --- a/yabause/src/CMakeLists.txt +++ b/yabause/src/CMakeLists.txt @@ -722,6 +722,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") else() CHECK_CXX_COMPILER_FLAG(-std=c++17 COMPILER_SUPPORTS_CXX17) + SET(CMAKE_REQUIRED_FLAGS "-std=c++17") check_cxx_source_compiles(" #include #include From 4c37dc364d06668223f9e454a709e1a411f44745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Sun, 19 Sep 2021 16:42:57 +0200 Subject: [PATCH 15/17] Forgotten play C++17 requirements behind --- yabause/src/play/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yabause/src/play/CMakeLists.txt b/yabause/src/play/CMakeLists.txt index 493ecac7f1..d98bc9aa32 100644 --- a/yabause/src/play/CMakeLists.txt +++ b/yabause/src/play/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) project(CodeGen CXX) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_library(CodeGen From e416dc7afe28c94d1e52c5723d829f5cf9619483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Thu, 29 Dec 2022 18:34:25 -0300 Subject: [PATCH 16/17] Add profiler to SH2, outputting yabause_performance.csv per subroutine providing execution time in ms and execution count for each address between 0x06004000 and 0x0600FFFF --- yabause/src/qt/ui/UIDebugSH2.cpp | 2 +- yabause/src/sh2core.c | 86 +++++++++++++++++++++++++++++++- yabause/src/sh2core.h | 29 +++++++++++ yabause/src/sh2int.c | 64 ++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 2 deletions(-) diff --git a/yabause/src/qt/ui/UIDebugSH2.cpp b/yabause/src/qt/ui/UIDebugSH2.cpp index 6868038eb4..ae75ab8209 100644 --- a/yabause/src/qt/ui/UIDebugSH2.cpp +++ b/yabause/src/qt/ui/UIDebugSH2.cpp @@ -366,7 +366,7 @@ void UIDebugSH2::updateCodePage(u32 evaluateAddress) if (addr2line.isEmpty()) codeBrowser->setText("addr2line utility is not configured properly, source not available."); else - codeBrowser->setText("Source not found or available."); + codeBrowser->setText(QString("Source not found or available. Stdout was:\n") + pstdout); } } } diff --git a/yabause/src/sh2core.c b/yabause/src/sh2core.c index a63a8b4828..fda69dbc4a 100644 --- a/yabause/src/sh2core.c +++ b/yabause/src/sh2core.c @@ -54,6 +54,9 @@ SH2Interface_struct *SH1Core=NULL; SH2Interface_struct *SH2Core=NULL; extern SH2Interface_struct *SH2CoreList[]; +FILE* ProfilerLogFile = NULL; +const char* ProfilerLogFilename = "yabause_performance.csv"; + void OnchipReset(SH2_struct *context); void FRTExec(SH2_struct *sh, u32 cycles); void WDTExec(SH2_struct *sh, u32 cycles); @@ -146,6 +149,12 @@ int SH2Init(int coreid) if (SH2TrackInfLoopInit(MSH2) != 0) return -1; + if (SH2NightzProfilerInitResetFile() != 0) + return -1; + + if (SH2NightzProfilerInit(MSH2) != 0) + return -1; + MSH2->onchip.BCR1 = 0x0000; MSH2->isslave = 0; MSH2->model = SHMT_SH2; @@ -159,6 +168,9 @@ int SH2Init(int coreid) if (SH2TrackInfLoopInit(SSH2) != 0) return -1; + if (SH2NightzProfilerInit(SSH2) != 0) + return -1; + SSH2->onchip.BCR1 = 0x8000; SSH2->isslave = 1; SSH2->model = SHMT_SH2; @@ -213,11 +225,13 @@ void SH2DeInit() { if (SH2Core) SH2Core->DeInit(); - SH2Core = NULL; + SH2Core = NULL; + if (MSH2) { SH2TrackInfLoopDeInit(MSH2); + SH2NightzProfilerDeInit(MSH2); free(MSH2); } MSH2 = NULL; @@ -225,8 +239,11 @@ void SH2DeInit() if (SSH2) { SH2TrackInfLoopDeInit(SSH2); + SH2NightzProfilerDeInit(SSH2); free(SSH2); } + + SH2NightzProfilerDeInitResetFile(); SSH2 = NULL; } @@ -433,6 +450,73 @@ void SH2TrackInfLoopClear(SH2_struct *context) ////////////////////////////////////////////////////////////////////////////// +int SH2NightzProfilerInitResetFile() +{ + ProfilerLogFile = fopen(ProfilerLogFilename, "w"); + if (ProfilerLogFile != NULL) + { + fprintf(ProfilerLogFile, "Count,Time(ms),Ptr(H)\n"); + return 0; + } + else + { + return -1; + } +} + +int SH2NightzProfilerDeInitResetFile() +{ + if (ProfilerLogFile) + { + fclose(ProfilerLogFile); + ProfilerLogFile = NULL; + } + + return 0; +} + +int SH2NightzProfilerInit(SH2_struct* context) +{ + if (context) + { + context->profilerInfo.stackPos = -1; + memset(context->profilerInfo.profile, 0, + PROFILE_NUM_INFOS * sizeof(struct SH2_ProfilerInfo)); + + memset(context->profilerInfo.stack, 0, + PROFILE_STACK_SIZE * sizeof(struct SH2_ProfilerStackInfo)); + + return 0; + } + else + { + return -1; + } +} + +////////////////////////////////////////////////////////////////////////////// + +void SH2NightzProfilerDeInit(SH2_struct *context) +{ + if (!context) + return; + + if (ProfilerLogFile) + { + for (u32 i = 0; i < PROFILE_NUM_INFOS; ++i) + { + struct SH2_ProfilerInfo* info = &context->profilerInfo.profile[i]; + if (info->count > 0) + { + fprintf(ProfilerLogFile, "%d,%d,%x\n", + info->count, info->time, PROFILE_START_ADDRESS + i); + } + } + } +} + +////////////////////////////////////////////////////////////////////////////// + void SH2GetRegisters(SH2_struct *context, sh2regs_struct * r) { if (r != NULL) { diff --git a/yabause/src/sh2core.h b/yabause/src/sh2core.h index 4eede4fa39..45d437a50d 100644 --- a/yabause/src/sh2core.h +++ b/yabause/src/sh2core.h @@ -357,6 +357,25 @@ typedef struct typedef struct SH2Interface_struct SH2Interface_struct; #include "sh2_jit.h" +#include + +struct SH2_ProfilerStackInfo +{ + u32 address; + clock_t startTime; + long totalTime; +}; + +struct SH2_ProfilerInfo +{ + long time; + u32 count; +}; + +#define PROFILE_STACK_SIZE 4096 +#define PROFILE_NUM_INFOS 0xFFFF +#define PROFILE_START_ADDRESS 0x06004000 +#define PROFILE_END_ADDRESS 0x0600FFFF struct SH2_struct { @@ -434,6 +453,11 @@ struct SH2_struct int maxNum; } trackInfLoop; + struct { + struct SH2_ProfilerInfo profile[PROFILE_NUM_INFOS]; + struct SH2_ProfilerStackInfo stack[PROFILE_STACK_SIZE]; + s32 stackPos; + } profilerInfo; }; struct SH2Interface_struct @@ -499,6 +523,11 @@ void SH2TrackInfLoopStart(SH2_struct *context); void SH2TrackInfLoopStop(SH2_struct *context); void SH2TrackInfLoopClear(SH2_struct *context); +int SH2NightzProfilerInitResetFile(); +int SH2NightzProfilerDeInitResetFile(); +int SH2NightzProfilerInit(SH2_struct *context); +void SH2NightzProfilerDeInit(SH2_struct *context); + void SH2GetRegisters(SH2_struct *context, sh2regs_struct * r); void SH2SetRegisters(SH2_struct *context, sh2regs_struct * r); void SH2WriteNotify(u32 start, u32 length); diff --git a/yabause/src/sh2int.c b/yabause/src/sh2int.c index c6f9696b26..9ab536db50 100644 --- a/yabause/src/sh2int.c +++ b/yabause/src/sh2int.c @@ -39,6 +39,8 @@ #include "sh2trace.h" #endif +#include + SH2Interface_struct SH2Interpreter = { SH2CORE_INTERPRETER, "SH2 Interpreter", @@ -111,6 +113,55 @@ SH2Interface_struct SH2DebugInterpreter = { NULL // SH2WriteNotify not used }; +static u8 FASTCALL nightzTrackAddr(u32 addr) +{ + return addr >= PROFILE_START_ADDRESS + && addr < PROFILE_END_ADDRESS; +} + +static void FASTCALL nightzTrack(SH2_struct* sh) +{ + const u32 pcAddr = sh->regs.PC; + if (nightzTrackAddr(pcAddr)) + { + assert(pcAddr >= PROFILE_START_ADDRESS); + + const u32 addr = pcAddr - PROFILE_START_ADDRESS; + assert(addr < PROFILE_NUM_INFOS); + + if (sh->profilerInfo.stackPos < PROFILE_STACK_SIZE) + { + sh->profilerInfo.stackPos++; + assert(sh->profilerInfo.stackPos >= 0); + assert(sh->profilerInfo.stackPos < PROFILE_STACK_SIZE); + + struct SH2_ProfilerStackInfo* info = + &sh->profilerInfo.stack[sh->profilerInfo.stackPos]; + + info->address = addr; + info->startTime = clock(); + } + } +} + +static void FASTCALL nightzStopTrack(SH2_struct* sh) +{ + const s32 stackPos = sh->profilerInfo.stackPos; + if (stackPos >= 0) + { + struct SH2_ProfilerStackInfo* stackInfo = + &sh->profilerInfo.stack[stackPos]; + + struct SH2_ProfilerInfo* info = + &sh->profilerInfo.profile[stackInfo->address]; + + info->time += clock() - stackInfo->startTime; + info->count++; + sh->profilerInfo.stackPos--; + } +} + + ////////////////////////////////////////////////////////////////////////////// int sh2_check_wait(SH2_struct * sh, u32 addr, int size) @@ -452,6 +503,8 @@ static void FASTCALL SH2bsr(SH2_struct * sh) if ((disp&0x800) != 0) disp |= 0xFFFFF000; sh->regs.PR = sh->regs.PC + 4; sh->regs.PC = sh->regs.PC+(disp<<1) + 4; + + nightzTrack(sh); sh->cycles += 2; SH2delay(sh, temp + 2); @@ -465,6 +518,9 @@ static void FASTCALL SH2bsrf(SH2_struct * sh) sh->regs.PR = sh->regs.PC + 4; sh->regs.PC += sh->regs.R[INSTRUCTION_B(sh->instruction)] + 4; sh->cycles += 2; + + nightzTrack(sh); + SH2delay(sh, temp + 2); } @@ -951,6 +1007,9 @@ static void FASTCALL SH2jsr(SH2_struct * sh) sh->regs.PR = sh->regs.PC + 4; sh->regs.PC = sh->regs.R[m]; sh->cycles += 2; + + nightzTrack(sh); + SH2delay(sh, temp + 2); } @@ -1882,6 +1941,9 @@ static void FASTCALL SH2rte(SH2_struct * sh) { u32 temp; temp=sh->regs.PC; + + nightzStopTrack(sh); + sh->regs.PC = sh->MappedMemoryReadLong(sh, sh->regs.R[15]); sh->regs.R[15] += 4; sh->regs.SR.all = sh->MappedMemoryReadLong(sh, sh->regs.R[15]) & 0x000003F3; @@ -1898,6 +1960,8 @@ static void FASTCALL SH2rts(SH2_struct * sh) temp = sh->regs.PC; sh->regs.PC = sh->regs.PR; + + nightzStopTrack(sh); sh->cycles += 2; SH2delay(sh, temp + 2); From 7c3f7b71574e9745a8f752f517ce29f50ac2c16d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romulo=20Leit=C3=A3o?= Date: Fri, 20 Jan 2023 14:29:34 -0300 Subject: [PATCH 17/17] Add script to easily configure cmake --- yabause/generate_build_from_cmake.ps1 | 34 +++++++++++++++++++++++++++ yabause/src/qt/CMakeLists.txt | 4 ++++ 2 files changed, 38 insertions(+) create mode 100644 yabause/generate_build_from_cmake.ps1 diff --git a/yabause/generate_build_from_cmake.ps1 b/yabause/generate_build_from_cmake.ps1 new file mode 100644 index 0000000000..7ce20a9309 --- /dev/null +++ b/yabause/generate_build_from_cmake.ps1 @@ -0,0 +1,34 @@ +$qtPath = 'D:\Desenvolvimento\Qt\Qt5.7.1\5.7\msvc2015_64' +$scriptDir = $PSScriptRoot + +$vars = @() +$vars += [System.Tuple]::Create("QT_QMAKE_EXECUTABLE", "${qtPath}\bin\qmake.exe") +$vars += [System.Tuple]::Create("Qt5Core_DIR", "${qtPath}\lib\cmake\Qt5Core") +$vars += [System.Tuple]::Create("Qt5Gui_DIR", "${qtPath}\lib\cmake\Qt5Gui") +$vars += [System.Tuple]::Create("Qt5Multimedia_DIR", "${qtPath}\lib\cmake\Qt5Multimedia") +$vars += [System.Tuple]::Create("Qt5Network_DIR", "${qtPath}\lib\cmake\Qt5Network") +$vars += [System.Tuple]::Create("Qt5OpenGL_DIR", "${qtPath}\lib\cmake\Qt5OpenGL") +$vars += [System.Tuple]::Create("Qt5Widgets_DIR", "${qtPath}\lib\cmake\Qt5Widgets") +$vars += [System.Tuple]::Create("Qt5_DIR", "${qtPath}\lib\cmake\Qt5") +$vars += [System.Tuple]::Create("CMAKE_INSTALL_PREFIX", "${scriptDir}\..\build_install") +$vars += [System.Tuple]::Create("OPENAL_LIBRARY", "${scriptDir}\..\dependencies\OpenAL\libs\Win64\OpenAL32.lib") +$vars += [System.Tuple]::Create("OPENAL_INCLUDE_DIR", "${scriptDir}\..\dependencies\OpenAL\include") +$vars += [System.Tuple]::Create("SH2_DYNAREC", "1") +$vars += [System.Tuple]::Create("SH2_TRACE", "1") +$vars += [System.Tuple]::Create("SH2_UBC", "1") +$vars += [System.Tuple]::Create("YAB_NETWORK", "1") + +$cmd = "cmake" +$args = "${scriptDir}" +$args += ' -G "Visual Studio 17 2022"' +foreach ($var in $vars) { + $param = $var.Item1 + $value = Resolve-Path $var.Item2 -ErrorAction Ignore + if (-not $value) { + $value = $var.Item2 + } + + $args += " -D${param}=${value}" +} + +Start-Process $cmd -ArgumentList $args -Wait -NoNewWindow \ No newline at end of file diff --git a/yabause/src/qt/CMakeLists.txt b/yabause/src/qt/CMakeLists.txt index e299ec2d98..02d7b7e871 100644 --- a/yabause/src/qt/CMakeLists.txt +++ b/yabause/src/qt/CMakeLists.txt @@ -4,6 +4,10 @@ yab_port_start() option(YAB_USE_QT5 "Use Qt 5 if available." ON) +set(CMAKE_CXX_STANDARD 17) + +set(CMAKE_CXX_STANDARD_REQUIRED True) + if(YAB_USE_QT5) find_package(Qt5 COMPONENTS Widgets QUIET) endif()