diff --git a/docs/release-notes.txt b/docs/release-notes.txt index 811b3d5..36580fe 100644 --- a/docs/release-notes.txt +++ b/docs/release-notes.txt @@ -1,44 +1,74 @@ +Retro Debugger v0.64.70 (Xmas 24 Dec'24 release) +Added: Remote debug WebSockets server on port $0DEB (thanks to Mojzesh for thorough testing, bug fixing and valuable assistance) + Check out the library and a great example of usage in Go, created by Mojzesh: https://github.com/mojzesh/c64d-ws-client +Added: C64 mouse support (thanks to Anthony Savva for pointing this out) +Added: Display current value (hex, dec, binary) in Memory/Data Dump views (thanks to Brush/Elysium for pointing this out) +Added: Support of Windows ARM64 architecture +Bug fixed: selecting C64 Vice border mode in Settings was not refreshing Screen and VIC Editor texture boundaries (thanks to DKT/Samar for reporting) +Bug fixed: searching for label was not finding it (thanks to Stein Pedersen for reporting and a fix) +Bug fixed: VicEditor's automatic grid lines were not updated on startup +Bug fixed: crash when scrubbing timeline when EasyFlash with state was attached +Bug fixed (Linux): fixes for CMake files, PR #50 (thanks Uffe Jakobsen) +Changed: Adjusted label resolution to prioritize +N labels over -N when closely positioned, especially for 16-bit pointers (thanks to Brush/Elysium for reporting) +Changed: More user-friendly message for not found ROMs, PR #68 (thanks to jumpjack) +Changed: Use project-relative paths in Visual Studio project files, PR #63 (thanks to Stein Pedersen) +... and a lot of refactoring and other various bug fixes. + +Enjoy my first ever DJ Set created for New Year's Eve EOY 2024/25 party! Play here: https://youtu.be/LZF44uOo1_g + +Retro Debugger v0.64.68 (Moonshine Dragons release) +Added: 1541 Drive disk contents editor and GCR view (C64/1541 Drive/1541 Disk contents and 1541 GCR Disk data) +Added: 1541 Drive memory map for full 64kB and only RAM +Fixed: 1541 Drive memory map allows zooming (thx to Bacchus/Fairlight for reporting) +Fixed: Clicking on 1541 Drive memory map moves to proper address in 1541 Drive memory dump (thx to Bacchus/Fairlight for reporting) +Added: Settings/C64/Reset C64 before PRG load allows selecting BASIC snapshot as starting point (note, this is now the best option to autostart PRG files, although only C64 PAL is now supported. Thx to Brush/Elysium for testing) +Changed: F7 keyboard shortcut to show D64 disk browser is now changed to Alt+F7, and F3 to Alt+F3, to not conflict with Action Replay/Retro Replay menu when bypass key shortcuts option is selected +Added: Store zoom and position of VIC Display screen and All Screens panes (note, VIC Editor's screen position may be off, you may need to zoom in and setup position manually after upgrading layout) +Added: Context menu to show controller in All Screens views +Added: Setting UI/Hide tab bar triangle icon +Added: #44 remember selected Segment when file is reloaded (thanks to SingleCopy for world's first PR to RetroDebugger!) +Fixed: #32 "$" input in C64 Data watch causes crash +Fixed: intermittent crash on quit when drive browser was refreshing contents +Fixed: crash on startup when multiple command line parameters were passed to Vice (thanks to Stephen D. for reporting) +Fixed: bug that caused strange random characters to be displayed in comment when a new debug event was created (thanks to David Youd for mentioning this in his video). +Fixed: C64 detach disk correctly now properly clears disk directory in D64 disk browser +Fixed: menu bar that consumed keyboard shortcuts, causing e.g. VIC Display to not respond to Ctrl+L/R arrows, as they were consumed by emulation rewind (thanks to Tom Telmo for reporting) +Fixed: 1541 Drive directory was not updated on snapshot reload +Fixed: Disassembly line bar was disappearing in some rare edge cases +Fixed: Paiting in VIC Editor using right mouse button did not work on mouse move +Fixed Windows: do not show system console when user started debugger by clicking on file (thx to Isildur/Samar for reporting) +Fixed Windows: #40 Window position is not correctly restored on restart on MS Windows (thx to Isildur/Samar for reporting) +Fixed Linux: #27 Compiling v0.64.66 on Debian fails with "unknown type name ‘BYTE’" +Fixed Linux: #31 Implicit Declaration errors +Fixed Linux: #43 Missing gcc compiler flag +Fixed Linux: #46 Leftover CViewC64KeyMap view in Screens folder was used instead of new version of this view (thanks to thecky for PR) + +Plus various fixes and improvements in CRT Maker plugin, +... and as always a lot of refactoring and small bug and crash fixes. + + Retro Debugger v0.64.66 (Xmas release) -Added: Debug Events History view (e.g. past breakpoints), you can now rewind - code to specific breakpoint (suggested by Brush/Elysium). - See demo: https://youtu.be/v_sunlK6_wo -Added: Memory Monitor view to track memory changes. - See demo: https://youtu.be/0r-z36Lk6TQ -Added: Memory Plot view (suggested by Digger/Elysium). - See demo: https://youtu.be/qqALSiTesHc -Added: File browser view (suggested by Chash/Caution^Fraction). - See demo: https://youtu.be/ctYunZSYzsU +Added: Debug Events History view (e.g. past breakpoints), you can now rewind code to specific breakpoint (suggested by Brush/Elysium). See demo: https://youtu.be/v_sunlK6_wo +Added: Memory Monitor view to track memory changes. See demo: https://youtu.be/0r-z36Lk6TQ +Added: Memory Plot view (suggested by Digger/Elysium). See demo: https://youtu.be/qqALSiTesHc +Added: File browser view (suggested by Chash/Caution^Fraction). See demo: https://youtu.be/ctYunZSYzsU Added: SidDump-style export in SID Tracker history view context menu -Added: New flags to memory markers dump: - VicScreen, VicSpritePointer, VicCharset, VicBitmap, VicColorRam - (suggested by Wacek/Arise) -Added: show labels with offsets in disassembly when label is not found - (e.g. label+1, label+2, etc.), configurable in Settings - (suggested by Brush/Elysium) -Added: Reset keymap to default - (issue https://github.com/slajerek/RetroDebugger/issues/22) +Added: New flags to memory markers dump: VicScreen, VicSpritePointer, VicCharset, VicBitmap, VicColorRam (suggested by Wacek/Arise) +Added: show labels with offsets in disassembly when label is not found (e.g. label+1, label+2, etc.), configurable in Settings (suggested by Brush/Elysium) +Added: Reset keymap to default (issue https://github.com/slajerek/RetroDebugger/issues/22) Added: 1541 disk directory view: format new disk image, add prg to disk image -Added: Context menu in the Memory map with an option to select CPU, or RAM - (suggested by Bacchus/Fairlight) -Added: Reset can now start emulation and continue running automatically, - configurable in Settings +Added: Context menu in the Memory map with an option to select CPU, or RAM (suggested by Bacchus/Fairlight) +Added: Reset can now start emulation and continue running automatically, configurable in Settings Added: Borrowed opensource fonts from Furnace tracker -Fixed: Setting emulator's screen zoom to 25%, 50%, 100% was off one pixel due - to recent refactorings (thanks to Jetboy/Elysium for reporting) -Fixed: mouse position and clicks were not properly forwarded to GoatTracker2 plugin - (thanks to Linus for reporting) -Fixed: sometimes invisible views could consume mouse clicks and other events - (thanks to Tom Telmo for additional testing) -Fixed: sometimes layout could not load all views parameters when run on older - RetroDebugger version and thus destroing unknown parameters on layout save -Changed MS Windows: Upgrading settings path, moving settings from - C:\ProgramData\RetroDebugger to C:\Users\mars\AppData\Local\RetroDebugger +Fixed: Setting emulator's screen zoom to 25%, 50%, 100% was off one pixel due to recent refactorings (thanks to Jetboy/Elysium for reporting) +Fixed: mouse position and clicks were not properly forwarded to GoatTracker2 plugin (thanks to Linus for reporting) +Fixed: sometimes invisible views could consume mouse clicks and other events (thanks to Tom Telmo for additional testing) +Fixed: sometimes layout could not load all views parameters when run on older RetroDebugger version and thus destroing unknown parameters on layout save +Changed MS Windows: Upgrading settings path, moving settings from C:\ProgramData\RetroDebugger\ to C:\Users\mars\AppData\Local\RetroDebugger\ ... and a lot of refactoring and other various bug fixes. -Big shoutout to Bacchus/Fairlight, Tom Telmo and Jetboy/Elysium for their -last-minute eagle eyes! Just moments before release, these heroes stepped in -to report bugs and conduct extra testing. +Big shoutout to Bacchus/Fairlight, Tom Telmo and Jetboy/Elysium for their last-minute eagle eyes! Just moments before release, these heroes stepped in to report bugs and conduct extra testing. Retro Debugger v0.64.64 The X Party release! diff --git a/platform/MacOS/c64d.xcodeproj/project.pbxproj b/platform/MacOS/c64d.xcodeproj/project.pbxproj index 086866f..68b7404 100644 --- a/platform/MacOS/c64d.xcodeproj/project.pbxproj +++ b/platform/MacOS/c64d.xcodeproj/project.pbxproj @@ -55,6 +55,9 @@ 4113CE9B25F8AF6900FB1236 /* TestTextEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4113CE9A25F8AF6900FB1236 /* TestTextEditor.cpp */; }; 4113F62629E2C5B7002FE970 /* CViewC64KeyMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4113F62429E2C5B7002FE970 /* CViewC64KeyMap.cpp */; }; 412085D323C76BFC00FBD7C3 /* CMainMenuBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 412085D123C76BFC00FBD7C3 /* CMainMenuBar.cpp */; }; + 4121FCE12CC6A1E600095AD3 /* CPipeProtocolDebuggerCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4121FCDA2CC6A1E600095AD3 /* CPipeProtocolDebuggerCallback.cpp */; }; + 4121FCE22CC6A1E600095AD3 /* CDebuggerServerWebSockets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4121FCDD2CC6A1E600095AD3 /* CDebuggerServerWebSockets.cpp */; }; + 4121FCE62CC6AB3900095AD3 /* C64DebuggerPluginParallax.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4121FCE32CC6AB3900095AD3 /* C64DebuggerPluginParallax.cpp */; }; 412897CE2B97D5B600495C47 /* CDataAdapterViceC64DirectRam.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 412897C32B97D5B600495C47 /* CDataAdapterViceC64DirectRam.cpp */; }; 412897CF2B97D5B600495C47 /* CDataAdapterViceC64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 412897C42B97D5B600495C47 /* CDataAdapterViceC64.cpp */; }; 412897D02B97D5B600495C47 /* CDataAdapterViceC64Reu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 412897C52B97D5B600495C47 /* CDataAdapterViceC64Reu.cpp */; }; @@ -67,6 +70,8 @@ 4134B5E4276384E500830012 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4134B5E3276384E400830012 /* GameController.framework */; }; 4134B5EA2763851A00830012 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4134B5E82763851A00830012 /* libiconv.tbd */; }; 4134D04D2B06CBB90032BE07 /* CViewDrive1541DiskData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4134D04C2B06CBB90032BE07 /* CViewDrive1541DiskData.cpp */; }; + 413601C82CE3D97200B562C0 /* CDebugBreakpointRasterLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 413601C72CE3D97200B562C0 /* CDebugBreakpointRasterLine.cpp */; }; + 413601CB2CE3E7BA00B562C0 /* CDebugBreakpointsRasterLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 413601CA2CE3E7BA00B562C0 /* CDebugBreakpointsRasterLine.cpp */; }; 413687832AED4F8D00E40A23 /* CViewDebugEventsHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 413687812AED4F8D00E40A23 /* CViewDebugEventsHistory.cpp */; }; 4137754F2C02245B006BF409 /* C64DebuggerPluginDNDK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4137754C2C02245B006BF409 /* C64DebuggerPluginDNDK.cpp */; }; 413EC7D1266E76CC00CB24D2 /* CViewBreakpoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 413EC7CE266E76CB00CB24D2 /* CViewBreakpoints.cpp */; }; @@ -130,6 +135,8 @@ 419703ED28D36FD100DDD728 /* asap.c in Sources */ = {isa = PBXBuildFile; fileRef = 419703E728D36E0A00DDD728 /* asap.c */; }; 4198907E2684A40900B1AE5C /* CDebugSymbolsSegmentC64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4198907B2684A40900B1AE5C /* CDebugSymbolsSegmentC64.cpp */; }; 41B403BD2600EF6B00C271F3 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 41B403BB2600EF6B00C271F3 /* ApplicationServices.framework */; }; + 41B4D9AB2C8A5D8200E62540 /* C64DebuggerPluginConvolution.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41B4D9A82C8A5D8200E62540 /* C64DebuggerPluginConvolution.cpp */; }; + 41B4D9B22C8A5E4D00E62540 /* C64DebuggerPluginGalaxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41B4D9AF2C8A5E4D00E62540 /* C64DebuggerPluginGalaxy.cpp */; }; 41BA937C2AEAACF30006D4F0 /* CViewDataPlot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41BA937B2AEAACF30006D4F0 /* CViewDataPlot.cpp */; }; 41BBDFB326BFF541006ADD98 /* C64DebuggerPluginTemplate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41BBDFB226BFF541006ADD98 /* C64DebuggerPluginTemplate.cpp */; }; 41BFDD152BC84BDE00002182 /* CDataAddressEditBoxDiskContents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41BFDD132BC84BDE00002182 /* CDataAddressEditBoxDiskContents.cpp */; }; @@ -138,7 +145,6 @@ 41C84A3023C61830007C0889 /* C64DebuggerPluginDummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4A5CD23AA0F0F00A54EB2 /* C64DebuggerPluginDummy.cpp */; }; 41C84A3623C61830007C0889 /* CDebugBreakpoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4A5F123AA0F0F00A54EB2 /* CDebugBreakpoints.cpp */; }; 41C84A3823C61830007C0889 /* CDebugInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4A5F523AA0F0F00A54EB2 /* CDebugInterface.cpp */; }; - 41C84A3923C61830007C0889 /* INT_BinaryProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4A5F823AA0F0F00A54EB2 /* INT_BinaryProtocol.cpp */; }; 41C84A3A23C61830007C0889 /* CDataAdapterAtari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4A61D23AA0F0F00A54EB2 /* CDataAdapterAtari.cpp */; }; 41C84A3B23C61830007C0889 /* CDebugInterfaceAtari.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4A61F23AA0F0F00A54EB2 /* CDebugInterfaceAtari.cpp */; }; 41C84A3C23C61830007C0889 /* AtariWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4A62123AA0F0F00A54EB2 /* AtariWrapper.cpp */; }; @@ -463,10 +469,9 @@ 41C84B7C23C61830007C0889 /* ViceLogWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4AD8823AA0F1100A54EB2 /* ViceLogWrapper.cpp */; }; 41C84B7D23C61830007C0889 /* ViceWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4AD8A23AA0F1100A54EB2 /* ViceWrapper.cpp */; }; 41C84B7F23C61830007C0889 /* CViewAbout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADDC23AA0F1100A54EB2 /* CViewAbout.cpp */; }; - 41C84B8023C61830007C0889 /* CViewBreakpointsOLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADDE23AA0F1100A54EB2 /* CViewBreakpointsOLD.cpp */; }; 41C84B8223C61830007C0889 /* CViewColodore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADE423AA0F1100A54EB2 /* CViewColodore.cpp */; }; 41C84B8423C61830007C0889 /* CViewKeyboardShortcuts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADE823AA0F1100A54EB2 /* CViewKeyboardShortcuts.cpp */; }; - 41C84B8523C61830007C0889 /* CViewMainMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADEA23AA0F1100A54EB2 /* CViewMainMenu.cpp */; }; + 41C84B8523C61830007C0889 /* CMainMenuHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADEA23AA0F1100A54EB2 /* CMainMenuHelper.cpp */; }; 41C84B8623C61830007C0889 /* CViewSettingsMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADEC23AA0F1100A54EB2 /* CViewSettingsMenu.cpp */; }; 41C84B8723C61830007C0889 /* CViewSnapshots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADEE23AA0F1100A54EB2 /* CViewSnapshots.cpp */; }; 41C84B8823C61830007C0889 /* C64DisplayListCodeGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D4ADF123AA0F1100A54EB2 /* C64DisplayListCodeGenerator.cpp */; }; @@ -1214,10 +1219,19 @@ 41EE306125E93B050050257F /* NstBoardAction53.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41EE305F25E93B050050257F /* NstBoardAction53.cpp */; }; 41EE306525E93B2B0050257F /* NstHomebrew.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41EE306325E93B2B0050257F /* NstHomebrew.cpp */; }; 41EE306A25E93C450050257F /* NstBoardInlNsf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41EE306825E93C450050257F /* NstBoardInlNsf.cpp */; }; + 41F616BA2CCAA839001253EE /* CDebuggerServerApiVice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F616B92CCAA838001253EE /* CDebuggerServerApiVice.cpp */; }; + 41F665B02CB11E5900EFFFD5 /* CDebugBreakpointData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F665AC2CB11E5900EFFFD5 /* CDebugBreakpointData.cpp */; }; + 41F665B12CB11E5900EFFFD5 /* CDebugBreakpointAddr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F665AD2CB11E5900EFFFD5 /* CDebugBreakpointAddr.cpp */; }; + 41F665B22CB11E5900EFFFD5 /* CDebugBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F665AE2CB11E5900EFFFD5 /* CDebugBreakpoint.cpp */; }; + 41F665B52CB1215300EFFFD5 /* CDebugBreakpointEventCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F665B42CB1215300EFFFD5 /* CDebugBreakpointEventCallback.cpp */; }; + 41F665BA2CB1246000EFFFD5 /* CDebugBreakpointsAddr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F665B72CB1246000EFFFD5 /* CDebugBreakpointsAddr.cpp */; }; + 41F665BB2CB1246000EFFFD5 /* CDebugBreakpointsData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F665B92CB1246000EFFFD5 /* CDebugBreakpointsData.cpp */; }; 41F8CF9B294E0C6F000AECAE /* CViewC64AllGraphicsSpritesControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F8CF96294E0C6E000AECAE /* CViewC64AllGraphicsSpritesControl.cpp */; }; 41F8CFA5294E0FC7000AECAE /* CViewC64AllGraphicsCharsetsControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F8CFA2294E0FC6000AECAE /* CViewC64AllGraphicsCharsetsControl.cpp */; }; 41F8CFA6294E0FC7000AECAE /* CViewC64AllGraphicsScreensControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F8CFA3294E0FC6000AECAE /* CViewC64AllGraphicsScreensControl.cpp */; }; 41F8CFA7294E0FC7000AECAE /* CViewC64AllGraphicsBitmapsControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F8CFA4294E0FC7000AECAE /* CViewC64AllGraphicsBitmapsControl.cpp */; }; + 41FB3C0D2CFE0D0800870F9B /* CDebuggerServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41FB3C092CFE0D0800870F9B /* CDebuggerServer.cpp */; }; + 41FB3C0E2CFE0D0800870F9B /* CDebuggerServerApi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41FB3C0B2CFE0D0800870F9B /* CDebuggerServerApi.cpp */; }; 41FD5350293CBAD50051A851 /* CViewC64ColorRamScreen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41FD534E293CBAD40051A851 /* CViewC64ColorRamScreen.cpp */; }; 41FD5357293CC3760051A851 /* CViewC64AllGraphicsSprites.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41FD5355293CC3760051A851 /* CViewC64AllGraphicsSprites.cpp */; }; 41FD535B293CD9420051A851 /* CViewC64AllGraphicsBitmaps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41FD535A293CD9420051A851 /* CViewC64AllGraphicsBitmaps.cpp */; }; @@ -1346,6 +1360,12 @@ 4113F62529E2C5B7002FE970 /* CViewC64KeyMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewC64KeyMap.h; sourceTree = ""; }; 412085D123C76BFC00FBD7C3 /* CMainMenuBar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CMainMenuBar.cpp; sourceTree = ""; }; 412085D223C76BFC00FBD7C3 /* CMainMenuBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CMainMenuBar.h; sourceTree = ""; }; + 4121FCDA2CC6A1E600095AD3 /* CPipeProtocolDebuggerCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CPipeProtocolDebuggerCallback.cpp; sourceTree = ""; }; + 4121FCDB2CC6A1E600095AD3 /* CPipeProtocolDebuggerCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPipeProtocolDebuggerCallback.h; sourceTree = ""; }; + 4121FCDD2CC6A1E600095AD3 /* CDebuggerServerWebSockets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebuggerServerWebSockets.cpp; sourceTree = ""; }; + 4121FCDE2CC6A1E600095AD3 /* CDebuggerServerWebSockets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebuggerServerWebSockets.h; sourceTree = ""; }; + 4121FCE32CC6AB3900095AD3 /* C64DebuggerPluginParallax.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = C64DebuggerPluginParallax.cpp; sourceTree = ""; }; + 4121FCE42CC6AB3900095AD3 /* C64DebuggerPluginParallax.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = C64DebuggerPluginParallax.h; sourceTree = ""; }; 412897C22B97D5B600495C47 /* CDataAdapterViceC64Cartridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataAdapterViceC64Cartridge.h; sourceTree = ""; }; 412897C32B97D5B600495C47 /* CDataAdapterViceC64DirectRam.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDataAdapterViceC64DirectRam.cpp; sourceTree = ""; }; 412897C42B97D5B600495C47 /* CDataAdapterViceC64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDataAdapterViceC64.cpp; sourceTree = ""; }; @@ -1374,6 +1394,10 @@ 4134B5E82763851A00830012 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; 4134D04B2B06CBB90032BE07 /* CViewDrive1541DiskData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewDrive1541DiskData.h; sourceTree = ""; }; 4134D04C2B06CBB90032BE07 /* CViewDrive1541DiskData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewDrive1541DiskData.cpp; sourceTree = ""; }; + 413601C62CE3D97200B562C0 /* CDebugBreakpointRasterLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugBreakpointRasterLine.h; sourceTree = ""; }; + 413601C72CE3D97200B562C0 /* CDebugBreakpointRasterLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugBreakpointRasterLine.cpp; sourceTree = ""; }; + 413601C92CE3E7BA00B562C0 /* CDebugBreakpointsRasterLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugBreakpointsRasterLine.h; sourceTree = ""; }; + 413601CA2CE3E7BA00B562C0 /* CDebugBreakpointsRasterLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugBreakpointsRasterLine.cpp; sourceTree = ""; }; 413687812AED4F8D00E40A23 /* CViewDebugEventsHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewDebugEventsHistory.cpp; sourceTree = ""; }; 413687822AED4F8D00E40A23 /* CViewDebugEventsHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewDebugEventsHistory.h; sourceTree = ""; }; 4137754C2C02245B006BF409 /* C64DebuggerPluginDNDK.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = C64DebuggerPluginDNDK.cpp; sourceTree = ""; }; @@ -1549,6 +1573,10 @@ 41B403AA25FF96B100C271F3 /* icon_tool_on_top_on_gfx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = icon_tool_on_top_on_gfx.h; sourceTree = ""; }; 41B403B426009F7C00C271F3 /* FontSweet16mono.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FontSweet16mono.h; sourceTree = ""; }; 41B403BB2600EF6B00C271F3 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; }; + 41B4D9A82C8A5D8200E62540 /* C64DebuggerPluginConvolution.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = C64DebuggerPluginConvolution.cpp; sourceTree = ""; }; + 41B4D9A92C8A5D8200E62540 /* C64DebuggerPluginConvolution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = C64DebuggerPluginConvolution.h; sourceTree = ""; }; + 41B4D9AF2C8A5E4D00E62540 /* C64DebuggerPluginGalaxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = C64DebuggerPluginGalaxy.cpp; sourceTree = ""; }; + 41B4D9B02C8A5E4D00E62540 /* C64DebuggerPluginGalaxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = C64DebuggerPluginGalaxy.h; sourceTree = ""; }; 41B5298823992DCB0084F0DB /* MTEngineSDL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MTEngineSDL.xcodeproj; path = ../../../MTEngineSDL/platform/MacOS/MTEngineSDL.xcodeproj; sourceTree = ""; }; 41B5299723992E0F0084F0DB /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; 41B5299923992E140084F0DB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; @@ -1608,8 +1636,6 @@ 41D4A5F523AA0F0F00A54EB2 /* CDebugInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugInterface.cpp; sourceTree = ""; }; 41D4A5F623AA0F0F00A54EB2 /* CDebugInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugInterface.h; sourceTree = ""; }; 41D4A5F723AA0F0F00A54EB2 /* DebuggerDefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerDefs.h; sourceTree = ""; }; - 41D4A5F823AA0F0F00A54EB2 /* INT_BinaryProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = INT_BinaryProtocol.cpp; sourceTree = ""; }; - 41D4A5F923AA0F0F00A54EB2 /* INT_BinaryProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INT_BinaryProtocol.h; sourceTree = ""; }; 41D4A5FC23AA0F0F00A54EB2 /* a-cartridge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "a-cartridge.c"; sourceTree = ""; }; 41D4A5FD23AA0F0F00A54EB2 /* a-cartridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "a-cartridge.h"; sourceTree = ""; }; 41D4A5FE23AA0F0F00A54EB2 /* a-crc32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "a-crc32.c"; sourceTree = ""; }; @@ -3514,16 +3540,14 @@ 41D4ADD723AA0F1100A54EB2 /* video-viewport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "video-viewport.c"; sourceTree = ""; }; 41D4ADDC23AA0F1100A54EB2 /* CViewAbout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewAbout.cpp; sourceTree = ""; }; 41D4ADDD23AA0F1100A54EB2 /* CViewAbout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewAbout.h; sourceTree = ""; }; - 41D4ADDE23AA0F1100A54EB2 /* CViewBreakpointsOLD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewBreakpointsOLD.cpp; sourceTree = ""; }; - 41D4ADDF23AA0F1100A54EB2 /* CViewBreakpointsOLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewBreakpointsOLD.h; sourceTree = ""; }; 41D4ADE023AA0F1100A54EB2 /* CViewC64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CViewC64.cpp; path = ../../src/Screens/CViewC64.cpp; sourceTree = ""; }; 41D4ADE123AA0F1100A54EB2 /* CViewC64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CViewC64.h; path = ../../src/Screens/CViewC64.h; sourceTree = ""; }; 41D4ADE423AA0F1100A54EB2 /* CViewColodore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewColodore.cpp; sourceTree = ""; }; 41D4ADE523AA0F1100A54EB2 /* CViewColodore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewColodore.h; sourceTree = ""; }; 41D4ADE823AA0F1100A54EB2 /* CViewKeyboardShortcuts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewKeyboardShortcuts.cpp; sourceTree = ""; }; 41D4ADE923AA0F1100A54EB2 /* CViewKeyboardShortcuts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewKeyboardShortcuts.h; sourceTree = ""; }; - 41D4ADEA23AA0F1100A54EB2 /* CViewMainMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewMainMenu.cpp; sourceTree = ""; }; - 41D4ADEB23AA0F1100A54EB2 /* CViewMainMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewMainMenu.h; sourceTree = ""; }; + 41D4ADEA23AA0F1100A54EB2 /* CMainMenuHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CMainMenuHelper.cpp; sourceTree = ""; }; + 41D4ADEB23AA0F1100A54EB2 /* CMainMenuHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CMainMenuHelper.h; sourceTree = ""; }; 41D4ADEC23AA0F1100A54EB2 /* CViewSettingsMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewSettingsMenu.cpp; sourceTree = ""; }; 41D4ADED23AA0F1100A54EB2 /* CViewSettingsMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewSettingsMenu.h; sourceTree = ""; }; 41D4ADEE23AA0F1100A54EB2 /* CViewSnapshots.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewSnapshots.cpp; sourceTree = ""; }; @@ -3803,6 +3827,20 @@ 41EE306425E93B2B0050257F /* NstHomebrew.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = NstHomebrew.hpp; sourceTree = ""; }; 41EE306825E93C450050257F /* NstBoardInlNsf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NstBoardInlNsf.cpp; sourceTree = ""; }; 41EE306925E93C450050257F /* NstBoardInlNsf.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = NstBoardInlNsf.hpp; sourceTree = ""; }; + 41F616B82CCAA838001253EE /* CDebuggerServerApiVice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebuggerServerApiVice.h; sourceTree = ""; }; + 41F616B92CCAA838001253EE /* CDebuggerServerApiVice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebuggerServerApiVice.cpp; sourceTree = ""; }; + 41F665AA2CB11E5900EFFFD5 /* CDebugBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugBreakpoint.h; sourceTree = ""; }; + 41F665AB2CB11E5900EFFFD5 /* CDebugBreakpointData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugBreakpointData.h; sourceTree = ""; }; + 41F665AC2CB11E5900EFFFD5 /* CDebugBreakpointData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugBreakpointData.cpp; sourceTree = ""; }; + 41F665AD2CB11E5900EFFFD5 /* CDebugBreakpointAddr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugBreakpointAddr.cpp; sourceTree = ""; }; + 41F665AE2CB11E5900EFFFD5 /* CDebugBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugBreakpoint.cpp; sourceTree = ""; }; + 41F665AF2CB11E5900EFFFD5 /* CDebugBreakpointAddr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugBreakpointAddr.h; sourceTree = ""; }; + 41F665B32CB1215300EFFFD5 /* CDebugBreakpointEventCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugBreakpointEventCallback.h; sourceTree = ""; }; + 41F665B42CB1215300EFFFD5 /* CDebugBreakpointEventCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugBreakpointEventCallback.cpp; sourceTree = ""; }; + 41F665B62CB1246000EFFFD5 /* CDebugBreakpointsData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugBreakpointsData.h; sourceTree = ""; }; + 41F665B72CB1246000EFFFD5 /* CDebugBreakpointsAddr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugBreakpointsAddr.cpp; sourceTree = ""; }; + 41F665B82CB1246000EFFFD5 /* CDebugBreakpointsAddr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebugBreakpointsAddr.h; sourceTree = ""; }; + 41F665B92CB1246000EFFFD5 /* CDebugBreakpointsData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebugBreakpointsData.cpp; sourceTree = ""; }; 41F8CF96294E0C6E000AECAE /* CViewC64AllGraphicsSpritesControl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewC64AllGraphicsSpritesControl.cpp; sourceTree = ""; }; 41F8CF98294E0C6F000AECAE /* CViewC64AllGraphicsSpritesControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewC64AllGraphicsSpritesControl.h; sourceTree = ""; }; 41F8CF9F294E0FC6000AECAE /* CViewC64AllGraphicsCharsetsControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewC64AllGraphicsCharsetsControl.h; sourceTree = ""; }; @@ -3811,6 +3849,10 @@ 41F8CFA2294E0FC6000AECAE /* CViewC64AllGraphicsCharsetsControl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewC64AllGraphicsCharsetsControl.cpp; sourceTree = ""; }; 41F8CFA3294E0FC6000AECAE /* CViewC64AllGraphicsScreensControl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewC64AllGraphicsScreensControl.cpp; sourceTree = ""; }; 41F8CFA4294E0FC7000AECAE /* CViewC64AllGraphicsBitmapsControl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewC64AllGraphicsBitmapsControl.cpp; sourceTree = ""; }; + 41FB3C092CFE0D0800870F9B /* CDebuggerServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebuggerServer.cpp; sourceTree = ""; }; + 41FB3C0A2CFE0D0800870F9B /* CDebuggerServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebuggerServer.h; sourceTree = ""; }; + 41FB3C0B2CFE0D0800870F9B /* CDebuggerServerApi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDebuggerServerApi.cpp; sourceTree = ""; }; + 41FB3C0C2CFE0D0800870F9B /* CDebuggerServerApi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDebuggerServerApi.h; sourceTree = ""; }; 41FD534D293CBAD40051A851 /* CViewC64ColorRamScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CViewC64ColorRamScreen.h; sourceTree = ""; }; 41FD534E293CBAD40051A851 /* CViewC64ColorRamScreen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewC64ColorRamScreen.cpp; sourceTree = ""; }; 41FD5355293CC3760051A851 /* CViewC64AllGraphicsSprites.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CViewC64AllGraphicsSprites.cpp; sourceTree = ""; }; @@ -3974,6 +4016,47 @@ path = TextEditor; sourceTree = ""; }; + 4121FCDC2CC6A1E600095AD3 /* Pipe */ = { + isa = PBXGroup; + children = ( + 4121FCDA2CC6A1E600095AD3 /* CPipeProtocolDebuggerCallback.cpp */, + 4121FCDB2CC6A1E600095AD3 /* CPipeProtocolDebuggerCallback.h */, + ); + path = Pipe; + sourceTree = ""; + }; + 4121FCDF2CC6A1E600095AD3 /* WebSockets */ = { + isa = PBXGroup; + children = ( + 4121FCDD2CC6A1E600095AD3 /* CDebuggerServerWebSockets.cpp */, + 4121FCDE2CC6A1E600095AD3 /* CDebuggerServerWebSockets.h */, + ); + path = WebSockets; + sourceTree = ""; + }; + 4121FCE02CC6A1E600095AD3 /* Remote */ = { + isa = PBXGroup; + children = ( + 41FB3C092CFE0D0800870F9B /* CDebuggerServer.cpp */, + 41FB3C0A2CFE0D0800870F9B /* CDebuggerServer.h */, + 41FB3C0B2CFE0D0800870F9B /* CDebuggerServerApi.cpp */, + 41FB3C0C2CFE0D0800870F9B /* CDebuggerServerApi.h */, + 4121FCDC2CC6A1E600095AD3 /* Pipe */, + 4121FCDF2CC6A1E600095AD3 /* WebSockets */, + ); + name = Remote; + path = ../../src/Remote; + sourceTree = ""; + }; + 4121FCE52CC6AB3900095AD3 /* Parallax */ = { + isa = PBXGroup; + children = ( + 4121FCE32CC6AB3900095AD3 /* C64DebuggerPluginParallax.cpp */, + 4121FCE42CC6AB3900095AD3 /* C64DebuggerPluginParallax.h */, + ); + path = Parallax; + sourceTree = ""; + }; 412897C12B97D5B600495C47 /* Adapters */ = { isa = PBXGroup; children = ( @@ -4039,6 +4122,22 @@ 4155B31C2681D8B600110009 /* Symbols */ = { isa = PBXGroup; children = ( + 41F665AE2CB11E5900EFFFD5 /* CDebugBreakpoint.cpp */, + 41F665AA2CB11E5900EFFFD5 /* CDebugBreakpoint.h */, + 41F665AD2CB11E5900EFFFD5 /* CDebugBreakpointAddr.cpp */, + 41F665AF2CB11E5900EFFFD5 /* CDebugBreakpointAddr.h */, + 41F665AC2CB11E5900EFFFD5 /* CDebugBreakpointData.cpp */, + 41F665AB2CB11E5900EFFFD5 /* CDebugBreakpointData.h */, + 413601C72CE3D97200B562C0 /* CDebugBreakpointRasterLine.cpp */, + 413601C62CE3D97200B562C0 /* CDebugBreakpointRasterLine.h */, + 41F665B42CB1215300EFFFD5 /* CDebugBreakpointEventCallback.cpp */, + 41F665B32CB1215300EFFFD5 /* CDebugBreakpointEventCallback.h */, + 41F665B72CB1246000EFFFD5 /* CDebugBreakpointsAddr.cpp */, + 41F665B82CB1246000EFFFD5 /* CDebugBreakpointsAddr.h */, + 41F665B92CB1246000EFFFD5 /* CDebugBreakpointsData.cpp */, + 41F665B62CB1246000EFFFD5 /* CDebugBreakpointsData.h */, + 413601CA2CE3E7BA00B562C0 /* CDebugBreakpointsRasterLine.cpp */, + 413601C92CE3E7BA00B562C0 /* CDebugBreakpointsRasterLine.h */, 41696A01268F2F1A00B1B0CA /* CDebugMemory.cpp */, 416969FF268F2F1A00B1B0CA /* CDebugMemory.h */, 41696A05268F2FD800B1B0CA /* CDebugMemoryCell.cpp */, @@ -4281,6 +4380,24 @@ name = src.MacOS; sourceTree = ""; }; + 41B4D9AA2C8A5D8200E62540 /* Convolution */ = { + isa = PBXGroup; + children = ( + 41B4D9A82C8A5D8200E62540 /* C64DebuggerPluginConvolution.cpp */, + 41B4D9A92C8A5D8200E62540 /* C64DebuggerPluginConvolution.h */, + ); + path = Convolution; + sourceTree = ""; + }; + 41B4D9B12C8A5E4D00E62540 /* Galaxy */ = { + isa = PBXGroup; + children = ( + 41B4D9AF2C8A5E4D00E62540 /* C64DebuggerPluginGalaxy.cpp */, + 41B4D9B02C8A5E4D00E62540 /* C64DebuggerPluginGalaxy.h */, + ); + path = Galaxy; + sourceTree = ""; + }; 41B5298923992DCB0084F0DB /* Products */ = { isa = PBXGroup; children = ( @@ -4299,6 +4416,7 @@ 41D4ADDB23AA0F1100A54EB2 /* Screens */, 41D4AE1323AA0F1100A54EB2 /* Tools */, 41D4AE9323AA0F1100A54EB2 /* Views */, + 4121FCE02CC6A1E600095AD3 /* Remote */, 41D4A5FA23AA0F0F00A54EB2 /* Emulators */, 418D82FF2733D2DF00CFFD8E /* RetroDebuggerAppInit.cpp */, 418D82FE2733D2DF00CFFD8E /* RetroDebuggerAppInit.h */, @@ -4336,6 +4454,9 @@ 41D4A5C823AA0F0F00A54EB2 /* Plugins */ = { isa = PBXGroup; children = ( + 4121FCE52CC6AB3900095AD3 /* Parallax */, + 41B4D9B12C8A5E4D00E62540 /* Galaxy */, + 41B4D9AA2C8A5D8200E62540 /* Convolution */, 4137754E2C02245B006BF409 /* DNDK */, 415002302BD68B9800FEFAF4 /* Slideshow */, 4183ACAE2A2B33340029BFAF /* Commando */, @@ -4422,8 +4543,6 @@ 417F88E1271AD2B3008F5E1B /* CDebuggerEmulatorPlugin.cpp */, 417F88E0271AD2B3008F5E1B /* CDebuggerEmulatorPlugin.h */, 41D4A5F723AA0F0F00A54EB2 /* DebuggerDefs.h */, - 41D4A5F823AA0F0F00A54EB2 /* INT_BinaryProtocol.cpp */, - 41D4A5F923AA0F0F00A54EB2 /* INT_BinaryProtocol.h */, ); name = DebugInterface; path = ../../src/DebugInterface; @@ -6773,6 +6892,8 @@ 41D4AD8723AA0F1100A54EB2 /* CAudioChannelVice.h */, 41864D76271ACDC600DE3020 /* CDebuggerApiVice.cpp */, 41864D77271ACDC600DE3020 /* CDebuggerApiVice.h */, + 41F616B92CCAA838001253EE /* CDebuggerServerApiVice.cpp */, + 41F616B82CCAA838001253EE /* CDebuggerServerApiVice.h */, 41864D75271ACDC600DE3020 /* CDebuggerEmulatorPluginVice.cpp */, 41864D78271ACDC600DE3020 /* CDebuggerEmulatorPluginVice.h */, ); @@ -6873,14 +6994,12 @@ 41D4ADF023AA0F1100A54EB2 /* VicEditor */, 41D4ADDC23AA0F1100A54EB2 /* CViewAbout.cpp */, 41D4ADDD23AA0F1100A54EB2 /* CViewAbout.h */, - 41D4ADDE23AA0F1100A54EB2 /* CViewBreakpointsOLD.cpp */, - 41D4ADDF23AA0F1100A54EB2 /* CViewBreakpointsOLD.h */, 41D4ADE423AA0F1100A54EB2 /* CViewColodore.cpp */, 41D4ADE523AA0F1100A54EB2 /* CViewColodore.h */, 41D4ADE823AA0F1100A54EB2 /* CViewKeyboardShortcuts.cpp */, 41D4ADE923AA0F1100A54EB2 /* CViewKeyboardShortcuts.h */, - 41D4ADEA23AA0F1100A54EB2 /* CViewMainMenu.cpp */, - 41D4ADEB23AA0F1100A54EB2 /* CViewMainMenu.h */, + 41D4ADEA23AA0F1100A54EB2 /* CMainMenuHelper.cpp */, + 41D4ADEB23AA0F1100A54EB2 /* CMainMenuHelper.h */, 41D4ADEC23AA0F1100A54EB2 /* CViewSettingsMenu.cpp */, 41D4ADED23AA0F1100A54EB2 /* CViewSettingsMenu.h */, 41D4ADEE23AA0F1100A54EB2 /* CViewSnapshots.cpp */, @@ -7346,11 +7465,13 @@ 417F88E7271AD2EF008F5E1B /* CDebuggerEmulatorPlugin.cpp in Sources */, 417F88E8271AD2EF008F5E1B /* CDebuggerEmulatorPlugin.h in Sources */, 4155B3282681DABA00110009 /* CDebugSymbolsSegment.cpp in Sources */, + 41FB3C0D2CFE0D0800870F9B /* CDebuggerServer.cpp in Sources */, 4155B3262681DAAB00110009 /* CDebugAsmSource.cpp in Sources */, 4155B3242681DA9A00110009 /* CDebugSymbols.cpp in Sources */, 41C84BEA23C6183A007C0889 /* archdep.c in Sources */, 41C84BEB23C6183A007C0889 /* mididrv.c in Sources */, 41C84BEC23C6183A007C0889 /* a-cartridge.c in Sources */, + 41F665BB2CB1246000EFFFD5 /* CDebugBreakpointsData.cpp in Sources */, 4110D894262BE2A400CF6F36 /* gorder.c in Sources */, 41C84BED23C6183A007C0889 /* a-crc32.c in Sources */, 41C84BEE23C6183A007C0889 /* a-log.c in Sources */, @@ -7427,6 +7548,7 @@ 41EE302C25E92A930050257F /* CViewNesPpuOam.cpp in Sources */, 41C84C2C23C6183A007C0889 /* xep80.c in Sources */, 41C84C2D23C6183A007C0889 /* xep80_fonts.c in Sources */, + 41FB3C0E2CFE0D0800870F9B /* CDebuggerServerApi.cpp in Sources */, 41C84C2E23C6183A007C0889 /* blockdev.c in Sources */, 41C84C2F23C6183A007C0889 /* catweaselmkiii.c in Sources */, 416FDA9C28D5FF41003DAB13 /* CVicEditorLayerC64Canvas.cpp in Sources */, @@ -7571,10 +7693,13 @@ 41C84CA923C6183B007C0889 /* digimax.c in Sources */, 41C84CAA23C6183B007C0889 /* dinamic.c in Sources */, 41C84CAB23C6183B007C0889 /* dqbb.c in Sources */, + 4121FCE12CC6A1E600095AD3 /* CPipeProtocolDebuggerCallback.cpp in Sources */, + 41F665B22CB11E5900EFFFD5 /* CDebugBreakpoint.cpp in Sources */, 41C84CAC23C6183B007C0889 /* ds12c887rtc.c in Sources */, 41C84CAD23C6183B007C0889 /* easycalc.c in Sources */, 41C84CAE23C6183B007C0889 /* easyflash.c in Sources */, 41C84CAF23C6183B007C0889 /* epyxfastload.c in Sources */, + 41F665BA2CB1246000EFFFD5 /* CDebugBreakpointsAddr.cpp in Sources */, 41C84CB023C6183B007C0889 /* ethernetcart.c in Sources */, 41C84CB123C6183B007C0889 /* exos.c in Sources */, 41C84CB223C6183B007C0889 /* expert.c in Sources */, @@ -7587,6 +7712,7 @@ 41C84CB923C6183B007C0889 /* funplay.c in Sources */, 41C84CBA23C6183B007C0889 /* gamekiller.c in Sources */, 41C84CBB23C6183B007C0889 /* georam.c in Sources */, + 41F665B52CB1215300EFFFD5 /* CDebugBreakpointEventCallback.cpp in Sources */, 41C84CBC23C6183B007C0889 /* gmod2.c in Sources */, 41C84CBD23C6183B007C0889 /* gs.c in Sources */, 41C84CBE23C6183B007C0889 /* ide64.c in Sources */, @@ -7596,6 +7722,7 @@ 41C84CC123C6183B007C0889 /* kingsoft.c in Sources */, 41C84CC223C6183B007C0889 /* mach5.c in Sources */, 41C84CC323C6183B007C0889 /* magicdesk.c in Sources */, + 41F665B02CB11E5900EFFFD5 /* CDebugBreakpointData.cpp in Sources */, 41C84CC423C6183B007C0889 /* magicformel.c in Sources */, 41C84CC523C6183B007C0889 /* magicvoice.c in Sources */, 41C84CC623C6183B007C0889 /* mikroass.c in Sources */, @@ -7808,6 +7935,7 @@ 41C84D7823C6183B007C0889 /* monitor.c in Sources */, 41C84D7923C6183B007C0889 /* monitor_network.c in Sources */, 41C84D7A23C6183B007C0889 /* parallel-trap.c in Sources */, + 4121FCE22CC6A1E600095AD3 /* CDebuggerServerWebSockets.cpp in Sources */, 41C84D7B23C6183B007C0889 /* parallel.c in Sources */, 41C84D7C23C6183B007C0889 /* platform.c in Sources */, 41C84D7D23C6183B007C0889 /* platform_amigaos3_runtime_os.c in Sources */, @@ -7836,6 +7964,7 @@ 41C84D9123C6183B007C0889 /* output-text.c in Sources */, 41C84D9223C6183B007C0889 /* printer-serial.c in Sources */, 41C84D9323C6183B007C0889 /* printer-userport.c in Sources */, + 4121FCE62CC6AB3900095AD3 /* C64DebuggerPluginParallax.cpp in Sources */, 41C84D9423C6183B007C0889 /* printer.c in Sources */, 41C84D9523C6183B007C0889 /* raster-cache.c in Sources */, 41C84D9623C6183B007C0889 /* raster-canvas.c in Sources */, @@ -7864,6 +7993,7 @@ 41C84DAB23C6183B007C0889 /* cmdline.c in Sources */, 41C84DAC23C6183B007C0889 /* color.c in Sources */, 41EE302925E92A930050257F /* CViewNesPpuPatterns.cpp in Sources */, + 41B4D9B22C8A5E4D00E62540 /* C64DebuggerPluginGalaxy.cpp in Sources */, 41C84DAD23C6183B007C0889 /* datasette.c in Sources */, 41C84DAE23C6183B007C0889 /* debug.c in Sources */, 41C84DAF23C6183B007C0889 /* dma.c in Sources */, @@ -7884,6 +8014,7 @@ 41C84DBD23C6183B007C0889 /* lib.c in Sources */, 41C84DBE23C6183B007C0889 /* libm_math.c in Sources */, 41C84DBF23C6183B007C0889 /* log.c in Sources */, + 413601CB2CE3E7BA00B562C0 /* CDebugBreakpointsRasterLine.cpp in Sources */, 41C84DC023C6183B007C0889 /* machine-bus.c in Sources */, 41C84DC123C6183B007C0889 /* machine.c in Sources */, 41E9502226442911008A842C /* C64VicDisplayCanvasHiresBitmap.cpp in Sources */, @@ -8017,6 +8148,7 @@ 41C84E2F23C6183B007C0889 /* render1x2crt.c in Sources */, 41C84E3023C6183B007C0889 /* render2x2.c in Sources */, 41C84E3123C6183B007C0889 /* render2x2crt.c in Sources */, + 41B4D9AB2C8A5D8200E62540 /* C64DebuggerPluginConvolution.cpp in Sources */, 416C256A28D6A3DB002BDC0D /* CVicEditorBrush.cpp in Sources */, 41C84E3223C6183B007C0889 /* render2x2ntsc.c in Sources */, 41C84E3323C6183B007C0889 /* render2x2pal.c in Sources */, @@ -8066,7 +8198,6 @@ 41C84A3023C61830007C0889 /* C64DebuggerPluginDummy.cpp in Sources */, 41C84A3623C61830007C0889 /* CDebugBreakpoints.cpp in Sources */, 41C84A3823C61830007C0889 /* CDebugInterface.cpp in Sources */, - 41C84A3923C61830007C0889 /* INT_BinaryProtocol.cpp in Sources */, 41C84A3A23C61830007C0889 /* CDataAdapterAtari.cpp in Sources */, 41EE303F25E92AE10050257F /* CDataAdapterNesRam.cpp in Sources */, 41C84A3B23C61830007C0889 /* CDebugInterfaceAtari.cpp in Sources */, @@ -8107,6 +8238,7 @@ 41C84A5623C61830007C0889 /* NstBoardAxRom.cpp in Sources */, 41C84A5723C61830007C0889 /* NstBoardBandai24c0x.cpp in Sources */, 41C84A5823C61830007C0889 /* NstBoardBandaiAerobicsStudio.cpp in Sources */, + 41F616BA2CCAA839001253EE /* CDebuggerServerApiVice.cpp in Sources */, 41C84A5923C61830007C0889 /* NstBoardBandaiDatach.cpp in Sources */, 41C84A5A23C61830007C0889 /* NstBoardBandaiKaraokeStudio.cpp in Sources */, 41C84A5B23C61830007C0889 /* NstBoardBandaiLz93d50.cpp in Sources */, @@ -8212,6 +8344,7 @@ 41C84AAD23C61830007C0889 /* NstBoardHenggedianzi.cpp in Sources */, 41C84AAE23C61830007C0889 /* NstBoardHes.cpp in Sources */, 41C84AAF23C61830007C0889 /* NstBoardHosenkan.cpp in Sources */, + 41F665B12CB11E5900EFFFD5 /* CDebugBreakpointAddr.cpp in Sources */, 41C84AB023C61830007C0889 /* NstBoardIremG101.cpp in Sources */, 41C84AB123C61830007C0889 /* NstBoardIremH3001.cpp in Sources */, 41C84AB223C61830007C0889 /* NstBoardIremHolyDiver.cpp in Sources */, @@ -8443,10 +8576,9 @@ 41C84B7C23C61830007C0889 /* ViceLogWrapper.cpp in Sources */, 41C84B7D23C61830007C0889 /* ViceWrapper.cpp in Sources */, 41C84B7F23C61830007C0889 /* CViewAbout.cpp in Sources */, - 41C84B8023C61830007C0889 /* CViewBreakpointsOLD.cpp in Sources */, 41C84B8223C61830007C0889 /* CViewColodore.cpp in Sources */, 41C84B8423C61830007C0889 /* CViewKeyboardShortcuts.cpp in Sources */, - 41C84B8523C61830007C0889 /* CViewMainMenu.cpp in Sources */, + 41C84B8523C61830007C0889 /* CMainMenuHelper.cpp in Sources */, 416FDA9B28D5FF41003DAB13 /* CVicEditorLayerVirtualSprites.cpp in Sources */, 41C84B8623C61830007C0889 /* CViewSettingsMenu.cpp in Sources */, 41C84B8723C61830007C0889 /* CViewSnapshots.cpp in Sources */, @@ -8521,6 +8653,7 @@ 41C84BD423C61830007C0889 /* CJukeboxPlaylist.cpp in Sources */, 41C84BD523C61830007C0889 /* CViewJukeboxPlaylist.cpp in Sources */, 4110D8A8262BE2A400CF6F36 /* gsid.cpp in Sources */, + 413601C82CE3D97200B562C0 /* CDebugBreakpointRasterLine.cpp in Sources */, 4110D862262BE2A400CF6F36 /* gplay.c in Sources */, 41732EC22919654A00F212AC /* CViewDrive1541Led.cpp in Sources */, 41C84BE623C61830007C0889 /* CViewC64.cpp in Sources */, @@ -8633,12 +8766,12 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon C64"; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CODE_SIGN_ENTITLEMENTS = "Retro Debugger.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_INJECT_BASE_ENTITLEMENTS = YES; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0.64.68; + CURRENT_PROJECT_VERSION = 0.64.69; DEVELOPMENT_TEAM = APV7Y7Q9JY; ENABLE_HARDENED_RUNTIME = YES; GCC_C_LANGUAGE_STANDARD = c17; @@ -8661,8 +8794,8 @@ "$(PROJECT_DIR)/lib", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 0.64.68; - ONLY_ACTIVE_ARCH = YES; + MARKETING_VERSION = 0.64.69; + ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "-Wno-implicit-function-declaration"; OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_CPLUSPLUSFLAGS = ( @@ -8679,12 +8812,12 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon C64"; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CODE_SIGN_ENTITLEMENTS = "Retro Debugger.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_INJECT_BASE_ENTITLEMENTS = YES; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0.64.68; + CURRENT_PROJECT_VERSION = 0.64.69; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = APV7Y7Q9JY; ENABLE_HARDENED_RUNTIME = YES; @@ -8706,8 +8839,8 @@ "$(PROJECT_DIR)/lib", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 0.64.68; - ONLY_ACTIVE_ARCH = YES; + MARKETING_VERSION = 0.64.69; + ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "-Wno-implicit-function-declaration"; OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_CPLUSPLUSFLAGS = ( diff --git a/platform/MacOS/c64d.xcodeproj/project.xcworkspace/xcuserdata/mars.xcuserdatad/UserInterfaceState.xcuserstate b/platform/MacOS/c64d.xcodeproj/project.xcworkspace/xcuserdata/mars.xcuserdatad/UserInterfaceState.xcuserstate index 271612b..283113e 100644 Binary files a/platform/MacOS/c64d.xcodeproj/project.xcworkspace/xcuserdata/mars.xcuserdatad/UserInterfaceState.xcuserstate and b/platform/MacOS/c64d.xcodeproj/project.xcworkspace/xcuserdata/mars.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/platform/Windows/c64d.sln b/platform/Windows/c64d.sln index dd9cba7..118433d 100644 --- a/platform/Windows/c64d.sln +++ b/platform/Windows/c64d.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29519.87 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 d17.12 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c64d", "c64d\c64d.vcxproj", "{7FBDFE33-F186-4E73-8908-49E9AA007B5D}" EndProject @@ -9,24 +9,34 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MTEngineSDL", "..\..\..\MTE EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Debug|ARM64.Build.0 = Debug|ARM64 {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Debug|x64.ActiveCfg = Debug|x64 {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Debug|x64.Build.0 = Debug|x64 {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Debug|x86.ActiveCfg = Debug|Win32 {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Debug|x86.Build.0 = Debug|Win32 + {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Release|ARM64.ActiveCfg = Release|ARM64 + {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Release|ARM64.Build.0 = Release|ARM64 {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Release|x64.ActiveCfg = Release|x64 {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Release|x64.Build.0 = Release|x64 {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Release|x86.ActiveCfg = Release|Win32 {7FBDFE33-F186-4E73-8908-49E9AA007B5D}.Release|x86.Build.0 = Release|Win32 + {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Debug|ARM64.Build.0 = Debug|ARM64 {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Debug|x64.ActiveCfg = Debug|x64 {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Debug|x64.Build.0 = Debug|x64 {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Debug|x86.ActiveCfg = Debug|Win32 {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Debug|x86.Build.0 = Debug|Win32 + {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Release|ARM64.ActiveCfg = Release|ARM64 + {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Release|ARM64.Build.0 = Release|ARM64 {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Release|x64.ActiveCfg = Release|x64 {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Release|x64.Build.0 = Release|x64 {E93D3B41-0438-4721-ABFE-83F1F37490CF}.Release|x86.ActiveCfg = Release|Win32 diff --git a/platform/Windows/c64d/c64d.vcxproj b/platform/Windows/c64d/c64d.vcxproj index d611d39..029b178 100644 --- a/platform/Windows/c64d/c64d.vcxproj +++ b/platform/Windows/c64d/c64d.vcxproj @@ -2,10 +2,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -45,6 +53,12 @@ v143 MultiByte + + Application + true + v143 + MultiByte + Application false @@ -52,6 +66,13 @@ true MultiByte + + Application + false + v143 + true + MultiByte + @@ -66,9 +87,15 @@ + + + + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ @@ -85,27 +112,38 @@ $(MTEngineSDLDir)platform\Windows\bin\$(Platform)\$(Configuration);$(MTEngineSDLDir)platform\Windows\libs\$(Platform)\$(Configuration);$(LibraryPath) $(MTEngineSDLDir)platform\Windows\include;$(IncludePath) + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(MTEngineSDLDir)platform\Windows\bin\$(Platform)\$(Configuration);$(MTEngineSDLDir)platform\Windows\libs\$(Platform)\$(Configuration);$(LibraryPath) + $(MTEngineSDLDir)platform\Windows\include;$(IncludePath) + $(SolutionDir)bin\$(Platform)\$(Configuration)\ $(MTEngineSDLDir)platform\Windows\bin\$(Platform)\$(Configuration);$(MTEngineSDLDir)platform\Windows\libs\$(Platform)\$(Configuration);$(LibraryPath) $(MTEngineSDLDir)platform\Windows\include;$(IncludePath) true + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(MTEngineSDLDir)platform\Windows\bin\$(Platform)\$(Configuration);$(MTEngineSDLDir)platform\Windows\libs\$(Platform)\$(Configuration);$(LibraryPath) + $(MTEngineSDLDir)platform\Windows\include;$(IncludePath) + true + Level3 Disabled false false - _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32 - $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) + _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;LIBUS_NO_SSL; + $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Remote\WebSockets;$(ProjectDir)..\..\..\src\Remote\Pipe;$(ProjectDir)..\..\..\src\Remote;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\nlohmann;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\uWebSockets;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) MultiThreadedDebug false - stdcpp17 + stdcpp20 Windows - MTEngineSDL.lib;SDL2.lib;SDL2main.lib;freetype.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;ws2_32.lib;%(AdditionalDependencies) + MTEngineSDL.lib;SDL2.lib;SDL2main.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;userenv.lib;psapi.lib;uSockets.lib;libuv.lib;msvcrt.lib;dbghelp.lib;%(AdditionalDependencies) @@ -114,15 +152,33 @@ Disabled false false - _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32 - $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) + _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;LIBUS_NO_SSL; + $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Remote\WebSockets;$(ProjectDir)..\..\..\src\Remote\Pipe;$(ProjectDir)..\..\..\src\Remote;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\nlohmann;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\uWebSockets;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) MultiThreadedDebug false - stdcpp17 + stdcpp20 Windows - MTEngineSDL.lib;SDL2.lib;SDL2main.lib;freetype.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;ws2_32.lib;%(AdditionalDependencies) + MTEngineSDL.lib;SDL2.lib;SDL2main.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;userenv.lib;psapi.lib;uSockets.lib;libuv.lib;msvcrt.lib;dbghelp.lib;%(AdditionalDependencies) + + + + + Level3 + Disabled + false + false + _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;LIBUS_NO_SSL;_ARM64_ + $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Remote\WebSockets;$(ProjectDir)..\..\..\src\Remote\Pipe;$(ProjectDir)..\..\..\src\Remote;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\nlohmann;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\uWebSockets;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) + MultiThreadedDebug + false + stdcpp20 + Default + + + Windows + MTEngineSDL.lib;SDL2.lib;SDL2main.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;userenv.lib;psapi.lib;uSockets.lib;libuv.lib;msvcrt.lib;dbghelp.lib;%(AdditionalDependencies) @@ -133,17 +189,17 @@ true false false - _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32 - $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) + _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;LIBUS_NO_SSL; + $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Remote\WebSockets;$(ProjectDir)..\..\..\src\Remote\Pipe;$(ProjectDir)..\..\..\src\Remote;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\nlohmann;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\uWebSockets;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) MultiThreaded false - stdcpp17 + stdcpp20 Windows true true - MTEngineSDL.lib;SDL2.lib;SDL2main.lib;freetype.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;ws2_32.lib;%(AdditionalDependencies) + MTEngineSDL.lib;SDL2.lib;SDL2main.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;userenv.lib;psapi.lib;uSockets.lib;libuv.lib;msvcrt.lib;dbghelp.lib;%(AdditionalDependencies) @@ -154,17 +210,40 @@ true false false - _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32 - $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) + _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;LIBUS_NO_SSL; + $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Remote\WebSockets;$(ProjectDir)..\..\..\src\Remote\Pipe;$(ProjectDir)..\..\..\src\Remote;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\nlohmann;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\uWebSockets;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) + MultiThreaded + false + stdcpp20 + + + Windows + true + true + MTEngineSDL.lib;SDL2.lib;SDL2main.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;userenv.lib;psapi.lib;uSockets.lib;libuv.lib;msvcrt.lib;dbghelp.lib;%(AdditionalDependencies) + UseLinkTimeCodeGeneration + + + + + Level3 + MaxSpeed + true + true + false + false + _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;LIBUS_NO_SSL;_ARM64_ + $(ProjectDir)..\..\..\src\Plugins\Commando;$(ProjectDir)..\..\..\src\Plugins\ShowPic;$(ProjectDir)..\..\..\src\Plugins\RasterBars;$(ProjectDir)..\..\..\src\Plugins\DNDK;$(ProjectDir)..\..\..\src\Plugins\Parallax;$(ProjectDir)..\..\..\src\Plugins\CrtMaker;$(ProjectDir)..\..\..\src\Plugins\Slideshow;$(ProjectDir)..\..\..\src\Plugins\Mapper;$(ProjectDir)..\..\..\src\Plugins\SidWizard;$(ProjectDir)..\..\..\platform\Windows\src.Windows\hardsid;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch\wpcap\net;$(ProjectDir)..\..\..\platform\Windows\src.Windows\arch;$(ProjectDir)..\..\..\platform\Windows\src.Windows;$(ProjectDir)..\..\..\src;$(ProjectDir)..\..\..\src\Plugins;$(ProjectDir)..\..\..\src\DebugInterface;$(ProjectDir)..\..\..\src\DebugInterface\MenuItems;$(ProjectDir)..\..\..\src\DebugInterface\C64;$(ProjectDir)..\..\..\src\DebugInterface\Symbols;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\asm;$(ProjectDir)..\..\..\src\Plugins\GoatTracker\gt2\bme;$(ProjectDir)..\..\..\src\Plugins\GoatTracker;$(ProjectDir)..\..\..\src\Embedded;$(ProjectDir)..\..\..\src\Emulators;$(ProjectDir)..\..\..\src\Emulators\atari800;$(ProjectDir)..\..\..\src\Emulators\atari800\atari_ntsc;$(ProjectDir)..\..\..\src\Emulators\atari800\codecs;$(ProjectDir)..\..\..\src\Emulators\atari800\roms;$(ProjectDir)..\..\..\src\Emulators\atari800\AtariInterface;$(ProjectDir)..\..\..\src\Emulators\atari800\sdl;$(ProjectDir)..\..\..\src\Emulators\nestopiaue;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\common;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\vssystem;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\input;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\board;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core\api;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\core;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\nes_ntsc\tests;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\NestopiaInterface\DataAdapters;$(ProjectDir)..\..\..\src\Emulators\nestopiaue\sdl;$(ProjectDir)..\..\..\src\Emulators\vice;$(ProjectDir)..\..\..\src\Emulators\vice\arch;$(ProjectDir)..\..\..\src\Emulators\vice\c64;$(ProjectDir)..\..\..\src\Emulators\vice\c64\cart;$(ProjectDir)..\..\..\src\Emulators\vice\core;$(ProjectDir)..\..\..\src\Emulators\vice\diag;$(ProjectDir)..\..\..\src\Emulators\vice\diskimage;$(ProjectDir)..\..\..\src\Emulators\vice\drive;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iec\c64exp;$(ProjectDir)..\..\..\src\Emulators\vice\drive\iecieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\ieee;$(ProjectDir)..\..\..\src\Emulators\vice\drive\tcbm;$(ProjectDir)..\..\..\src\Emulators\vice\fileio;$(ProjectDir)..\..\..\src\Emulators\vice\fsdevice;$(ProjectDir)..\..\..\src\Emulators\vice\gfxoutputdrv;$(ProjectDir)..\..\..\src\Emulators\vice\iecbus;$(ProjectDir)..\..\..\src\Emulators\vice\imagecontents;$(ProjectDir)..\..\..\src\Emulators\vice\joyport;$(ProjectDir)..\..\..\src\Emulators\vice\lib;$(ProjectDir)..\..\..\src\Emulators\vice\lib\p64;$(ProjectDir)..\..\..\src\Emulators\vice\monitor;$(ProjectDir)..\..\..\src\Emulators\vice\parallel;$(ProjectDir)..\..\..\src\Emulators\vice\platform;$(ProjectDir)..\..\..\src\Emulators\vice\printerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\raster;$(ProjectDir)..\..\..\src\Emulators\vice\resid;$(ProjectDir)..\..\..\src\Emulators\vice\resid-fp;$(ProjectDir)..\..\..\src\Emulators\vice\root;$(ProjectDir)..\..\..\src\Emulators\vice\rs232drv;$(ProjectDir)..\..\..\src\Emulators\vice\rtc;$(ProjectDir)..\..\..\src\Emulators\vice\samplerdrv;$(ProjectDir)..\..\..\src\Emulators\vice\serial;$(ProjectDir)..\..\..\src\Emulators\vice\sid;$(ProjectDir)..\..\..\src\Emulators\vice\sounddrv;$(ProjectDir)..\..\..\src\Emulators\vice\tape;$(ProjectDir)..\..\..\src\Emulators\vice\tapeport;$(ProjectDir)..\..\..\src\Emulators\vice\userport;$(ProjectDir)..\..\..\src\Emulators\vice\vdrive;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface;$(ProjectDir)..\..\..\src\Emulators\vice\ViceInterface\Adapters;$(ProjectDir)..\..\..\src\Emulators\vice\viciisc;$(ProjectDir)..\..\..\src\Emulators\vice\video;$(ProjectDir)..\..\..\src\Remote\WebSockets;$(ProjectDir)..\..\..\src\Remote\Pipe;$(ProjectDir)..\..\..\src\Remote;$(ProjectDir)..\..\..\src\Screens;$(ProjectDir)..\..\..\src\Screens\VicEditor;$(ProjectDir)..\..\..\src\Tools;$(ProjectDir)..\..\..\src\Tools\64tass;$(ProjectDir)..\..\..\src\Tools\asap;$(ProjectDir)..\..\..\src\Tools\exomizer;$(ProjectDir)..\..\..\src\Tools\libpsid64;$(ProjectDir)..\..\..\src\Tools\sidplay;$(ProjectDir)..\..\..\src\Tools\sidplay\sidtune;$(ProjectDir)..\..\..\src\Tools\sidplay\utils;$(ProjectDir)..\..\..\src\Tools\stilview;$(ProjectDir)..\..\..\src\Tools\TextEditor;$(ProjectDir)..\..\..\src\Views;$(ProjectDir)..\..\..\src\Views\Atari800;$(ProjectDir)..\..\..\src\Views\C64;$(ProjectDir)..\..\..\src\Views\C64\AllGraphics;$(ProjectDir)..\..\..\src\Views\C64\VicDisplay;$(ProjectDir)..\..\..\src\Views\C64\VicEditor;$(ProjectDir)..\..\..\src\Views\C64\VicEditor\Layers;$(ProjectDir)..\..\..\src\Views\Nes;$(ProjectDir)..\..\..\src\Views\JukeboxPlaylist;$(MTEngineSDLDir)src;$(MTEngineSDLDir)src\Embedded;$(MTEngineSDLDir)src\Engine;$(MTEngineSDLDir)src\Engine\Audio;$(MTEngineSDLDir)src\Engine\Audio\MIDI;$(MTEngineSDLDir)src\Engine\Audio\WAV;$(MTEngineSDLDir)src\Engine\Core;$(MTEngineSDLDir)src\Engine\Core\GamePads;$(MTEngineSDLDir)src\Engine\Core\Render;$(MTEngineSDLDir)src\Engine\Core\Net;$(MTEngineSDLDir)src\Engine\Core\Pool;$(MTEngineSDLDir)src\Engine\Funct;$(MTEngineSDLDir)src\Engine\Funct\DataTable;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\resampler;$(MTEngineSDLDir)src\Engine\Funct\ImageProcessing\stb_image;$(MTEngineSDLDir)src\Engine\GUI;$(MTEngineSDLDir)src\Engine\GUI\AudioMixer;$(MTEngineSDLDir)src\Engine\GUI\Controls;$(MTEngineSDLDir)src\Engine\GUI\Waveform;$(MTEngineSDLDir)src\Engine\GUI\Layout;$(MTEngineSDLDir)src\Engine\GUI\Helpers;$(MTEngineSDLDir)src\Engine\GUI\Helpers\LoadingScreen;$(MTEngineSDLDir)src\Engine\GUI\Helpers\ResourceManager;$(MTEngineSDLDir)src\Engine\Libs;$(MTEngineSDLDir)src\Engine\Libs\hjson;$(MTEngineSDLDir)src\Engine\Libs\stb;$(MTEngineSDLDir)src\Engine\Libs\imgui;$(MTEngineSDLDir)src\Engine\Libs\implot;$(MTEngineSDLDir)src\Engine\Libs\imguiext;$(MTEngineSDLDir)src\Engine\Libs\imgui-notify;$(MTEngineSDLDir)src\Engine\Libs\jpeg;$(MTEngineSDLDir)src\Engine\Libs\jpeg\jpeg-9a;$(MTEngineSDLDir)src\Engine\Libs\nlohmann;$(MTEngineSDLDir)src\Engine\Libs\libjson;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\libbase64++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Dependencies\mempool++;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source;$(MTEngineSDLDir)src\Engine\Libs\libjson\_internal\Source\JSONDefs;$(MTEngineSDLDir)src\Engine\Libs\libpng;$(MTEngineSDLDir)src\Engine\Libs\lodepng;$(MTEngineSDLDir)src\Engine\Libs\md5;$(MTEngineSDLDir)src\Engine\Libs\minizip;$(MTEngineSDLDir)src\Engine\Libs\mtrand;$(MTEngineSDLDir)src\Engine\Libs\nfd;$(MTEngineSDLDir)src\Engine\Libs\pugixml;$(MTEngineSDLDir)src\Engine\Libs\rtmidi;$(MTEngineSDLDir)src\Engine\Libs\tremor;$(MTEngineSDLDir)src\Engine\Libs\tremor\Ogg;$(MTEngineSDLDir)src\Engine\Libs\utf8;$(MTEngineSDLDir)src\Engine\Libs\uWebSockets;$(MTEngineSDLDir)src\Engine\Libs\zlib;$(MTEngineSDLDir)platform\Windows\src.Windows;(AdditionalIncludeDirectories) MultiThreaded false - stdcpp17 + stdcpp20 + Default Windows true true - MTEngineSDL.lib;SDL2.lib;SDL2main.lib;freetype.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;ws2_32.lib;%(AdditionalDependencies) + MTEngineSDL.lib;SDL2.lib;SDL2main.lib;version.lib;imm32.lib;setupapi.lib;winmm.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;userenv.lib;psapi.lib;uSockets.lib;libuv.lib;msvcrt.lib;dbghelp.lib;%(AdditionalDependencies) UseLinkTimeCodeGeneration @@ -184,11 +263,18 @@ - + + + + + + + + @@ -1107,6 +1193,7 @@ + @@ -1194,13 +1281,17 @@ + + + + + - @@ -1388,11 +1479,18 @@ - + + + + + + + + @@ -2454,6 +2552,7 @@ + @@ -2540,13 +2639,17 @@ + + + + + - diff --git a/platform/Windows/c64d/c64d.vcxproj.filters b/platform/Windows/c64d/c64d.vcxproj.filters index 67c5358..cb3f42e 100644 --- a/platform/Windows/c64d/c64d.vcxproj.filters +++ b/platform/Windows/c64d/c64d.vcxproj.filters @@ -252,6 +252,15 @@ {c04896c9-3f9c-4714-a338-b5fbbac3244a} + + {d1406b71-a32f-4393-9871-aafa15f92907} + + + {4eb66e94-21dc-44bf-b574-40ca7f3211e6} + + + {a4052fb4-3f92-4cde-b656-d483767e28b8} + @@ -2033,9 +2042,6 @@ Source Files\src\Screens - - Source Files\src\Screens - Source Files\src\Screens @@ -3506,39 +3512,9 @@ Source Files\src\Screens - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\Symbols - Source Files\src\Views - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - Source Files\src\Emulators\vice\ViceInterface @@ -3623,18 +3599,6 @@ Source Files\src\Embedded - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\C64 - - - Source Files\src\DebugInterface\C64 - Source Files\src\Views\C64 @@ -3764,9 +3728,6 @@ Source Files\src\Views - - Source Files\src\DebugInterface - Source Files\src\Emulators\vice\diskimage @@ -3785,18 +3746,6 @@ Source Files\src\Views\C64 - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\C64 - - - Source Files\src\DebugInterface\C64 - Source Files\src\Emulators\vice\ViceInterface\Adapters @@ -3833,6 +3782,24 @@ Source Files\src\Emulators\vice\ViceInterface\Adapters + + Source Files\src\Plugins\Slideshow + + + Source Files\src\Views\C64 + + + Source Files\src\Views\C64 + + + Source Files\src\DebugInterface\C64 + + + Source Files\src\DebugInterface\C64 + + + Source Files\src\DebugInterface\C64 + Source Files\src\DebugInterface\C64 @@ -3845,14 +3812,92 @@ Source Files\src\DebugInterface\C64 - - Source Files\src\Plugins\Slideshow + + Source Files\src\DebugInterface\C64 - - Source Files\src\Views\C64 + + Source Files\src\DebugInterface\Symbols - - Source Files\src\Views\C64 + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\Remote + + + Source Files\src\Remote + + + Source Files\src\Remote\WebSockets + + + Source Files\src\Remote\Pipe + + + Source Files\src\Screens + + + Source Files\src\Emulators\vice\ViceInterface @@ -5875,9 +5920,6 @@ Source Files\src\Screens - - Source Files\src\Screens - Source Files\src\Screens @@ -7552,42 +7594,9 @@ Source Files\src\Screens - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\Symbols - Source Files\src\Views - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - - - Source Files\src\DebugInterface - Source Files\src\Emulators\vice\ViceInterface @@ -7675,9 +7684,6 @@ Source Files\src\Embedded - - Source Files\src\DebugInterface\Symbols - Source Files\src\Embedded @@ -7696,15 +7702,6 @@ Source Files\src\Embedded - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\C64 - - - Source Files\src\DebugInterface\C64 - Source Files\src\Views\C64 @@ -7861,9 +7858,6 @@ Source Files\src\Views - - Source Files\src\DebugInterface - Source Files\src\Views @@ -7879,18 +7873,6 @@ Source Files\src\Views\C64 - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\Symbols - - - Source Files\src\DebugInterface\C64 - - - Source Files\src\DebugInterface\C64 - Source Files\src\Embedded @@ -7930,6 +7912,27 @@ Source Files\src\Emulators\vice\ViceInterface\Adapters + + Source Files\src\Plugins\Slideshow + + + Source Files\src\Views\C64 + + + Source Files\src\Views\C64 + + + Source Files\src\Views\C64\AllGraphics + + + Source Files\src\DebugInterface\C64 + + + Source Files\src\DebugInterface\C64 + + + Source Files\src\DebugInterface\C64 + Source Files\src\DebugInterface\C64 @@ -7942,17 +7945,95 @@ Source Files\src\DebugInterface\C64 - - Source Files\src\Plugins\Slideshow + + Source Files\src\DebugInterface\C64 - - Source Files\src\Views\C64 + + Source Files\src\DebugInterface\Symbols - - Source Files\src\Views\C64 + + Source Files\src\DebugInterface\Symbols - - Source Files\src\Views\C64\AllGraphics + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface\Symbols + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\DebugInterface + + + Source Files\src\Remote + + + Source Files\src\Remote + + + Source Files\src\Remote\WebSockets + + + Source Files\src\Remote\Pipe + + + Source Files\src\Screens + + + Source Files\src\Emulators\vice\ViceInterface diff --git a/platform/Windows/c64d/c64d.vcxproj.user b/platform/Windows/c64d/c64d.vcxproj.user index 1310204..4171d32 100644 --- a/platform/Windows/c64d/c64d.vcxproj.user +++ b/platform/Windows/c64d/c64d.vcxproj.user @@ -9,6 +9,12 @@ ..\_RUNTIME_ WindowsLocalDebugger + + + + ..\_RUNTIME_ + WindowsLocalDebugger + ..\_RUNTIME_ WindowsLocalDebugger @@ -23,4 +29,10 @@ + + ..\_RUNTIME_ + WindowsLocalDebugger + + + \ No newline at end of file diff --git a/src/C64D_Version.h b/src/C64D_Version.h index 26dcb1d..7f3f815 100644 --- a/src/C64D_Version.h +++ b/src/C64D_Version.h @@ -1,6 +1,6 @@ #ifndef _C64D_VERSION_H_ -#define RETRODEBUGGER_VERSION_STRING "0.64.68" +#define RETRODEBUGGER_VERSION_STRING "0.64.70" #endif diff --git a/src/DebugInterface/C64/CDataAdapterDrive1541Minimal.cpp b/src/DebugInterface/C64/CDataAdapterDrive1541Minimal.cpp index d3d03c3..7f8dd5e 100644 --- a/src/DebugInterface/C64/CDataAdapterDrive1541Minimal.cpp +++ b/src/DebugInterface/C64/CDataAdapterDrive1541Minimal.cpp @@ -157,7 +157,7 @@ CDataAdapterDrive1541Minimal::CDataAdapterDrive1541Minimal(CDebugSymbols *debugS int CDataAdapterDrive1541Minimal::AdapterGetDataLength() { - return DRIVE1541_SHORTENED_MEMORY_ADAPTER_LENGTH; + return DRIVE1541_MINIMAL_MEMORY_ADAPTER_LENGTH; } void CDataAdapterDrive1541Minimal::AdapterReadByte(int pointer, uint8 *value, bool *isAvailable) diff --git a/src/DebugInterface/C64/CDataAdapterDrive1541Minimal.h b/src/DebugInterface/C64/CDataAdapterDrive1541Minimal.h index 186917d..a9f9728 100644 --- a/src/DebugInterface/C64/CDataAdapterDrive1541Minimal.h +++ b/src/DebugInterface/C64/CDataAdapterDrive1541Minimal.h @@ -1,5 +1,5 @@ -#ifndef CDataAdapterDrive1541ShortenedMemory_h -#define CDataAdapterDrive1541ShortenedMemory_h +#ifndef CDataAdapterDrive1541Minimal_h +#define CDataAdapterDrive1541Minimal_h #include "CDebugDataAdapter.h" @@ -11,7 +11,7 @@ class CDebugInterfaceC64; // imageHeight=1024 imageWidth=64 // last cell is vx=16 vy=33 addr=1c10 // 64 per row * 33 = 2112 + 16 = 2128 -#define DRIVE1541_SHORTENED_MEMORY_ADAPTER_LENGTH 2128 +#define DRIVE1541_MINIMAL_MEMORY_ADAPTER_LENGTH 2128 class CDataAdapterDrive1541Minimal : public CDebugDataAdapter { diff --git a/src/DebugInterface/C64/CDebugInterfaceC64.cpp b/src/DebugInterface/C64/CDebugInterfaceC64.cpp index 7943a7e..fbd6e25 100644 --- a/src/DebugInterface/C64/CDebugInterfaceC64.cpp +++ b/src/DebugInterface/C64/CDebugInterfaceC64.cpp @@ -2,7 +2,7 @@ #include "CViewC64.h" #include "CDebugMemory.h" #include "CViewDataMap.h" -#include "CViewMainMenu.h" +#include "CMainMenuHelper.h" #include "CViewC64StateSID.h" #include "CByteBuffer.h" #include "CDebugSymbols.h" @@ -58,13 +58,13 @@ void CDebugInterfaceC64::Shutdown() int CDebugInterfaceC64::GetEmulatorType() { - SYS_FatalExit("CDebugInterfaceC64::GetEmulatorType"); + LOGTODO("CDebugInterfaceC64::GetEmulatorType"); return -1; } CSlrString *CDebugInterfaceC64::GetEmulatorVersionString() { - SYS_FatalExit("CDebugInterfaceC64::GetEmulatorVersionString"); + LOGTODO("CDebugInterfaceC64::GetEmulatorVersionString"); return NULL; } @@ -73,6 +73,11 @@ const char *CDebugInterfaceC64::GetPlatformNameString() return "C64"; } +const char *CDebugInterfaceC64::GetPlatformNameEndpointString() +{ + return "c64"; +} + float CDebugInterfaceC64::GetEmulationFPS() { return -1; @@ -115,17 +120,17 @@ unsigned int CDebugInterfaceC64::GetEmulationFrameNumber() void CDebugInterfaceC64::RefreshScreenNoCallback() { - SYS_FatalExit("CDebugInterfaceC64::RefreshScreenNoCallback"); + LOGTODO("CDebugInterfaceC64::RefreshScreenNoCallback"); } void CDebugInterfaceC64::InitKeyMap(C64KeyMap *keyMap) { - SYS_FatalExit("CDebugInterfaceC64::InitKeyMap"); + LOGTODO("CDebugInterfaceC64::InitKeyMap"); } uint8 *CDebugInterfaceC64::GetCharRom() { - SYS_FatalExit("CDebugInterfaceC64::GetCharRom"); + LOGTODO("CDebugInterfaceC64::GetCharRom"); return NULL; } @@ -133,7 +138,7 @@ uint8 *CDebugInterfaceC64::GetCharRom() void CDebugInterfaceC64::RunEmulationThread() { CDebugInterface::RunEmulationThread(); - SYS_FatalExit("CDebugInterfaceC64::RunEmulationThread"); + LOGTODO("CDebugInterfaceC64::RunEmulationThread"); } void CDebugInterfaceC64::CheckLoadedRoms() @@ -182,271 +187,271 @@ void CDebugInterfaceC64::SetDebugOnDrive1541(bool debugOnDrive1541) this->debugOnDrive1541 = debugOnDrive1541; } -void CDebugInterfaceC64::Reset() +void CDebugInterfaceC64::ResetSoft() { - SYS_FatalExit("CDebugInterfaceC64::Reset"); + LOGTODO("CDebugInterfaceC64::ResetSoft"); } -void CDebugInterfaceC64::HardReset() +void CDebugInterfaceC64::ResetHard() { - SYS_FatalExit("CDebugInterfaceC64::HardReset"); + LOGTODO("CDebugInterfaceC64::ResetHard"); } void CDebugInterfaceC64::DiskDriveReset() { - SYS_FatalExit("CDebugInterfaceC64::DiskDriveReset"); + LOGTODO("CDebugInterfaceC64::DiskDriveReset"); } bool CDebugInterfaceC64::KeyboardDown(uint32 mtKeyCode) { - SYS_FatalExit("CDebugInterfaceC64::KeyboardDown"); + LOGTODO("CDebugInterfaceC64::KeyboardDown"); return false; } bool CDebugInterfaceC64::KeyboardUp(uint32 mtKeyCode) { - SYS_FatalExit("CDebugInterfaceC64::KeyboardUp"); + LOGTODO("CDebugInterfaceC64::KeyboardUp"); return false; } void CDebugInterfaceC64::JoystickDown(int port, uint32 axis) { - SYS_FatalExit("CDebugInterfaceC64::JoystickDown"); + LOGTODO("CDebugInterfaceC64::JoystickDown"); } void CDebugInterfaceC64::JoystickUp(int port, uint32 axis) { - SYS_FatalExit("CDebugInterfaceC64::JoystickUp"); + LOGTODO("CDebugInterfaceC64::JoystickUp"); } int CDebugInterfaceC64::GetCpuPC() { - SYS_FatalExit("CDebugInterfaceC64::GetCpuPC"); + LOGTODO("CDebugInterfaceC64::GetCpuPC"); return 0; } int CDebugInterfaceC64::GetDrive1541PC() { - SYS_FatalExit("CDebugInterfaceC64::GetDrive1541PC"); + LOGTODO("CDebugInterfaceC64::GetDrive1541PC"); return 0; } void CDebugInterfaceC64::GetC64CpuState(C64StateCPU *state) { - SYS_FatalExit("CDebugInterfaceC64::GetC64CpuState"); + LOGTODO("CDebugInterfaceC64::GetC64CpuState"); } void CDebugInterfaceC64::GetDrive1541CpuState(C64StateCPU *state) { - SYS_FatalExit("CDebugInterfaceC64::GetDrive1541CpuState"); + LOGTODO("CDebugInterfaceC64::GetDrive1541CpuState"); } void CDebugInterfaceC64::GetVICState(C64StateVIC *state) { - SYS_FatalExit("CDebugInterfaceC64::GetVICState"); + LOGTODO("CDebugInterfaceC64::GetVICState"); } void CDebugInterfaceC64::GetDrive1541State(C64StateDrive1541 *state) { - SYS_FatalExit("CDebugInterfaceC64::GetDrive1541State"); + LOGTODO("CDebugInterfaceC64::GetDrive1541State"); } // void CDebugInterfaceC64::SetStackPointerC64(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetStackPointerC64"); + LOGTODO("CDebugInterfaceC64::SetStackPointerC64"); } void CDebugInterfaceC64::SetRegisterAC64(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetRegisterAC64"); + LOGTODO("CDebugInterfaceC64::SetRegisterAC64"); } void CDebugInterfaceC64::SetRegisterXC64(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetRegisterXC64"); + LOGTODO("CDebugInterfaceC64::SetRegisterXC64"); } void CDebugInterfaceC64::SetRegisterYC64(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetRegisterYC64"); + LOGTODO("CDebugInterfaceC64::SetRegisterYC64"); } void CDebugInterfaceC64::SetRegisterPC64(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetRegisterPC64"); + LOGTODO("CDebugInterfaceC64::SetRegisterPC64"); } void CDebugInterfaceC64::SetStackPointer1541(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetStackPointer1541"); + LOGTODO("CDebugInterfaceC64::SetStackPointer1541"); } void CDebugInterfaceC64::SetRegisterA1541(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetRegisterA1541"); + LOGTODO("CDebugInterfaceC64::SetRegisterA1541"); } void CDebugInterfaceC64::SetRegisterX1541(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetRegisterX1541"); + LOGTODO("CDebugInterfaceC64::SetRegisterX1541"); } void CDebugInterfaceC64::SetRegisterY1541(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetRegisterY1541"); + LOGTODO("CDebugInterfaceC64::SetRegisterY1541"); } void CDebugInterfaceC64::SetRegisterP1541(uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetRegisterP1541"); + LOGTODO("CDebugInterfaceC64::SetRegisterP1541"); } void CDebugInterfaceC64::InsertD64(CSlrString *path) { - SYS_FatalExit("CDebugInterfaceC64::InsertD64"); + LOGTODO("CDebugInterfaceC64::InsertD64"); } void CDebugInterfaceC64::DetachDriveDisk() { - SYS_FatalExit("CDebugInterfaceC64::DetachDriveDisk"); + LOGTODO("CDebugInterfaceC64::DetachDriveDisk"); } void CDebugInterfaceC64::MakeJMPToBasicRunC64() { - SYS_FatalExit("CDebugInterfaceC64::MakeBasicRunC64"); + LOGTODO("CDebugInterfaceC64::MakeBasicRunC64"); } bool CDebugInterfaceC64::GetSettingIsWarpSpeed() { - SYS_FatalExit("CDebugInterfaceC64::GetSettingIsWarpSpeed"); + LOGTODO("CDebugInterfaceC64::GetSettingIsWarpSpeed"); return false; } void CDebugInterfaceC64::SetSettingIsWarpSpeed(bool isWarpSpeed) { - SYS_FatalExit("CDebugInterfaceC64::SetSettingIsWarpSpeed"); + LOGTODO("CDebugInterfaceC64::SetSettingIsWarpSpeed"); } void CDebugInterfaceC64::GetSidTypes(std::vector *sidTypes) { - SYS_FatalExit("CDebugInterfaceC64::GetSidTypes"); + LOGTODO("CDebugInterfaceC64::GetSidTypes"); } void CDebugInterfaceC64::GetSidTypes(std::vector *sidTypes) { - SYS_FatalExit("CDebugInterfaceC64::GetSidTypes"); + LOGTODO("CDebugInterfaceC64::GetSidTypes"); } void CDebugInterfaceC64::SetSidType(int sidType) { - SYS_FatalExit("CDebugInterfaceC64::SetSidType"); + LOGTODO("CDebugInterfaceC64::SetSidType"); } // samplingMethod: Fast=0, Interpolating=1, Resampling=2, Fast Resampling=3 void CDebugInterfaceC64::SetSidSamplingMethod(int samplingMethod) { - SYS_FatalExit("CDebugInterfaceC64::SetSidSamplingMethod"); + LOGTODO("CDebugInterfaceC64::SetSidSamplingMethod"); } // emulateFilters: no=0, yes=1 void CDebugInterfaceC64::SetSidEmulateFilters(int emulateFilters) { - SYS_FatalExit("CDebugInterfaceC64::SetSidEmulateFilters"); + LOGTODO("CDebugInterfaceC64::SetSidEmulateFilters"); } // passband: 0-90 void CDebugInterfaceC64::SetSidPassBand(int passband) { - SYS_FatalExit("CDebugInterfaceC64::SetSidPassBand"); + LOGTODO("CDebugInterfaceC64::SetSidPassBand"); } // filterBias: -500 500 void CDebugInterfaceC64::SetSidFilterBias(int filterBias) { - SYS_FatalExit("CDebugInterfaceC64::SetSidFilterBias"); + LOGTODO("CDebugInterfaceC64::SetSidFilterBias"); } int CDebugInterfaceC64::GetNumSids() { - SYS_FatalExit("CDebugInterfaceC64::GetNumSids"); + LOGTODO("CDebugInterfaceC64::GetNumSids"); return 0; } void CDebugInterfaceC64::SetSidStereo(int stereoMode) { - SYS_FatalExit("CDebugInterfaceC64::SetSidStereo"); + LOGTODO("CDebugInterfaceC64::SetSidStereo"); } void CDebugInterfaceC64::SetSidStereoAddress(uint16 sidAddress) { - SYS_FatalExit("CDebugInterfaceC64::SetSidStereoAddress"); + LOGTODO("CDebugInterfaceC64::SetSidStereoAddress"); } void CDebugInterfaceC64::SetSidTripleAddress(uint16 sidAddress) { - SYS_FatalExit("CDebugInterfaceC64::SetSidTripleAddress"); + LOGTODO("CDebugInterfaceC64::SetSidTripleAddress"); } void CDebugInterfaceC64::GetC64ModelTypes(std::vector *modelTypeNames, std::vector *modelTypeIds) { - SYS_FatalExit("CDebugInterfaceC64::GetC64ModelTypes"); + LOGTODO("CDebugInterfaceC64::GetC64ModelTypes"); } void CDebugInterfaceC64::GetC64ModelTypes(std::vector *modelTypeNames, std::vector *modelTypeIds) { - SYS_FatalExit("CDebugInterfaceC64::GetC64ModelTypes"); + LOGTODO("CDebugInterfaceC64::GetC64ModelTypes"); } void CDebugInterfaceC64::SetC64ModelType(int modelType) { - SYS_FatalExit("CDebugInterfaceC64::SetC64ModelType"); + LOGTODO("CDebugInterfaceC64::SetC64ModelType"); } void CDebugInterfaceC64::SetPatchKernalFastBoot(bool isPatchKernal) { - SYS_FatalExit("CDebugInterfaceC64::SetPatchKernalFastBoot"); + LOGTODO("CDebugInterfaceC64::SetPatchKernalFastBoot"); } void CDebugInterfaceC64::SetRunSIDWhenInWarp(bool isRunningSIDInWarp) { - SYS_FatalExit("CDebugInterfaceC64::SetRunSIDWhenInWarp"); + LOGTODO("CDebugInterfaceC64::SetRunSIDWhenInWarp"); } void CDebugInterfaceC64::SetEmulationMaximumSpeed(int maximumSpeed) { - SYS_FatalExit("CDebugInterfaceC64::SetEmulationMaximumSpeed"); + LOGTODO("CDebugInterfaceC64::SetEmulationMaximumSpeed"); } void CDebugInterfaceC64::SetVSPBugEmulation(bool isVSPBugEmulation) { - SYS_FatalExit("CDebugInterfaceC64::SetVSPBugEmulation"); + LOGTODO("CDebugInterfaceC64::SetVSPBugEmulation"); } void CDebugInterfaceC64::SetSkipDrawingSprites(bool isSkipDrawingSprites) { - SYS_FatalExit("CDebugInterfaceC64::SetSkipDrawingSprites"); + LOGTODO("CDebugInterfaceC64::SetSkipDrawingSprites"); } void CDebugInterfaceC64::SetByteC64(uint16 addr, uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetByteC64"); + LOGTODO("CDebugInterfaceC64::SetByteC64"); } void CDebugInterfaceC64::SetByteToRamC64(uint16 addr, uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetByteToRamC64"); + LOGTODO("CDebugInterfaceC64::SetByteToRamC64"); } uint8 CDebugInterfaceC64::GetByteC64(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::GetByteC64"); + LOGTODO("CDebugInterfaceC64::GetByteC64"); return 0; } uint8 CDebugInterfaceC64::GetByteFromRamC64(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::GetByteFromRamC64"); + LOGTODO("CDebugInterfaceC64::GetByteFromRamC64"); return 0; } @@ -469,22 +474,22 @@ void CDebugInterfaceC64::MakeJmpAndReset(uint16 addr) void CDebugInterfaceC64::MakeJmpC64(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::MakeJmpC64"); + LOGTODO("CDebugInterfaceC64::MakeJmpC64"); } void CDebugInterfaceC64::MakeJmpNoResetC64(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::MakeJmpNoResetC64"); + LOGTODO("CDebugInterfaceC64::MakeJmpNoResetC64"); } void CDebugInterfaceC64::MakeJsrC64(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::MakeJsrC64"); + LOGTODO("CDebugInterfaceC64::MakeJsrC64"); } void CDebugInterfaceC64::MakeJmpNoReset1541(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::MakeJmpNoReset1541"); + LOGTODO("CDebugInterfaceC64::MakeJmpNoReset1541"); } void CDebugInterfaceC64::SupportsBreakpoints(bool *writeBreakpoint, bool *readBreakpoint) @@ -504,159 +509,159 @@ void CDebugInterfaceC64::ClearTemporaryBreakpoint() void CDebugInterfaceC64::SetByte1541(uint16 addr, uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetByte1541"); + LOGTODO("CDebugInterfaceC64::SetByte1541"); } void CDebugInterfaceC64::SetByteToRam1541(uint16 addr, uint8 val) { - SYS_FatalExit("CDebugInterfaceC64::SetByteToRam1541"); + LOGTODO("CDebugInterfaceC64::SetByteToRam1541"); } uint8 CDebugInterfaceC64::GetByte1541(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::GetByte1541"); + LOGTODO("CDebugInterfaceC64::GetByte1541"); return 0; } uint8 CDebugInterfaceC64::GetByteFromRam1541(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::GetByteFromRam1541"); + LOGTODO("CDebugInterfaceC64::GetByteFromRam1541"); return 0; } void CDebugInterfaceC64::MakeJmp1541(uint16 addr) { - SYS_FatalExit("CDebugInterfaceC64::MakeJmp1541"); + LOGTODO("CDebugInterfaceC64::MakeJmp1541"); } void CDebugInterfaceC64::GetWholeMemoryMap(uint8 *buffer) { - SYS_FatalExit("CDebugInterfaceC64::GetWholeMemoryMap"); + LOGTODO("CDebugInterfaceC64::GetWholeMemoryMap"); } void CDebugInterfaceC64::GetWholeMemoryMapFromRam(uint8 *buffer) { - SYS_FatalExit("CDebugInterfaceC64::GetWholeMemoryMapFromRam"); + LOGTODO("CDebugInterfaceC64::GetWholeMemoryMapFromRam"); } void CDebugInterfaceC64::GetWholeMemoryMap1541(uint8 *buffer) { - SYS_FatalExit("CDebugInterfaceC64::GetWholeMemoryMap1541"); + LOGTODO("CDebugInterfaceC64::GetWholeMemoryMap1541"); } void CDebugInterfaceC64::GetWholeMemoryMapFromRam1541(uint8 *buffer) { - SYS_FatalExit("CDebugInterfaceC64::GetWholeMemoryMapFromRam1541"); + LOGTODO("CDebugInterfaceC64::GetWholeMemoryMapFromRam1541"); } void CDebugInterfaceC64::GetMemory(uint8 *buffer, int addrStart, int addrEnd) { - SYS_FatalExit("CDebugInterfaceC64::GetMemory"); + LOGTODO("CDebugInterfaceC64::GetMemory"); } void CDebugInterfaceC64::GetMemoryFromRam(uint8 *buffer, int addrStart, int addrEnd) { - SYS_FatalExit("CDebugInterfaceC64::GetMemoryFromRam"); + LOGTODO("CDebugInterfaceC64::GetMemoryFromRam"); } void CDebugInterfaceC64::GetMemoryDrive1541(uint8 *buffer, int addrStart, int addrEnd) { - SYS_FatalExit("CDebugInterfaceC64::GetMemoryDrive1541"); + LOGTODO("CDebugInterfaceC64::GetMemoryDrive1541"); } void CDebugInterfaceC64::GetMemoryFromRamDrive1541(uint8 *buffer, int addrStart, int addrEnd) { - SYS_FatalExit("CDebugInterfaceC64::GetMemoryFromRamDrive1541"); + LOGTODO("CDebugInterfaceC64::GetMemoryFromRamDrive1541"); } void CDebugInterfaceC64::FillC64Ram(uint16 addr, uint16 size, uint8 value) { - SYS_FatalExit("CDebugInterfaceC64::FillC64Ram"); + LOGTODO("CDebugInterfaceC64::FillC64Ram"); } bool CDebugInterfaceC64::LoadFullSnapshot(CByteBuffer *snapshotBuffer) { - SYS_FatalExit("CDebugInterfaceC64::LoadFullSnapshot"); + LOGTODO("CDebugInterfaceC64::LoadFullSnapshot"); return false; } void CDebugInterfaceC64::SaveFullSnapshot(CByteBuffer *snapshotBuffer) { - SYS_FatalExit("CDebugInterfaceC64::SaveFullSnapshot"); + LOGTODO("CDebugInterfaceC64::SaveFullSnapshot"); } bool CDebugInterfaceC64::LoadFullSnapshot(char *filePath) { - SYS_FatalExit("CDebugInterfaceC64::LoadFullSnapshot"); + LOGTODO("CDebugInterfaceC64::LoadFullSnapshot"); return false; } void CDebugInterfaceC64::SaveFullSnapshot(char *filePath) { - SYS_FatalExit("CDebugInterfaceC64::SaveFullSnapshot"); + LOGTODO("CDebugInterfaceC64::SaveFullSnapshot"); } // this call should be synced with CPU IRQ so snapshot store or restore is allowed bool CDebugInterfaceC64::LoadChipsSnapshotSynced(CByteBuffer *byteBuffer) { - SYS_FatalExit("CDebugInterfaceC64::LoadChipsSnapshotSynced"); + LOGTODO("CDebugInterfaceC64::LoadChipsSnapshotSynced"); return false; } bool CDebugInterfaceC64::SaveChipsSnapshotSynced(CByteBuffer *byteBuffer) { - SYS_FatalExit("CDebugInterfaceC64::SaveChipsSnapshotSynced"); + LOGTODO("CDebugInterfaceC64::SaveChipsSnapshotSynced"); return false; } bool CDebugInterfaceC64::LoadDiskDataSnapshotSynced(CByteBuffer *byteBuffer) { - SYS_FatalExit("CDebugInterfaceC64::LoadDiskDataSnapshotSynced"); + LOGTODO("CDebugInterfaceC64::LoadDiskDataSnapshotSynced"); return false; } bool CDebugInterfaceC64::SaveDiskDataSnapshotSynced(CByteBuffer *byteBuffer) { - SYS_FatalExit("CDebugInterfaceC64::SaveDiskDataSnapshotSynced"); + LOGTODO("CDebugInterfaceC64::SaveDiskDataSnapshotSynced"); return false; } bool CDebugInterfaceC64::IsDriveDirtyForSnapshot() { - SYS_FatalExit("CDebugInterfaceC64::IsDriveDirtyForSnapshot"); + LOGTODO("CDebugInterfaceC64::IsDriveDirtyForSnapshot"); return false; } void CDebugInterfaceC64::ClearDriveDirtyForSnapshotFlag() { - SYS_FatalExit("CDebugInterfaceC64::ClearDriveDirtyForSnapshotFlag"); + LOGTODO("CDebugInterfaceC64::ClearDriveDirtyForSnapshotFlag"); } void CDebugInterfaceC64::GetVICColors(uint8 *cD021, uint8 *cD022, uint8 *cD023, uint8 *cD025, uint8 *cD026, uint8 *cD027, uint8 *cD800) { - SYS_FatalExit("CDebugInterfaceC64::GetVICColors"); + LOGTODO("CDebugInterfaceC64::GetVICColors"); } void CDebugInterfaceC64::GetVICSpriteColors(uint8 *cD021, uint8 *cD025, uint8 *cD026, uint8 *spriteColors) { - SYS_FatalExit("CDebugInterfaceC64::GetVICSpriteColors"); + LOGTODO("CDebugInterfaceC64::GetVICSpriteColors"); } void CDebugInterfaceC64::GetCBMColor(uint8 colorNum, uint8 *r, uint8 *g, uint8 *b) { - SYS_FatalExit("CDebugInterfaceC64::GetCBMColor"); + LOGTODO("CDebugInterfaceC64::GetCBMColor"); } void CDebugInterfaceC64::GetFloatCBMColor(uint8 colorNum, float *r, float *g, float *b) { - SYS_FatalExit("CDebugInterfaceC64::GetFloatCBMColor"); + LOGTODO("CDebugInterfaceC64::GetFloatCBMColor"); } // //void CDebugInterfaceC64::UiInsertD64(CSlrString *path) //{ -// SYS_FatalExit("CDebugInterfaceC64::UiInsertD64"); +// LOGTODO("CDebugInterfaceC64::UiInsertD64"); //// LOGTODO("CDebugInterfaceC64::UiInsertD64: shall we update Folder path to D64?"); //// viewC64->viewC64MainMenu->InsertD64(path, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0); //} @@ -664,12 +669,12 @@ void CDebugInterfaceC64::GetFloatCBMColor(uint8 colorNum, float *r, float *g, fl // void CDebugInterfaceC64::SetVicRegister(uint8 registerNum, uint8 value) { - SYS_FatalExit("CDebugInterfaceC64::SetVicRegister"); + LOGTODO("CDebugInterfaceC64::SetVicRegister"); } u8 CDebugInterfaceC64::GetVicRegister(uint8 registerNum) { - SYS_FatalExit("CDebugInterfaceC64::GetVicRegister"); + LOGTODO("CDebugInterfaceC64::GetVicRegister"); return 0; } @@ -681,51 +686,51 @@ u8 CDebugInterfaceC64::GetVicRegister(vicii_cycle_state_t *viciiState, uint8 reg void CDebugInterfaceC64::SetCiaRegister(uint8 ciaId, uint8 registerNum, uint8 value) { - SYS_FatalExit("CDebugInterfaceC64::SetCiaRegister"); + LOGTODO("CDebugInterfaceC64::SetCiaRegister"); } u8 CDebugInterfaceC64::GetCiaRegister(uint8 ciaId, uint8 registerNum) { - SYS_FatalExit("CDebugInterfaceC64::GetCiaRegister"); + LOGTODO("CDebugInterfaceC64::GetCiaRegister"); return 0; } void CDebugInterfaceC64::SetSidRegister(uint8 sidId, uint8 registerNum, uint8 value) { - SYS_FatalExit("CDebugInterfaceC64::SetSidRegister"); + LOGTODO("CDebugInterfaceC64::SetSidRegister"); } u8 CDebugInterfaceC64::GetSidRegister(uint8 sidId, uint8 registerNum) { - SYS_FatalExit("CDebugInterfaceC64::GetSidRegister"); + LOGTODO("CDebugInterfaceC64::GetSidRegister"); return 0; } void CDebugInterfaceC64::UpdateSidDataHistory() { - SYS_FatalExit("CDebugInterfaceC64::UpdateSidDataHistory"); + LOGTODO("CDebugInterfaceC64::UpdateSidDataHistory"); } void CDebugInterfaceC64::SetViaRegister(uint8 driveId, uint8 viaId, uint8 registerNum, uint8 value) { - SYS_FatalExit("CDebugInterfaceC64::SetViaRegister"); + LOGTODO("CDebugInterfaceC64::SetViaRegister"); } u8 CDebugInterfaceC64::GetViaRegister(uint8 driveId, uint8 viaId, uint8 registerNum) { - SYS_FatalExit("CDebugInterfaceC64::GetViaRegister"); + LOGTODO("CDebugInterfaceC64::GetViaRegister"); return 0; } void CDebugInterfaceC64::SetSIDMuteChannels(int sidNumber, bool mute1, bool mute2, bool mute3, bool muteExt) { - SYS_FatalExit("CDebugInterfaceC64::SetSIDMuteChannels"); + LOGTODO("CDebugInterfaceC64::SetSIDMuteChannels"); } void CDebugInterfaceC64::SetSIDReceiveChannelsData(int sidNumber, bool isReceiving) { - SYS_FatalExit("CDebugInterfaceC64::SetSIDReceiveChannelsData"); + LOGTODO("CDebugInterfaceC64::SetSIDReceiveChannelsData"); } // @@ -796,60 +801,59 @@ void CDebugInterfaceC64::UpdateWaveformsMuteStatus() void CDebugInterfaceC64::SetVicRecordStateMode(uint8 recordMode) { - SYS_FatalExit("CDebugInterfaceC64::SetVicRecordStateMode"); + LOGTODO("CDebugInterfaceC64::SetVicRecordStateMode"); } bool CDebugInterfaceC64::IsCpuJam() { - SYS_FatalExit("CDebugInterfaceC64::IsCpuJam"); + LOGTODO("CDebugInterfaceC64::IsCpuJam"); return false; } void CDebugInterfaceC64::ForceRunAndUnJamCpu() { - SYS_FatalExit("CDebugInterfaceC64::ForceRunAndUnJamCpu"); + LOGTODO("CDebugInterfaceC64::ForceRunAndUnJamCpu"); } - // void CDebugInterfaceC64::AttachTape(CSlrString *filePath) { - SYS_FatalExit("CDebugInterfaceC64::AttachTape"); + LOGTODO("CDebugInterfaceC64::AttachTape"); } void CDebugInterfaceC64::DetachTape() { - SYS_FatalExit("CDebugInterfaceC64::DetachTape"); + LOGTODO("CDebugInterfaceC64::DetachTape"); } void CDebugInterfaceC64::DatasettePlay() { - SYS_FatalExit("CDebugInterfaceC64::DatasettePlay"); + LOGTODO("CDebugInterfaceC64::DatasettePlay"); } void CDebugInterfaceC64::DatasetteStop() { - SYS_FatalExit("CDebugInterfaceC64::DatasetteStop"); + LOGTODO("CDebugInterfaceC64::DatasetteStop"); } void CDebugInterfaceC64::DatasetteForward() { - SYS_FatalExit("CDebugInterfaceC64::DatasetteForward"); + LOGTODO("CDebugInterfaceC64::DatasetteForward"); } void CDebugInterfaceC64::DatasetteRewind() { - SYS_FatalExit("CDebugInterfaceC64::DatasetteRewind"); + LOGTODO("CDebugInterfaceC64::DatasetteRewind"); } void CDebugInterfaceC64::DatasetteRecord() { - SYS_FatalExit("CDebugInterfaceC64::DatasetteRecord"); + LOGTODO("CDebugInterfaceC64::DatasetteRecord"); } void CDebugInterfaceC64::DatasetteReset() { - SYS_FatalExit("CDebugInterfaceC64::DatasetteReset"); + LOGTODO("CDebugInterfaceC64::DatasetteReset"); } void CDebugInterfaceC64::DatasetteSetSpeedTuning(int speedTuning) @@ -870,81 +874,81 @@ void CDebugInterfaceC64::DatasetteSetTapeWobble(int tapeWobble) void CDebugInterfaceC64::AttachCartridge(CSlrString *filePath) { - SYS_FatalExit("CDebugInterfaceC64::AttachCartridge"); + LOGTODO("CDebugInterfaceC64::AttachCartridge"); } void CDebugInterfaceC64::DetachCartridge() { - SYS_FatalExit("CDebugInterfaceC64::DetachCartridge"); + LOGTODO("CDebugInterfaceC64::DetachCartridge"); } void CDebugInterfaceC64::CartridgeFreezeButtonPressed() { - SYS_FatalExit("CDebugInterfaceC64::CartridgeFreezeButtonPressed"); + LOGTODO("CDebugInterfaceC64::CartridgeFreezeButtonPressed"); } void CDebugInterfaceC64::GetC64CartridgeState(C64StateCartridge *cartridgeState) { - SYS_FatalExit("CDebugInterfaceC64::GetC64CartridgeState"); + LOGTODO("CDebugInterfaceC64::GetC64CartridgeState"); } // REU void CDebugInterfaceC64::SetReuEnabled(bool isEnabled) { - SYS_FatalExit("CDebugInterfaceC64::SetReuEnabled"); + LOGTODO("CDebugInterfaceC64::SetReuEnabled"); } void CDebugInterfaceC64::SetReuSize(int reuSize) { - SYS_FatalExit("CDebugInterfaceC64::SetReuSize"); + LOGTODO("CDebugInterfaceC64::SetReuSize"); } bool CDebugInterfaceC64::LoadReu(char *filePath) { - SYS_FatalExit("CDebugInterfaceC64::LoadReu"); + LOGTODO("CDebugInterfaceC64::LoadReu"); return false; } bool CDebugInterfaceC64::SaveReu(char *filePath) { - SYS_FatalExit("CDebugInterfaceC64::SaveReu"); + LOGTODO("CDebugInterfaceC64::SaveReu"); return false; } // void CDebugInterfaceC64::DetachEverything() { - SYS_FatalExit("CDebugInterfaceC64::DetachEverything"); + LOGTODO("CDebugInterfaceC64::DetachEverything"); } void CDebugInterfaceC64::SetPalette(uint8 *palette) { - SYS_FatalExit("CDebugInterfaceC64::SetPalette"); + LOGTODO("CDebugInterfaceC64::SetPalette"); } void CDebugInterfaceC64::SetRunSIDEmulation(bool isSIDEmulationOn) { - SYS_FatalExit("CDebugInterfaceC64::SetRunSIDEmulation"); + LOGTODO("CDebugInterfaceC64::SetRunSIDEmulation"); } void CDebugInterfaceC64::SetAudioVolume(float volume) { - SYS_FatalExit("CDebugInterfaceC64::SetAudioVolume"); + LOGTODO("CDebugInterfaceC64::SetAudioVolume"); } void CDebugInterfaceC64::ProfilerActivate(char *fileName, int runForNumCycles, bool pauseCpuWhenFinished) { - SYS_FatalExit("CDebugInterfaceC64::ProfilerActivate"); + LOGTODO("CDebugInterfaceC64::ProfilerActivate"); } void CDebugInterfaceC64::ProfilerDeactivate() { - SYS_FatalExit("CDebugInterfaceC64::ProfilerDeactivate"); + LOGTODO("CDebugInterfaceC64::ProfilerDeactivate"); } bool CDebugInterfaceC64::IsProfilerActive() { - SYS_FatalExit("CDebugInterfaceC64::IsProfilerActive"); + LOGTODO("CDebugInterfaceC64::IsProfilerActive"); return false; } @@ -953,9 +957,14 @@ CDebugDataAdapter *CDebugInterfaceC64::GetDataAdapter() return this->dataAdapterC64; } +CDebugDataAdapter *CDebugInterfaceC64::GetDataAdapterDirectRam() +{ + return this->dataAdapterC64DirectRam; +} + //void CDebugInterfaceC64::UpdateDriveDiskID(int driveId) //{ -// SYS_FatalExit("CDebugInterfaceC64::UpdateDriveDiskID"); +// LOGTODO("CDebugInterfaceC64::UpdateDriveDiskID"); //} // @@ -1231,3 +1240,47 @@ bool CDebugInterfaceC64::ExecuteCodeMonitorCommand(CSlrString *commandStr) return false; } +void CDebugInterfaceC64::EmulatedMouseUpdateSettings() +{ +} + +bool CDebugInterfaceC64::EmulatedMouseEnable(bool enable) +{ + return false; +} + +void CDebugInterfaceC64::EmulatedMouseSetType(int mouseType) +{ +} + +void CDebugInterfaceC64::EmulatedMouseSetPort(int port) +{ +} + +void CDebugInterfaceC64::EmulatedMouseSetPosition(int newX, int newY) +{ +} + +void CDebugInterfaceC64::EmulatedMouseButtonLeft(bool isPressed) +{ +} + +void CDebugInterfaceC64::EmulatedMouseButtonMiddle(bool isPressed) +{ +} + +void CDebugInterfaceC64::EmulatedMouseButtonRight(bool isPressed) +{ +} + +CDebuggerApi *CDebugInterfaceC64::GetDebuggerApi() +{ + LOGError("CDebugInterfaceC64::GetDebuggerApi: not implemented"); + return NULL; +} + +CDebuggerServerApi *CDebugInterfaceC64::GetDebuggerServerApi() +{ + return CDebugInterface::GetDebuggerServerApi(); +} + diff --git a/src/DebugInterface/C64/CDebugInterfaceC64.h b/src/DebugInterface/C64/CDebugInterfaceC64.h index 83fd475..fa0a584 100644 --- a/src/DebugInterface/C64/CDebugInterfaceC64.h +++ b/src/DebugInterface/C64/CDebugInterfaceC64.h @@ -2,7 +2,6 @@ #define _CDebugInterfaceC64_H_ #include "CDebugInterface.h" -#include "CDebugBreakpoints.h" #include "CDataAdapter.h" #include "CByteBuffer.h" #include "DebuggerDefs.h" @@ -38,6 +37,7 @@ class CDebugInterfaceC64 : public CDebugInterface virtual int GetEmulatorType(); virtual CSlrString *GetEmulatorVersionString(); virtual const char *GetPlatformNameString(); + virtual const char *GetPlatformNameEndpointString(); virtual float GetEmulationFPS(); @@ -94,8 +94,8 @@ class CDebugInterfaceC64 : public CDebugInterface virtual int GetScreenSizeX(); virtual int GetScreenSizeY(); - virtual void Reset(); - virtual void HardReset(); + virtual void ResetSoft(); + virtual void ResetHard(); virtual void DiskDriveReset(); // C64 keyboard & joystick mapper @@ -105,6 +105,16 @@ class CDebugInterfaceC64 : public CDebugInterface virtual void JoystickDown(int port, uint32 axis); virtual void JoystickUp(int port, uint32 axis); + // + virtual void EmulatedMouseUpdateSettings(); + virtual bool EmulatedMouseEnable(bool enable); + virtual void EmulatedMouseSetType(int mouseType); + virtual void EmulatedMouseSetPort(int port); + virtual void EmulatedMouseSetPosition(int x, int y); + virtual void EmulatedMouseButtonLeft(bool isPressed); + virtual void EmulatedMouseButtonMiddle(bool isPressed); + virtual void EmulatedMouseButtonRight(bool isPressed); + // debugger control virtual void SetDebugOnC64(bool debugOnC64); virtual void SetDebugOnDrive1541(bool debugOnDrive1541); @@ -247,6 +257,7 @@ class CDebugInterfaceC64 : public CDebugInterface // // see $F3F6 in 1541 ROM: http://unusedino.de/ec64/technical/misc/c1541/romlisting.html#FDD3 // virtual void UpdateDriveDiskID(int driveId); + virtual void DetachEverything(); // tape virtual void AttachTape(CSlrString *filePath); @@ -268,9 +279,6 @@ class CDebugInterfaceC64 : public CDebugInterface virtual bool LoadReu(char *filePath); virtual bool SaveReu(char *filePath); - // - virtual void DetachEverything(); - // snapshots virtual bool LoadFullSnapshot(CByteBuffer *snapshotBuffer); virtual void SaveFullSnapshot(CByteBuffer *snapshotBuffer); @@ -332,6 +340,7 @@ class CDebugInterfaceC64 : public CDebugInterface // virtual CDebugDataAdapter *GetDataAdapter(); + virtual CDebugDataAdapter *GetDataAdapterDirectRam(); // // @returns NULL when monitor is not supported @@ -352,7 +361,9 @@ class CDebugInterfaceC64 : public CDebugInterface virtual bool IsProfilerActive(); // - + virtual CDebuggerApi *GetDebuggerApi(); + virtual CDebuggerServerApi *GetDebuggerServerApi(); + }; #endif diff --git a/src/DebugInterface/C64/CDebugSymbolsSegmentC64.cpp b/src/DebugInterface/C64/CDebugSymbolsSegmentC64.cpp index e137d39..3b5f2a7 100644 --- a/src/DebugInterface/C64/CDebugSymbolsSegmentC64.cpp +++ b/src/DebugInterface/C64/CDebugSymbolsSegmentC64.cpp @@ -1,5 +1,7 @@ #include "CDebugSymbolsSegmentC64.h" #include "CDebugSymbols.h" +#include "CDebugBreakpointsRasterLine.h" +#include "CDebugBreakpointRasterLine.h" CDebugSymbolsSegmentC64::CDebugSymbolsSegmentC64(CDebugSymbols *debugSymbols, CSlrString *name, int segmentNum) : CDebugSymbolsSegment(debugSymbols, name, segmentNum, true) @@ -11,8 +13,10 @@ void CDebugSymbolsSegmentC64::Init() CDebugSymbolsSegment::Init(); breakOnRaster = true; - breakpointsRasterLine = new CDebugBreakpointsAddr(BREAKPOINT_TYPE_RASTER_LINE, "RasterLine", this, "%03X", 0, 0x137); + breakpointsRasterLine = new CDebugBreakpointsRasterLine(BREAKPOINT_TYPE_RASTER_LINE, "RasterLine", this, "%03X", 0, 0x137); breakpointsRasterLine->addBreakpointPopupHeadlineStr = "Add Raster line Breakpoint"; + breakpointsRasterLine->addBreakpointsTableColumnAddrStr = "Raster line"; + breakpointsRasterLine->addressNameJsonStr = "rasterLine"; breakpointsByType[BREAKPOINT_TYPE_RASTER_LINE] = breakpointsRasterLine; @@ -21,12 +25,18 @@ void CDebugSymbolsSegmentC64::Init() breakOnC64IrqNMI = false; } -void CDebugSymbolsSegmentC64::AddBreakpointRaster(int rasterNum) +CDebugBreakpointRasterLine *CDebugSymbolsSegmentC64::AddBreakpointRaster(int rasterNum) { - CBreakpointAddr *rasterBreakpoint = new CBreakpointAddr(rasterNum); - this->breakpointsRasterLine->AddBreakpoint(rasterBreakpoint); - - this->breakOnRaster = true; + CDebugBreakpointRasterLine *rasterBreakpoint = new CDebugBreakpointRasterLine(symbols, rasterNum); + breakpointsRasterLine->AddBreakpoint(rasterBreakpoint); + breakOnRaster = true; + return rasterBreakpoint; +} + +u64 CDebugSymbolsSegmentC64::RemoveBreakpointRaster(int rasterNum) +{ + u64 breakpointId = breakpointsRasterLine->DeleteBreakpoint(rasterNum); + return breakpointId; } void CDebugSymbolsSegmentC64::UpdateRenderBreakpoints() diff --git a/src/DebugInterface/C64/CDebugSymbolsSegmentC64.h b/src/DebugInterface/C64/CDebugSymbolsSegmentC64.h index 45ecfd9..79a1e0e 100644 --- a/src/DebugInterface/C64/CDebugSymbolsSegmentC64.h +++ b/src/DebugInterface/C64/CDebugSymbolsSegmentC64.h @@ -23,7 +23,8 @@ class CDebugSymbolsSegmentC64 : public CDebugSymbolsSegment virtual void Init(); // - void AddBreakpointRaster(int rasterNum); + CDebugBreakpointRasterLine *AddBreakpointRaster(int rasterNum); + u64 RemoveBreakpointRaster(int rasterNum); void AddBreakpointVIC(); void AddBreakpointCIA(); void AddBreakpointNMI(); diff --git a/src/DebugInterface/CDebugBreakpoints.cpp b/src/DebugInterface/CDebugBreakpoints.cpp index 851f110..8b13789 100644 --- a/src/DebugInterface/CDebugBreakpoints.cpp +++ b/src/DebugInterface/CDebugBreakpoints.cpp @@ -1,820 +1 @@ -#include "CDebugBreakpoints.h" -#include "CViewDisassembly.h" -#include "CDebugInterface.h" -#include "CDebugSymbols.h" -#include "CDebugSymbolsSegment.h" -#include "CDebugSymbolsCodeLabel.h" -#include "GUI_Main.h" -CDebugBreakpoint::CDebugBreakpoint() -{ -} - -CDebugBreakpoint::~CDebugBreakpoint() -{ -} - -void CDebugBreakpoint::Serialize(Hjson::Value hjsonRoot) -{ -} - -void CDebugBreakpoint::Deserialize(Hjson::Value hjsonRoot) -{ -} - -CBreakpointAddr::CBreakpointAddr(int addr) -{ - this->isActive = true; - this->addr = addr; - this->actions = ADDR_BREAKPOINT_ACTION_STOP; - this->data = 0x00; -} - -void CBreakpointAddr::Serialize(Hjson::Value hjsonRoot) -{ - hjsonRoot["IsActive"] = isActive; - hjsonRoot["Addr"] = addr; - hjsonRoot["Actions"] = actions; - hjsonRoot["Data"] = data; -} - -void CBreakpointAddr::Deserialize(Hjson::Value hjsonRoot) -{ - isActive = (bool)hjsonRoot["IsActive"]; - addr = hjsonRoot["Addr"]; - actions = hjsonRoot["Actions"]; - data = hjsonRoot["Data"]; -} - -CBreakpointAddr::~CBreakpointAddr() -{ -} - -CBreakpointMemory::CBreakpointMemory(int addr, - u32 memoryAccess, MemoryBreakpointComparison comparison, int value) -: CBreakpointAddr(addr) -{ - this->memoryAccess = memoryAccess; - this->value = value; - this->comparison = comparison; -} - -void CBreakpointMemory::Serialize(Hjson::Value hjsonRoot) -{ - CBreakpointAddr::Serialize(hjsonRoot); - - hjsonRoot["MemoryAccess"] = memoryAccess; - hjsonRoot["Value"] = value; - hjsonRoot["Comparison"] = (int)comparison; -} - -void CBreakpointMemory::Deserialize(Hjson::Value hjsonRoot) -{ - CBreakpointAddr::Deserialize(hjsonRoot); - - memoryAccess = hjsonRoot["MemoryAccess"]; - value = hjsonRoot["Value"]; - comparison = (MemoryBreakpointComparison) ((int)hjsonRoot["Comparison"]); -} - -//std::map memoryBreakpoints; - -CDebugBreakpointsAddr::CDebugBreakpointsAddr(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr) -{ - this->breakpointsType = breakpointType; - this->breakpointsTypeStr = breakpointTypeStr; - this->segment = segment; - this->symbols = segment->symbols; - this->addressFormatStr = addressFormatStr; - this->minAddr = minAddr; - this->maxAddr = maxAddr; - comboFilterState = {0, false}; - comboFilterTextBuf[0] = 0; - - renderBreakpointsMutex = new CSlrMutex("CDebugBreakpointsAddr::renderBreakpointsMutex"); - - addBreakpointPopupHeadlineStr = "Add PC Breakpoint"; - addBreakpointPopupAddrStr = "Address"; - addBreakpointPopupAddrInputFlags = ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase; - - temporaryBreakpointPC = -1; - - // TODO: workaround, remove me when ImGui bug is fixed: https://github.com/ocornut/imgui/issues/1655 - imGuiColumnsWidthWorkaroundFrame = 0; - - imGuiOpenPopupFrame = 999; -} - -// address -1 means no breakpoint -void CDebugBreakpointsAddr::SetTemporaryBreakpointPC(int address) -{ - this->temporaryBreakpointPC = address; -} - -int CDebugBreakpointsAddr::GetTemporaryBreakpointPC() -{ - return this->temporaryBreakpointPC; -} - -void CDebugBreakpointsAddr::ClearBreakpoints() -{ - while(!breakpoints.empty()) - { - std::map::iterator it = breakpoints.begin(); - CBreakpointAddr *breakpoint = it->second; - - breakpoints.erase(it); - delete breakpoint; - } -} - -CDebugBreakpoint *CDebugBreakpointsAddr::CreateEmptyBreakpoint() -{ - return new CBreakpointAddr(0); -} - -void CDebugBreakpointsAddr::Serialize(Hjson::Value hjsonBreakpoints) -{ - for (std::map::iterator it = breakpoints.begin(); it != breakpoints.end(); it++) - { - CBreakpointAddr *breakpoint = it->second; - Hjson::Value hjsonBreakpoint; - breakpoint->Serialize(hjsonBreakpoint); - - CDebugSymbolsCodeLabel *label = segment->FindLabel(breakpoint->addr); - if (label) - { - hjsonBreakpoint["Label"] = label->GetLabelText(); - } - - hjsonBreakpoints.push_back(hjsonBreakpoint); - } -} - -void CDebugBreakpointsAddr::Deserialize(Hjson::Value hjsonBreakpoints) -{ - for (int index = 0; index < hjsonBreakpoints.size(); ++index) - { - Hjson::Value hjsonBreakpoint = hjsonBreakpoints[index]; - CBreakpointAddr *breakpoint = (CBreakpointAddr*)CreateEmptyBreakpoint(); - breakpoint->Deserialize(hjsonBreakpoint); - - // check label - Hjson::Value hjsonBreakpointLabel = hjsonBreakpoint["Label"]; - if (hjsonBreakpointLabel != Hjson::Type::Undefined) - { - const char *labelStr = hjsonBreakpoint["Label"]; - CDebugSymbolsCodeLabel *label = segment->FindLabelByText(labelStr); - if (label) - { - breakpoint->addr = label->address; - } - } - - AddBreakpoint(breakpoint); - } -} - -CDebugBreakpointsMemory::CDebugBreakpointsMemory(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr) -: CDebugBreakpointsAddr(breakpointType, breakpointTypeStr, segment, addressFormatStr, minAddr, maxAddr) -{ - addBreakpointPopupHeadlineStr = "Add Memory Breakpoint"; - addBreakpointPopupAddrStr = "Address"; -} - -CDebugBreakpoint *CDebugBreakpointsMemory::CreateEmptyBreakpoint() -{ - return new CBreakpointMemory(0, 0, MemoryBreakpointComparison::MEMORY_BREAKPOINT_EQUAL, 0); -} - -void CDebugBreakpointsAddr::AddBreakpoint(CBreakpointAddr *breakpoint) -{ - // check if breakpoint is already in the map and remove it, can be with other addr so we can't use find - for (std::map::iterator it = breakpoints.begin(); it != breakpoints.end(); it++) - { - CBreakpointAddr *existingBreakpoint = it->second; - - if (existingBreakpoint == breakpoint) - { - breakpoints.erase(it); - break; - } - } - - // check if there's a breakpoint with the same address and delete it (we are replacing it) - std::map::iterator it = breakpoints.find(breakpoint->addr); - if (it != breakpoints.end()) - { - CBreakpointAddr *existingBreakpoint = it->second; - breakpoints.erase(it); - delete existingBreakpoint; - } - - // add a breakpoint - breakpoints[breakpoint->addr] = breakpoint; -} - -CBreakpointAddr *CDebugBreakpointsAddr::GetBreakpoint(int addr) -{ - std::map::iterator it = breakpoints.find(addr); - if (it == breakpoints.end()) - return NULL; - - return it->second; -} - -void CDebugBreakpointsAddr::DeleteBreakpoint(int addr) -{ - std::map::iterator it = breakpoints.find(addr); - if (it != breakpoints.end()) - { - CBreakpointAddr *breakpoint = it->second; - breakpoints.erase(it); - delete breakpoint; - } -} - -void CDebugBreakpointsAddr::DeleteBreakpoint(CBreakpointAddr *breakpoint) -{ - this->DeleteBreakpoint(breakpoint->addr); -} - -void CDebugBreakpointsAddr::RemoveBreakpoint(CBreakpointAddr *breakpoint) -{ - std::map::iterator it = breakpoints.find(breakpoint->addr); - if (it != breakpoints.end()) - { - breakpoints.erase(it); - } - - UpdateRenderBreakpoints(); -} - - -// TODO: create a condition parser (tree for condition) and parse the condition text -CBreakpointAddr *CDebugBreakpointsAddr::EvaluateBreakpoint(int addr) -{ - std::map::iterator it = breakpoints.find(addr); - if (it != breakpoints.end()) - { - CBreakpointAddr *breakpoint = it->second; - if (breakpoint->isActive == false) - return NULL; - - return breakpoint; - } - - return NULL; -} - -CBreakpointMemory *CDebugBreakpointsMemory::EvaluateBreakpoint(int addr, int value, u32 memoryAccess) -{ - std::map::iterator it = breakpoints.find(addr); - if (it != breakpoints.end()) - { - CBreakpointMemory *memoryBreakpoint = (CBreakpointMemory *)it->second; - if (memoryBreakpoint->isActive == false) - return NULL; - - // check memory access (read/write) - if (!IS_SET(memoryBreakpoint->memoryAccess, memoryAccess)) - { - return NULL; - } - - if (memoryBreakpoint->comparison == MemoryBreakpointComparison::MEMORY_BREAKPOINT_EQUAL) - { - if (value == memoryBreakpoint->value) - { - return memoryBreakpoint; - } - } - else if (memoryBreakpoint->comparison == MemoryBreakpointComparison::MEMORY_BREAKPOINT_NOT_EQUAL) - { - if (value != memoryBreakpoint->value) - { - return memoryBreakpoint; - } - } - else if (memoryBreakpoint->comparison == MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS) - { - if (value < memoryBreakpoint->value) - { - return memoryBreakpoint; - } - } - else if (memoryBreakpoint->comparison == MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL) - { - if (value <= memoryBreakpoint->value) - { - return memoryBreakpoint; - } - } - else if (memoryBreakpoint->comparison == MemoryBreakpointComparison::MEMORY_BREAKPOINT_GREATER) - { - if (value > memoryBreakpoint->value) - { - return memoryBreakpoint; - } - } - else if (memoryBreakpoint->comparison == MemoryBreakpointComparison::MEMORY_BREAKPOINT_GREATER_OR_EQUAL) - { - if (value >= memoryBreakpoint->value) - { - return memoryBreakpoint; - } - } - } - - return NULL; -} - -CDebugBreakpointsAddr::~CDebugBreakpointsAddr() -{ - ClearBreakpoints(); -} - -CDebugBreakpointsMemory::~CDebugBreakpointsMemory() -{ - ClearBreakpoints(); -} - -// -bool CDebugBreakpointsAddr::ComboFilterShouldOpenPopupCallback(const char *label, char *buffer, int bufferlen, - const char **hints, int num_hints, ImGui::ComboFilterState *s) -{ - // do not need to open combo popup when number is hex - if (FUN_IsHexNumber(buffer)) - { - return false; - } - - if (hints == NULL) - { - return false; - } - - if (num_hints == 0) - { - return false; - } - - return (buffer[0] != 0) && strcmp(buffer, hints[s->activeIdx]); -} - -void CDebugBreakpointsAddr::RenderImGui() -{ -// LOGD("CDebugBreakpointsAddr::RenderImGui"); - - char *buf = SYS_GetCharBuf(); - - ImVec4 colorNotActive(0.5, 0.5, 0.5, 1); - ImVec4 colorActive(1.0, 1.0, 1.0, 1); - - symbols->LockMutex(); - - CBreakpointAddr *deleteBreakpoint = NULL; - - sprintf(buf, "##BreakpointsAddrTable_%s", symbols->dataAdapter->adapterID); - - // active | address | symbol | delete - if (ImGui::BeginTable(buf, 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Borders)) - { - u32 i = 0; - -// ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(0.7f, 0.7f, 0.7f, 0.65f))); - - ImGui::TableNextColumn(); - ImGui::Text("Active"); - ImGui::TableNextColumn(); - ImGui::Text("Address"); - ImGui::TableNextColumn(); - ImGui::Text("Label"); - ImGui::TableNextColumn(); - ImGui::Text(""); - -// ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, 0); - - for (std::map::iterator it = breakpoints.begin(); it != breakpoints.end(); it++) - { - CBreakpointAddr *bp = it->second; - - sprintf(buf, "##chkBoxAddr%x%d", this, i); - - ImGui::TableNextColumn(); - if (ImGui::Checkbox(buf, &bp->isActive)) - { - symbols->UpdateRenderBreakpoints(); - } - - ImGui::TableNextColumn(); - ImVec4 color = bp->isActive ? colorActive : colorNotActive; - - ImGui::TextColored(color, addressFormatStr, bp->addr); - - ImGui::TableNextColumn(); - CDebugSymbolsCodeLabel *label = NULL; - if (symbols->currentSegment) - { - label = symbols->currentSegment->FindLabel(bp->addr); - } - - ImGui::TextColored(color, label ? label->GetLabelText() : ""); - - ImGui::TableNextColumn(); - sprintf(buf, "X##%x%d", this, i); - if (ImGui::Button(buf)) - { - // delete breakpoint - deleteBreakpoint = bp; - } - - i++; - } - - ImGui::EndTable(); - } - - if (deleteBreakpoint) - { - DeleteBreakpoint(deleteBreakpoint); - symbols->UpdateRenderBreakpoints(); - } - - - /// - - // shold we evaluate Enter press as adding the breakpoint or closing the combo? - bool skipClosePopupByEnterPressInThisFrame = false; - - if (ImGui::Button("+") || (ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))) - { - ImGui::OpenPopup("addAddrBreakpointPopup"); - - addBreakpointPopupAddr = 0; - addBreakpointPopupSymbol[0] = '\0'; - comboFilterTextBuf[0] = 0; - - imGuiOpenPopupFrame = 0; - skipClosePopupByEnterPressInThisFrame = true; - } - - if (ImGui::BeginPopup("addAddrBreakpointPopup")) - { - ImGui::Text(addBreakpointPopupHeadlineStr); -// ImGui::SameLine(); -// ImGui::Text("Address: %04x", ) - ImGui::Separator(); - - if (imGuiOpenPopupFrame < 2) - { - ImGui::SetKeyboardFocusHere(); - imGuiOpenPopupFrame++; - } - - sprintf(buf, "##addPCBreakpointPopupAddress_%s", symbols->dataAdapter->adapterID); - - bool buttonAddClicked = false; - if (symbols->currentSegment) - { - const char **hints = symbols->currentSegment->codeLabelsArray; - int numHints = symbols->currentSegment->numCodeLabelsInArray; - - // https://github.com/ocornut/imgui/issues/1658 | IM_ARRAYSIZE(hints) - if( ComboFilter(buf, comboFilterTextBuf, IM_ARRAYSIZE(comboFilterTextBuf), hints, numHints, comboFilterState, this) ) - { - LOGD("SELECTED %d comboTextBuf='%s'", comboFilterState.activeIdx, comboFilterTextBuf); - skipClosePopupByEnterPressInThisFrame = false; //true; - - // if that is not address then replace by selected symbol - if (FUN_IsHexNumber(comboFilterTextBuf)) - { - FUN_ToUpperCaseStr(comboFilterTextBuf); - addBreakpointPopupAddr = FUN_HexStrToValue(comboFilterTextBuf); - } - else if (hints != NULL && numHints > 0 && comboFilterState.activeIdx < numHints) - { - strcpy(comboFilterTextBuf, hints[comboFilterState.activeIdx]); - } - } - - ImGui::SameLine(); - if (ImGui::Button("Add")) - { - buttonAddClicked = true; - } - } - - bool finalizeAddingBreakpoint = buttonAddClicked - || (!skipClosePopupByEnterPressInThisFrame && ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter))); - -// if (ImGui::Button("Create PC Breakpoint")) -// { -// finalizeAddingBreakpoint = true; -// } - - if (finalizeAddingBreakpoint) - { - CDebugSymbolsCodeLabel *label = symbols->currentSegment->FindLabelByText(comboFilterTextBuf); - if (label) - { - addBreakpointPopupAddr = label->address; - } - else if (FUN_IsHexNumber(comboFilterTextBuf)) - { - FUN_ToUpperCaseStr(comboFilterTextBuf); - addBreakpointPopupAddr = FUN_HexStrToValue(comboFilterTextBuf); - } - else - { - char *buf = SYS_GetCharBuf(); - sprintf(buf, "Invalid address or symbol:\n%s", comboFilterTextBuf); - guiMain->ShowMessageBox("Can't add breakpoint", buf); - SYS_ReleaseCharBuf(buf); - addBreakpointPopupAddr = -1; - } - - if (addBreakpointPopupAddr >= 0) - { - addBreakpointPopupAddr = URANGE(minAddr, addBreakpointPopupAddr, maxAddr); - - CBreakpointAddr *breakpoint = new CBreakpointAddr(addBreakpointPopupAddr); - AddBreakpoint(breakpoint); - UpdateRenderBreakpoints(); - - ImGui::CloseCurrentPopup(); - } - } - - //// - - ImGui::EndPopup(); - } - - symbols->UnlockMutex(); - - SYS_ReleaseCharBuf(buf); -} - -void CDebugBreakpointsAddr::UpdateRenderBreakpoints() -{ - renderBreakpointsMutex->Lock(); - symbols->LockMutex(); - - renderBreakpoints.clear(); - for (std::map::iterator it = breakpoints.begin(); - it != breakpoints.end(); it++) - { - CBreakpointAddr *breakpoint = it->second; - renderBreakpoints[breakpoint->addr] = breakpoint; - } - - symbols->UnlockMutex(); - this->renderBreakpointsMutex->Unlock(); -} - -void CDebugBreakpointsMemory::RenderImGui() -{ -// LOGD("CDebugBreakpointsMemory::RenderImGui"); - - char *buf = SYS_GetCharBuf(); - - ImVec4 colorNotActive(0.5, 0.5, 0.5, 1); - ImVec4 colorActive(1.0, 1.0, 1.0, 1); - - sprintf(buf, "##BreakpointsMemoryTable_%s", symbols->dataAdapter->adapterID); - - symbols->LockMutex(); - - CBreakpointAddr *deleteBreakpoint = NULL; - - // active | address | <= | FF | symbol | delete - if (ImGui::BeginTable(buf, 6, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders)) //| ImGuiTableFlags_Sortable TODO - { - u32 i = 0; - -// ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(0.7f, 0.7f, 0.7f, 0.65f))); - - ImGui::TableNextColumn(); - ImGui::Text("Active"); - ImGui::TableNextColumn(); - ImGui::Text("Address"); - ImGui::TableNextColumn(); - ImGui::Text("Comparison"); - ImGui::TableNextColumn(); - ImGui::Text("Value"); - ImGui::TableNextColumn(); - ImGui::Text("Label"); - ImGui::TableNextColumn(); - ImGui::Text(""); - -// ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, 0); - - for (std::map::iterator it = breakpoints.begin(); it != breakpoints.end(); it++) - { - CBreakpointMemory *bp = (CBreakpointMemory*)it->second; - - sprintf(buf, "##chkBoxMem%x%d", this, i); - - ImGui::TableNextColumn(); - if (ImGui::Checkbox(buf, &bp->isActive)) - { - // we do not need to update anything - } - - ImGui::TableNextColumn(); - ImVec4 color = bp->isActive ? colorActive : colorNotActive; - ImGui::TextColored(color, addressFormatStr, bp->addr); - - ImGui::TableNextColumn(); - const char *comparisonStr = MemoryComparisonToStr(bp->comparison); - ImGui::TextColored(color, comparisonStr, bp->addr); - - ImGui::TableNextColumn(); - ImGui::TextColored(color, "%02X", bp->value); - - ImGui::TableNextColumn(); - CDebugSymbolsCodeLabel *label = NULL; - if (symbols->currentSegment) - { - label = symbols->currentSegment->FindLabel(bp->addr); - } - ImGui::TextColored(color, label ? label->GetLabelText() : ""); - - ImGui::TableNextColumn(); - sprintf(buf, "X##%x%d", this, i); - if (ImGui::Button(buf)) - { - // delete breakpoint - deleteBreakpoint = bp; - } - - i++; - } - - ImGui::EndTable(); - } - - if (deleteBreakpoint) - { - DeleteBreakpoint(deleteBreakpoint); - symbols->UpdateRenderBreakpoints(); - } - - // shold we evaluate Enter press as adding the breakpoint or closing the combo? - bool skipClosePopupByEnterPressInThisFrame = false; - - if (ImGui::Button("+") || (ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))) - { - ImGui::OpenPopup("addMemBreakpointPopup"); - - addBreakpointPopupAddr = 0; - addBreakpointPopupSymbol[0] = '\0'; - addBreakpointPopupValue = 0xFF; - addBreakpointPopupComparisonMethod = MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL; - comboFilterTextBuf[0] = 0; //memcpy(buf, hints[0], strlen(hints[0]) + 1); - - imGuiOpenPopupFrame = 0; - skipClosePopupByEnterPressInThisFrame = true; - } - - if (ImGui::BeginPopup("addMemBreakpointPopup")) - { - ImGui::Text(addBreakpointPopupHeadlineStr); - ImGui::Separator(); - - if (imGuiOpenPopupFrame < 2) - { - ImGui::SetKeyboardFocusHere(); - imGuiOpenPopupFrame++; - } - - sprintf(buf, "##addMemBreakpointPopupAddress_%s", symbols->dataAdapter->adapterID); - - if (symbols->currentSegment) - { - const char **hints = symbols->currentSegment->codeLabelsArray; - int numHints = symbols->currentSegment->numCodeLabelsInArray; - - // https://github.com/ocornut/imgui/issues/1658 | IM_ARRAYSIZE(hints) - if( ComboFilter(buf, comboFilterTextBuf, IM_ARRAYSIZE(comboFilterTextBuf), hints, numHints, comboFilterState, this) ) - { - LOGD("SELECTED %d comboTextBuf='%s'", comboFilterState.activeIdx, comboFilterTextBuf); - skipClosePopupByEnterPressInThisFrame = true; - - // TODO: fix this logic, we need to first check if label exists, if yes then use label first even if label is some hexcode string - - // if that is not address then replace by selected symbol - if (FUN_IsHexNumber(comboFilterTextBuf)) - { - FUN_ToUpperCaseStr(comboFilterTextBuf); - addBreakpointPopupAddr = FUN_HexStrToValue(comboFilterTextBuf); - } - else if (hints != NULL && numHints > 0 && comboFilterState.activeIdx < numHints) - { - strcpy(comboFilterTextBuf, hints[comboFilterState.activeIdx]); - } - } - } - - ImGui::SameLine(); - - // - const char *selectedComparisonStr = MemoryComparisonToStr((MemoryBreakpointComparison)addBreakpointPopupComparisonMethod); - - sprintf(buf, "##addMemBreakpointPopupComboComparison%x", this); - if (ImGui::BeginCombo(buf, selectedComparisonStr)) - { - skipClosePopupByEnterPressInThisFrame = true; - for (int n = 0; n < MEMORY_BREAKPOINT_ARRAY_SIZE; n++) - { - bool is_selected = (addBreakpointPopupComparisonMethod == n); - if (ImGui::Selectable(comparisonMethodsStr[n], is_selected)) - { - addBreakpointPopupComparisonMethod = n; - } - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - - ImGui::SameLine(); - - sprintf(buf, "##addMemBreakpointPopupValue%x", this); - ImGui::InputScalar(buf, ImGuiDataType_::ImGuiDataType_U8, &addBreakpointPopupValue, NULL, NULL, "%02X", - ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); - -// ImGui::SameLine(); - - bool finalizeAddingBreakpoint = !skipClosePopupByEnterPressInThisFrame && ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)); - - if (ImGui::Button("Create Breakpoint")) - { - finalizeAddingBreakpoint = true; - } - - if (finalizeAddingBreakpoint) - { - CDebugSymbolsCodeLabel *label = symbols->currentSegment->FindLabelByText(comboFilterTextBuf); - if (label) - { - addBreakpointPopupAddr = label->address; - } - else if (FUN_IsHexNumber(comboFilterTextBuf)) - { - FUN_ToUpperCaseStr(comboFilterTextBuf); - addBreakpointPopupAddr = FUN_HexStrToValue(comboFilterTextBuf); - } - else - { - char *buf = SYS_GetCharBuf(); - sprintf(buf, "Invalid address or symbol:\n%s", comboFilterTextBuf); - guiMain->ShowMessageBox("Can't add breakpoint", buf); - SYS_ReleaseCharBuf(buf); - addBreakpointPopupAddr = -1; - } - - if (addBreakpointPopupAddr >= 0) - { - addBreakpointPopupAddr = URANGE(minAddr, addBreakpointPopupAddr, maxAddr); - addBreakpointPopupValue = URANGE(0, addBreakpointPopupValue, 0xFF); - - CBreakpointMemory *breakpoint = new CBreakpointMemory(addBreakpointPopupAddr, MEMORY_BREAKPOINT_ACCESS_WRITE, - (MemoryBreakpointComparison)addBreakpointPopupComparisonMethod, - addBreakpointPopupValue); - AddBreakpoint(breakpoint); - UpdateRenderBreakpoints(); - - ImGui::CloseCurrentPopup(); - } - } - - ImGui::EndPopup(); - } - - symbols->UnlockMutex(); - - SYS_ReleaseCharBuf(buf); -} - -const char *CDebugBreakpointsMemory::MemoryComparisonToStr(MemoryBreakpointComparison comparison) -{ - switch(comparison) - { - case MemoryBreakpointComparison::MEMORY_BREAKPOINT_EQUAL: - return "=="; - case MemoryBreakpointComparison::MEMORY_BREAKPOINT_NOT_EQUAL: - return "!="; - case MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS: - return "<"; - case MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL: - return "<="; - case MemoryBreakpointComparison::MEMORY_BREAKPOINT_GREATER: - return ">"; - case MemoryBreakpointComparison::MEMORY_BREAKPOINT_GREATER_OR_EQUAL: - return ">="; - default: - return "???"; - } -} diff --git a/src/DebugInterface/CDebugBreakpoints.h b/src/DebugInterface/CDebugBreakpoints.h index 9a9b76c..01101f9 100644 --- a/src/DebugInterface/CDebugBreakpoints.h +++ b/src/DebugInterface/CDebugBreakpoints.h @@ -1,149 +1,11 @@ #ifndef _CDEBUGGERBREAKPOINTS_H_ #define _CDEBUGGERBREAKPOINTS_H_ -#include "SYS_Defs.h" -#include "DebuggerDefs.h" -#include "GUI_Main.h" -#include "CDebugSymbols.h" -#include "imguiComboFilter.h" -#include "hjson.h" -#include - -#define BREAKPOINT_TYPE_CPU_PC 0 -#define BREAKPOINT_TYPE_MEMORY 1 -#define NUM_DEFAULT_BREAKPOINT_TYPES 2 - -#define ADDR_BREAKPOINT_ACTION_STOP BV01 -#define ADDR_BREAKPOINT_ACTION_SET_BACKGROUND BV02 -#define ADDR_BREAKPOINT_ACTION_STOP_ON_RASTER BV03 - -#define MEMORY_BREAKPOINT_ACCESS_WRITE BV01 -#define MEMORY_BREAKPOINT_ACCESS_READ BV02 - - -class CDebugSymbols; - -// generic breakpoint -class CDebugBreakpoint -{ -public: - CDebugBreakpoint(); - virtual ~CDebugBreakpoint(); - - virtual void Serialize(Hjson::Value hjsonRoot); - virtual void Deserialize(Hjson::Value hjsonRoot); -}; - -class CBreakpointAddr : public CDebugBreakpoint -{ -public: - CBreakpointAddr(int addr); - virtual ~CBreakpointAddr(); - bool isActive; - - int addr; - u32 actions; - u8 data; - - virtual void Serialize(Hjson::Value hjsonRoot); - virtual void Deserialize(Hjson::Value hjsonRoot); -}; - -// TODO: refactor this to 2 breakpoints (make list?) -class CBreakpointMemory : public CBreakpointAddr -{ -public: - CBreakpointMemory(int addr, - u32 memoryAccess, MemoryBreakpointComparison comparison, int value); - - u32 memoryAccess; - int value; - MemoryBreakpointComparison comparison; - - virtual void Serialize(Hjson::Value hjsonRoot); - virtual void Deserialize(Hjson::Value hjsonRoot); -}; - -class CDebugBreakpointsAddr : public ImGui::ComboFilterCallback -{ -public: - CDebugBreakpointsAddr(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr); - ~CDebugBreakpointsAddr(); - - int breakpointsType; - const char *breakpointsTypeStr; - - const char *addressFormatStr; - int minAddr, maxAddr; - const char *addBreakpointPopupHeadlineStr; - const char *addBreakpointPopupAddrStr; - ImGuiInputTextFlags addBreakpointPopupAddrInputFlags; - - CDebugSymbolsSegment *segment; - CDebugSymbols *symbols; - - std::map breakpoints; - - // copy of the breakpoints used for rendering that is not synchronised, to offload mutex switching for emulators during renderings - CSlrMutex *renderBreakpointsMutex; - std::map renderBreakpoints; - - virtual void UpdateRenderBreakpoints(); - - // factory - virtual CDebugBreakpoint *CreateEmptyBreakpoint(); - - virtual void AddBreakpoint(CBreakpointAddr *addrBreakpoint); - CBreakpointAddr *GetBreakpoint(int addr); - virtual void RemoveBreakpoint(CBreakpointAddr *breakpoint); - virtual void DeleteBreakpoint(CBreakpointAddr *addrBreakpoint); - virtual void DeleteBreakpoint(int addr); - - virtual CBreakpointAddr *EvaluateBreakpoint(int addr); - - virtual void ClearBreakpoints(); - virtual void RenderImGui(); - - // for stepping over JSR, set temporary breakpoint after the JSR and run code - int temporaryBreakpointPC; - virtual int GetTemporaryBreakpointPC(); - virtual void SetTemporaryBreakpointPC(int address); - - - virtual bool ComboFilterShouldOpenPopupCallback(const char *label, char *buffer, int bufferlen, - const char **hints, int num_hints, ImGui::ComboFilterState *s); - - virtual void Serialize(Hjson::Value hjsonBreakpoints); - virtual void Deserialize(Hjson::Value hjsonBreakpoints); - -protected: - int addBreakpointPopupAddr; - char addBreakpointPopupSymbol[256]; - int imGuiColumnsWidthWorkaroundFrame; - int imGuiOpenPopupFrame; - ImGui::ComboFilterState comboFilterState = {0, false}; - char comboFilterTextBuf[MAX_LABEL_TEXT_BUFFER_SIZE]; -}; - -class CDebugBreakpointsMemory : public CDebugBreakpointsAddr -{ -public: - CDebugBreakpointsMemory(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr); - ~CDebugBreakpointsMemory(); - - // factory - virtual CDebugBreakpoint *CreateEmptyBreakpoint(); - - virtual CBreakpointMemory *EvaluateBreakpoint(int addr, int value, u32 memoryAccess); - - virtual void RenderImGui(); - - const char *comparisonMethodsStr[MEMORY_BREAKPOINT_ARRAY_SIZE] = { "==", "!=", "<", "<=", ">", ">=" }; - static const char *MemoryComparisonToStr(MemoryBreakpointComparison comparison); - -protected: - int addBreakpointPopupValue; - int addBreakpointPopupComparisonMethod; -}; +#include "CDebugBreakpoint.h" +#include "CDebugBreakpointAddr.h" +#include "CDebugBreakpointData.h" +#include "CDebugBreakpointRasterLine.h" +#include "CDebugBreakpointsAddr.h" +#include "CDebugBreakpointsData.h" #endif diff --git a/src/DebugInterface/CDebugInterface.cpp b/src/DebugInterface/CDebugInterface.cpp index 84d5a27..ec87db1 100644 --- a/src/DebugInterface/CDebugInterface.cpp +++ b/src/DebugInterface/CDebugInterface.cpp @@ -9,6 +9,7 @@ #include "CDebuggerEmulatorPlugin.h" #include "CViewDisassembly.h" #include "CDebugEventsHistory.h" +#include "CDebuggerServerApi.h" CDebugInterface::CDebugInterface(CViewC64 *viewC64) { @@ -17,6 +18,7 @@ CDebugInterface::CDebugInterface(CViewC64 *viewC64) snapshotsManager = NULL; symbols = NULL; codeMonitorCallback = NULL; + debuggerServerApi = NULL; isDebugOn = true; @@ -33,6 +35,7 @@ CDebugInterface::CDebugInterface(CViewC64 *viewC64) emulationFrameCounter = 0; viewScreen = NULL; + viewDisassembly = NULL; this->debugMode = DEBUGGER_MODE_RUNNING; } @@ -61,6 +64,11 @@ const char *CDebugInterface::GetPlatformNameString() return NULL; } +const char *CDebugInterface::GetPlatformNameEndpointString() +{ + return NULL; +} + float CDebugInterface::GetEmulationFPS() { return -1; @@ -155,7 +163,7 @@ void CDebugInterface::CreateScreenData() void CDebugInterface::RefreshScreenNoCallback() { - SYS_FatalExit("CDebugInterface::RefreshScreenNoCallback"); + LOGTODO("CDebugInterface::RefreshScreenNoCallback"); } @@ -180,10 +188,16 @@ CImageData *CDebugInterface::GetScreenImageData() CDebugDataAdapter *CDebugInterface::GetDataAdapter() { - SYS_FatalExit("CDebugInterface::GetDataAdapter"); + LOGTODO("CDebugInterface::GetDataAdapter"); return NULL; } +CDebugDataAdapter *CDebugInterface::GetDataAdapterDirectRam() +{ + LOGTODO("CDebugInterface::GetDataAdapterDirectRam"); + return GetDataAdapter(); +} + void CDebugInterface::ClearDebugMarkers() { LOGError("CDebugInterface::ClearDebugMarkers: not implemented for emulator %s", GetEmulatorVersionString()); @@ -196,15 +210,20 @@ void CDebugInterface::ClearHistory() symbols->debugEventsHistory->DeleteAllEvents(); } +void CDebugInterface::DetachEverything() +{ + LOGTODO("CDebugInterface::DetachEverything"); +} + bool CDebugInterface::LoadExecutable(char *fullFilePath) { - SYS_FatalExit("CDebugInterface::LoadExecutable"); + LOGTODO("CDebugInterface::LoadExecutable"); return false; } bool CDebugInterface::MountDisk(char *fullFilePath, int diskNo, bool readOnly) { - SYS_FatalExit("CDebugInterface::MountDisk"); + LOGTODO("CDebugInterface::MountDisk"); return false; } @@ -239,13 +258,13 @@ bool CDebugInterface::SaveDiskDataSnapshotSynced(CByteBuffer *byteBuffer) bool CDebugInterface::IsDriveDirtyForSnapshot() { - SYS_FatalExit("CDebugInterface::IsDriveDirtyForSnapshot"); + LOGTODO("CDebugInterface::IsDriveDirtyForSnapshot"); return false; } void CDebugInterface::ClearDriveDirtyForSnapshotFlag() { - SYS_FatalExit("CDebugInterface::ClearDriveDirtyForSnapshotFlag"); + LOGTODO("CDebugInterface::ClearDriveDirtyForSnapshotFlag"); } int CDebugInterface::GetScreenSizeX() @@ -330,18 +349,18 @@ void ReplayInputEventsFromSnapshotsManager(CByteBuffer *byteBuffer); // state int CDebugInterface::GetCpuPC() { - SYS_FatalExit("CDebugInterface::GetCpuPC"); + LOGTODO("CDebugInterface::GetCpuPC"); return -1; } void CDebugInterface::GetWholeMemoryMap(uint8 *buffer) { - SYS_FatalExit("CDebugInterface::GetWholeMemoryMap"); + LOGTODO("CDebugInterface::GetWholeMemoryMap"); } void CDebugInterface::GetWholeMemoryMapFromRam(uint8 *buffer) { - SYS_FatalExit("CDebugInterface::GetWholeMemoryMap"); + LOGTODO("CDebugInterface::GetWholeMemoryMap"); } // @@ -395,14 +414,14 @@ uint8 CDebugInterface::GetDebugMode() return this->debugMode; } -void CDebugInterface::Reset() +void CDebugInterface::ResetSoft() { - SYS_FatalExit("CDebugInterface::Reset"); + LOGTODO("CDebugInterface::ResetSoft"); } -void CDebugInterface::HardReset() +void CDebugInterface::ResetHard() { - SYS_FatalExit("CDebugInterface::HardReset"); + LOGTODO("CDebugInterface::HardReset"); } void CDebugInterface::SetDebugOn(bool debugOn) @@ -430,13 +449,13 @@ void CDebugInterface::SetSettingIsWarpSpeed(bool isWarpSpeed) // make jmp without resetting CPU depending on dataAdapter void CDebugInterface::MakeJmpNoReset(CDataAdapter *dataAdapter, uint16 addr) { - SYS_FatalExit("CDebugInterface::MakeJmpNoReset"); + LOGTODO("CDebugInterface::MakeJmpNoReset"); } // make jmp and reset CPU void CDebugInterface::MakeJmpAndReset(uint16 addr) { - SYS_FatalExit("CDebugInterface::MakeJmpAndReset"); + LOGTODO("CDebugInterface::MakeJmpAndReset"); } void CDebugInterface::ClearTemporaryBreakpoint() @@ -461,6 +480,14 @@ void CDebugInterface::StepOneCycle() this->SetDebugMode(DEBUGGER_MODE_RUN_ONE_CYCLE); } +void CDebugInterface::StepOverSubroutine() +{ + if (viewDisassembly) + { + viewDisassembly->StepOverJsr(); + } +} + void CDebugInterface::RunContinueEmulation() { this->ClearTemporaryBreakpoint(); @@ -575,7 +602,7 @@ void CDebugInterface::AddMenuItem(CDebugInterfaceMenuItem *menuItem) } // -CGuiView *CDebugInterface::GetViewScreen() +CViewEmulatorScreen *CDebugInterface::GetViewScreen() { return viewScreen; } @@ -595,6 +622,27 @@ CViewTimeline *CDebugInterface::GetViewTimeline() return this->snapshotsManager->viewTimeline; } +CViewDisassembly *CDebugInterface::GetViewDisassembly() +{ + return viewDisassembly; +} + +CDebuggerApi *CDebugInterface::GetDebuggerApi() +{ + LOGError("CDebugInterface::GetDebuggerApi: not implemeted"); + return NULL; +} + +// singleton (override factory) +CDebuggerServerApi *CDebugInterface::GetDebuggerServerApi() +{ + if (debuggerServerApi) + return debuggerServerApi; + + debuggerServerApi = new CDebuggerServerApi(this); + return debuggerServerApi; +} + // TODO: ADD "#define DEBUGMUTEX" and push/pull names of locks here, list to be displayed when this locks here again void CDebugInterface::LockMutex() { diff --git a/src/DebugInterface/CDebugInterface.h b/src/DebugInterface/CDebugInterface.h index e9a3200..4d25f67 100644 --- a/src/DebugInterface/CDebugInterface.h +++ b/src/DebugInterface/CDebugInterface.h @@ -1,16 +1,23 @@ #ifndef _CDEBUGINTERFACE_H_ #define _CDEBUGINTERFACE_H_ -#include "CDebugBreakpoints.h" +#include "CDebugBreakpoint.h" +#include "CDebugBreakpointAddr.h" +#include "CDebugBreakpointData.h" +#include "CDebugBreakpointRasterLine.h" +#include "CDebugBreakpointsAddr.h" +#include "CDebugBreakpointsData.h" #include "CDebugDataAdapter.h" #include "CByteBuffer.h" #include "DebuggerDefs.h" #include "EmulatorsConfig.h" +#include "json.hpp" #include #include class CGuiView; + class CViewC64; class CSlrMutex; class CImageData; @@ -20,6 +27,7 @@ class CSnapshotsManager; class CDebugSymbols; class CDebugSymbolsSegment; +class CViewEmulatorScreen; class CViewDisassembly; class CViewBreakpoints; class CViewDataWatch; @@ -31,6 +39,9 @@ class CViewDataMap; class CViewTimeline; class CDebugEventsHistory; +class CDebuggerApi; +class CDebuggerServerApi; + class CDebugInterfaceCodeMonitorCallback { public: @@ -52,6 +63,7 @@ class CDebugInterface virtual int GetEmulatorType(); virtual CSlrString *GetEmulatorVersionString(); virtual const char *GetPlatformNameString(); + virtual const char *GetPlatformNameEndpointString(); virtual float GetEmulationFPS(); @@ -120,7 +132,6 @@ class CDebugInterface virtual void JoystickDown(int port, uint32 axis); virtual void JoystickUp(int port, uint32 axis); - // TODO: mouse virtual void MouseDown(float x, float y); virtual void MouseMove(float x, float y); virtual void MouseUp(float x, float y); @@ -141,9 +152,12 @@ class CDebugInterface virtual void PauseEmulationBlockedWait(); // - virtual void Reset(); - virtual void HardReset(); + virtual void ResetSoft(); + virtual void ResetHard(); + virtual void DetachEverything(); + + // virtual bool LoadExecutable(char *fullFilePath); virtual bool MountDisk(char *fullFilePath, int diskNo, bool readOnly); @@ -188,6 +202,8 @@ class CDebugInterface virtual void StepOverInstruction(); virtual void StepOneCycle(); + virtual void StepOverSubroutine(); + virtual void RunContinueEmulation(); // breakpoints @@ -196,7 +212,10 @@ class CDebugInterface virtual void SetDebugOn(bool debugOn); virtual CDebugDataAdapter *GetDataAdapter(); - + + // note this may fallback to default data adapter if not implemented + virtual CDebugDataAdapter *GetDataAdapterDirectRam(); + // view breakpoints virtual void UpdateRenderBreakpoints(); @@ -229,11 +248,20 @@ class CDebugInterface void RemovePlugin(CDebuggerEmulatorPlugin *plugin); // views - CGuiView *viewScreen; - virtual CGuiView *GetViewScreen(); + CViewEmulatorScreen *viewScreen; + virtual CViewEmulatorScreen *GetViewScreen(); std::vector viewsMemoryMap; virtual void AddViewMemoryMap(CViewDataMap *viewMemoryMap); virtual CViewTimeline *GetViewTimeline(); + CViewDisassembly *viewDisassembly; + virtual CViewDisassembly *GetViewDisassembly(); + + // plugin api + virtual CDebuggerApi *GetDebuggerApi(); + + // debugger server api + CDebuggerServerApi *debuggerServerApi; + virtual CDebuggerServerApi *GetDebuggerServerApi(); // CSlrMutex *breakpointsMutex; diff --git a/src/DebugInterface/CDebuggerApi.cpp b/src/DebugInterface/CDebuggerApi.cpp index bcc3a6a..2c304da 100644 --- a/src/DebugInterface/CDebuggerApi.cpp +++ b/src/DebugInterface/CDebuggerApi.cpp @@ -25,28 +25,23 @@ #include "CDebuggerApiNestopia.h" #include "CDebuggerApiAtari.h" -// factory +// static factory CDebuggerApi *CDebuggerApi::GetDebuggerApi(u8 emulatorType) { CDebugInterface *debugInterface = viewC64->GetDebugInterface(emulatorType); - - switch(emulatorType) + if (debugInterface) { - case EMULATOR_TYPE_C64_VICE: - return new CDebuggerApiVice(debugInterface); - case EMULATOR_TYPE_NESTOPIA: - return new CDebuggerApiNestopia(debugInterface); - case EMULATOR_TYPE_ATARI800: - return new CDebuggerApiAtari(debugInterface); + return debugInterface->GetDebuggerApi(); } - SYS_FatalExit("CDebuggerAPI::GetDebuggerApi: emulatorType=%d not supported", emulatorType); + + LOGError("CDebuggerAPI::GetDebuggerApi: emulatorType=%d not supported", emulatorType); return NULL; } CDebuggerApi::CDebuggerApi(CDebugInterface *debugInterface) { this->debugInterface = debugInterface; - this->byteBufferAssembleText = new CByteBuffer(); + byteBufferAssembleText = new CByteBuffer(); } CDebuggerApi::~CDebuggerApi() @@ -56,15 +51,46 @@ CDebuggerApi::~CDebuggerApi() void CDebuggerApi::PauseEmulation() { LOGD("CDebuggerApi::PauseEmulation"); - this->debugInterface->SetDebugMode(DEBUGGER_MODE_PAUSED); + debugInterface->SetDebugMode(DEBUGGER_MODE_PAUSED); } void CDebuggerApi::UnPauseEmulation() { LOGD("CDebuggerApi::UnPauseEmulation"); - this->debugInterface->SetDebugMode(DEBUGGER_MODE_RUNNING); + debugInterface->SetDebugMode(DEBUGGER_MODE_RUNNING); } +void CDebuggerApi::StepOneCycle() +{ + debugInterface->StepOneCycle(); +} + +void CDebuggerApi::StepOverInstruction() +{ + debugInterface->StepOverInstruction(); +} + +void CDebuggerApi::StepOverSubroutine() +{ + debugInterface->StepOverSubroutine(); +} + +u64 CDebuggerApi::GetMainCpuCycleCounter() +{ + return debugInterface->GetMainCpuCycleCounter(); +} + +u64 CDebuggerApi::GetMainCpuInstructionCycleCounter() +{ + return debugInterface->GetCurrentCpuInstructionCycleCounter(); +} + +unsigned int CDebuggerApi::GetEmulationFrameNumber() +{ + return debugInterface->GetEmulationFrameNumber(); +} + + void CDebuggerApi::StartThread(CSlrThread *run) { SYS_StartThread(run); @@ -168,9 +194,16 @@ long CDebuggerApi::GetCurrentFrameNumber() return debugInterface->GetEmulationFrameNumber(); } -void CDebuggerApi::ResetMachine() +void CDebuggerApi::ResetMachine(bool isHardReset) { - SYS_FatalExit("CDebuggerApi::ResetMachine: not implemented"); + if (isHardReset) + { + debugInterface->ResetHard(); + } + else + { + debugInterface->ResetSoft(); + } } void CDebuggerApi::MakeJmp(int addr) @@ -178,6 +211,16 @@ void CDebuggerApi::MakeJmp(int addr) SYS_FatalExit("CDebuggerApi::MakeJMP: not implemented"); } +CDataAdapter *CDebuggerApi::GetDataAdapterMemoryWithIO() +{ + return debugInterface->GetDataAdapter(); +} + +CDataAdapter *CDebuggerApi::GetDataAdapterMemoryDirectRAM() +{ + return debugInterface->GetDataAdapterDirectRam(); +} + void CDebuggerApi::SetByte(int addr, u8 v) { CDataAdapter *dataAdapter = debugInterface->GetDataAdapter(); @@ -238,7 +281,7 @@ void CDebuggerApi::ClearRam(int startAddr, int endAddr, u8 value) { for (int i = startAddr; i < endAddr; i++) { - this->SetByteToRam(i, value); + SetByteToRam(i, value); } } @@ -269,7 +312,7 @@ bool CDebuggerApi::Assemble64TassToRam(int *codeStartAddr, int *codeSize) bool CDebuggerApi::Assemble64TassToRam(int *codeStartAddr, int *codeSize, char *fileName, bool quiet) { - u8 *buf = this->Assemble64Tass(codeStartAddr, codeSize, fileName, quiet); + u8 *buf = Assemble64Tass(codeStartAddr, codeSize, fileName, quiet); if (buf == NULL) { @@ -282,7 +325,7 @@ bool CDebuggerApi::Assemble64TassToRam(int *codeStartAddr, int *codeSize, char * int addr = *codeStartAddr; for (int i = 0; i < *codeSize; i++) { - this->SetByteToRam(addr, buf[i]); + SetByteToRam(addr, buf[i]); addr++; } free(buf); @@ -319,7 +362,7 @@ void CDebuggerApi::Assemble64TassAddLine(const char *format, ...) u8 *CDebuggerApi::Assemble64Tass(int *codeStartAddr, int *codeSize) { - return this->Assemble64Tass(codeStartAddr, codeSize, NULL, false); + return Assemble64Tass(codeStartAddr, codeSize, NULL, false); } u8 *CDebuggerApi::Assemble64Tass(int *codeStartAddr, int *codeSize, const char *storeAsmFileName, bool quiet) @@ -366,6 +409,51 @@ int CDebuggerApi::Assemble(int addr, char *assembleText) return -1; } +// +CSlrString *CDebuggerApi::GetCurrentSegmentName() +{ + if (debugInterface->symbols->currentSegment == NULL) + return NULL; + return debugInterface->symbols->currentSegment->name; +} + +bool CDebuggerApi::SetCurrentSegment(CSlrString *segmentName) +{ + return debugInterface->symbols->SetSegment(segmentName); +} + +u64 CDebuggerApi::AddBreakpointPC(int addr) +{ + debugInterface->LockMutex(); + CDebugBreakpointAddr *breakpoint = debugInterface->viewDisassembly->AddPCBreakpoint(addr); + debugInterface->UnlockMutex(); + return breakpoint->breakpointId; +} + +u64 CDebuggerApi::RemoveBreakpointPC(int addr) +{ + debugInterface->LockMutex(); + u64 breakpointId = debugInterface->viewDisassembly->RemovePCBreakpoint(addr); + debugInterface->UnlockMutex(); + return breakpointId; +} + +u64 CDebuggerApi::AddBreakpointMemory(int address, u32 memoryAccess, DataBreakpointComparison comparison, int value) +{ + debugInterface->LockMutex(); + CDebugBreakpointData *breakpoint = debugInterface->symbols->currentSegment->AddBreakpointMemory(address, memoryAccess, comparison, value); + debugInterface->UnlockMutex(); + return breakpoint->breakpointId; +} + +u64 CDebuggerApi::RemoveBreakpointMemory(int address) +{ + debugInterface->LockMutex(); + u64 breakpointId = debugInterface->symbols->currentSegment->breakpointsData->DeleteBreakpoint(address); + debugInterface->UnlockMutex(); + return breakpointId; +} + void CDebuggerApi::AddWatch(CSlrString *segmentName, int address, CSlrString *watchName, uint8 representation, int numberOfValues) { if (debugInterface->symbols) @@ -410,7 +498,7 @@ void CDebuggerApi::AddWatch(int address, char *watchName, uint8 representation, void CDebuggerApi::AddWatch(int address, char *watchName) { - this->AddWatch(address, watchName, WATCH_REPRESENTATION_HEX_8, 1); + AddWatch(address, watchName, WATCH_REPRESENTATION_HEX_8, 1); } u8 *CDebuggerApi::ExomizerMemoryRaw(u16 fromAddr, u16 toAddr, int *compressedSize) @@ -418,19 +506,14 @@ u8 *CDebuggerApi::ExomizerMemoryRaw(u16 fromAddr, u16 toAddr, int *compressedSiz return C64ExomizeMemoryRaw(fromAddr, toAddr, compressedSize); } -// TODO: fixme! -void CDebuggerApi::SaveBinary(u16 fromAddr, u16 toAddr, char *filePath) +void CDebuggerApi::SaveBinary(int fromAddr, int toAddr, const char *filePath) { - // TODO: we can implement this generic via SetRam(... - SYS_FatalExit("CDebuggerApi::SaveBinary: not implemented"); + C64SaveMemory(fromAddr, toAddr, false, debugInterface->GetDataAdapterDirectRam(), filePath); } -// TODO: fixme! -int CDebuggerApi::LoadBinary(u16 fromAddr, char *filePath) +int CDebuggerApi::LoadBinary(int fromAddr, const char *filePath) { - // TODO: we can implement this generic via SetRam(... - SYS_FatalExit("CDebuggerApi::LoadBinary: not implemented"); - return -1; + return C64LoadMemory(fromAddr, debugInterface->GetDataAdapterDirectRam(), filePath); } void CDebuggerApi::LoadSnapshot(const char *fileName) @@ -444,6 +527,31 @@ void CDebuggerApi::ResetEmulationCounters() debugInterface->ResetEmulationFrameCounter(); } +void CDebuggerApi::SetWarpSpeed(bool isWarpSpeed) +{ + debugInterface->SetSettingIsWarpSpeed(isWarpSpeed); +} + +bool CDebuggerApi::KeyboardDown(u32 mtKeyCode) +{ + return debugInterface->KeyboardDown(mtKeyCode); +} + +bool CDebuggerApi::KeyboardUp(u32 mtKeyCode) +{ + return debugInterface->KeyboardUp(mtKeyCode); +} + +void CDebuggerApi::JoystickDown(int port, u32 axis) +{ + debugInterface->JoystickDown(port, axis); +} + +void CDebuggerApi::JoystickUp(int port, u32 axis) +{ + debugInterface->JoystickUp(port, axis); +} + void CDebuggerApi::ShowMessage(const char *text) { viewC64->ShowMessage((char*)text); @@ -463,3 +571,61 @@ void CDebuggerApi::AddView(CGuiView *view) guiMain->UnlockMutex(); } +nlohmann::json CDebuggerApi::GetCpuStatusJson() +{ + nlohmann::json empty; + return empty; +} + +u32 CDebuggerApi::JoypadAxisNameToAxisCode(std::string axisName) +{ + if (axisName == "select") + { + return JOYPAD_SELECT; + } + if (axisName == "start") + { + return JOYPAD_START; + } + if (axisName == "fireB") + { + return JOYPAD_FIRE_B; + } + if (axisName == "fire") + { + return JOYPAD_FIRE; + } + if (axisName == "e" || axisName == "east") + { + return JOYPAD_E; + } + if (axisName == "w" || axisName == "west") + { + return JOYPAD_W; + } + if (axisName == "s" || axisName == "south") + { + return JOYPAD_S; + } + if (axisName == "n" || axisName == "north") + { + return JOYPAD_N; + } + if (axisName == "sw" || axisName == "southwest") + { + return JOYPAD_SW; + } + if (axisName == "se" || axisName == "southeast") + { + return JOYPAD_SE; + } + if (axisName == "nw" || axisName == "northwest") + { + return JOYPAD_NW; + } + if (axisName == "ne" || axisName == "northeast") + { + return JOYPAD_NE; + } + return JOYPAD_IDLE; +} diff --git a/src/DebugInterface/CDebuggerApi.h b/src/DebugInterface/CDebuggerApi.h index 9268fee..087118a 100644 --- a/src/DebugInterface/CDebuggerApi.h +++ b/src/DebugInterface/CDebuggerApi.h @@ -21,24 +21,32 @@ class CDebuggerApi static CDebuggerApi *GetDebuggerApi(u8 emulatorType); - virtual void ResetMachine(); + virtual void ResetMachine(bool isHardReset); virtual void PauseEmulation(); virtual void UnPauseEmulation(); + virtual void StepOneCycle(); + virtual void StepOverInstruction(); + virtual void StepOverSubroutine(); // step over JSR + + virtual u64 GetMainCpuCycleCounter(); + virtual u64 GetMainCpuInstructionCycleCounter(); + virtual unsigned int GetEmulationFrameNumber(); + virtual void CreateNewPicture(u8 mode, u8 backgroundColor); virtual void StartThread(CSlrThread *run); - + // rgb reference image in vic editor virtual void ClearReferenceImage(); virtual void LoadReferenceImage(char *filePath); virtual void LoadReferenceImage(CImageData *imageData); virtual void SetReferenceImageLayerVisible(bool isVisible); CImageData *GetReferenceImage(); - + // emulated computer screen virtual void ClearScreen(); virtual void ZoomDisplay(float newScale); - + // load from png file virtual bool ConvertImageToScreen(char *filePath); virtual bool ConvertImageToScreen(CImageData *imageData); @@ -46,23 +54,27 @@ class CDebuggerApi // always returns 320x200 for C64: virtual CImageData *GetScreenImageWithoutBorders(); - + // virtual u8 PaintPixel(int x, int y, u8 color); virtual u8 PaintReferenceImagePixel(int x, int y, u8 color); virtual u8 PaintReferenceImagePixel(int x, int y, u8 r, u8 g, u8 b, u8 a); - // + // data adapters + CDataAdapter *GetDataAdapterMemoryWithIO(); + CDataAdapter *GetDataAdapterMemoryDirectRAM(); + + // direct access virtual void SetByte(int addr, u8 v); /// NOTE: this is generic poke, peek, in most cases including I/O, should not be used virtual void SetByteWithIo(int addr, u8 v); virtual void SetByteToRam(int addr, u8 v); virtual u8 GetByte(int addr); virtual u8 GetByteWithIo(int addr); virtual u8 GetByteFromRam(int addr); - + virtual void SetWord(int addr, u16 v); virtual void MakeJmp(int addr); - + // virtual void DetachEverything(); virtual void ClearRam(int startAddr, int endAddr, u8 value); @@ -78,24 +90,34 @@ class CDebuggerApi virtual bool Assemble64TassToRam(int *codeStartAddr, int *codeSize); virtual bool Assemble64TassToRam(int *codeStartAddr, int *codeSize, char *storeAsmFileName, bool quiet); virtual void Assemble64TassAddLine(const char *format, ...); - + // virtual void AddWatch(CSlrString *segmentName, int address, CSlrString *watchName, uint8 representation, int numberOfValues); virtual void AddWatch(int address, char *watchName, uint8 representation, int numberOfValues); virtual void AddWatch(int address, char *watchName); // - virtual void SaveBinary(u16 fromAddr, u16 toAddr, char *fileName); - virtual int LoadBinary(u16 fromAddr, char *filePath); + virtual void SaveBinary(int fromAddr, int toAddr, const char *fileName); + virtual int LoadBinary(int fromAddr, const char *filePath); // virtual void LoadSnapshot(const char *fileName); - + virtual u8 *ExomizerMemoryRaw(u16 fromAddr, u16 toAddr, int *compressedSize); // virtual void ResetEmulationCounters(); + // + virtual void SetWarpSpeed(bool isWarpSpeed); + + // input + virtual bool KeyboardDown(u32 mtKeyCode); + virtual bool KeyboardUp(u32 mtKeyCode); + + virtual void JoystickDown(int port, u32 axis); + virtual void JoystickUp(int port, u32 axis); + // shortcuts to the Engine virtual void ShowMessage(const char *text); virtual void BlitText(const char *text, float posX, float posY, float fontSize); @@ -103,8 +125,23 @@ class CDebuggerApi virtual long GetCurrentTimeInMilliseconds(); virtual long GetCurrentFrameNumber(); + static u32 JoypadAxisNameToAxisCode(std::string axisName); + + // segments + CSlrString *GetCurrentSegmentName(); + bool SetCurrentSegment(CSlrString *segmentName); + + // breakpoints + u64 AddBreakpointPC(int addr); + u64 RemoveBreakpointPC(int addr); + u64 AddBreakpointMemory(int address, u32 memoryAccess, DataBreakpointComparison comparison, int value); + u64 RemoveBreakpointMemory(int address); + // virtual void AddView(CGuiView *view); + + // + virtual nlohmann::json GetCpuStatusJson(); }; #endif diff --git a/src/DebugInterface/DebuggerDefs.h b/src/DebugInterface/DebuggerDefs.h index 746cadc..f0776bd 100644 --- a/src/DebugInterface/DebuggerDefs.h +++ b/src/DebugInterface/DebuggerDefs.h @@ -42,8 +42,7 @@ enum EmulatorType #define JOYPAD_NW (JOYPAD_N | JOYPAD_W) #define JOYPAD_NE (JOYPAD_N | JOYPAD_E) - -enum MemoryBreakpointComparison //: unsigned char +enum DataBreakpointComparison //: unsigned char { MEMORY_BREAKPOINT_EQUAL = 0, MEMORY_BREAKPOINT_NOT_EQUAL, @@ -98,6 +97,8 @@ enum c64PictureMode { C64_PICTURE_MODE_TEXT_HIRES=1, C64_PICTURE_MODE_TEXT_MULTI, + C64_PICTURE_MODE_TEXT_HIRES_EXTENDED, + C64_PICTURE_MODE_TEXT_MULTI_EXTENDED, C64_PICTURE_MODE_BITMAP_HIRES, C64_PICTURE_MODE_BITMAP_MULTI }; diff --git a/src/DebugInterface/Symbols/CDebugAsmSource.cpp b/src/DebugInterface/Symbols/CDebugAsmSource.cpp index 87f4c19..f251eff 100644 --- a/src/DebugInterface/Symbols/CDebugAsmSource.cpp +++ b/src/DebugInterface/Symbols/CDebugAsmSource.cpp @@ -593,31 +593,31 @@ void CDebugAsmSource::ParseXML(CByteBuffer *byteBuffer, CDebugInterface *debugIn int value = arg->ToIntFromHex(); - MemoryBreakpointComparison memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; + DataBreakpointComparison memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; if (op->Equals("==") || op->Equals("=")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; } else if (op->Equals("!=")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_NOT_EQUAL; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_NOT_EQUAL; } else if (op->Equals("<")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_LESS; } else if (op->Equals("<=") || op->Equals("=<")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL; } else if (op->Equals(">")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_GREATER; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_GREATER; } else if (op->Equals(">=") || op->Equals("=>")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_GREATER_OR_EQUAL; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_GREATER_OR_EQUAL; } else { diff --git a/src/DebugInterface/Symbols/CDebugAsmSource.h b/src/DebugInterface/Symbols/CDebugAsmSource.h index 52a0c76..ae355f5 100644 --- a/src/DebugInterface/Symbols/CDebugAsmSource.h +++ b/src/DebugInterface/Symbols/CDebugAsmSource.h @@ -3,7 +3,12 @@ #include "SYS_Defs.h" #include "CSlrString.h" -#include "CDebugBreakpoints.h" +#include "CDebugBreakpoint.h" +#include "CDebugBreakpointAddr.h" +#include "CDebugBreakpointData.h" +#include "CDebugBreakpointRasterLine.h" +#include "CDebugBreakpointsAddr.h" +#include "CDebugBreakpointsData.h" #include #include diff --git a/src/DebugInterface/Symbols/CDebugBreakpoint.cpp b/src/DebugInterface/Symbols/CDebugBreakpoint.cpp new file mode 100644 index 0000000..8259c48 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpoint.cpp @@ -0,0 +1,36 @@ +#include "CDebugBreakpoint.h" +#include "CDebugSymbols.h" +#include "CDebugInterface.h" + +u64 CDebugBreakpoint::lastBreakpointId = 0; + +CDebugBreakpoint::CDebugBreakpoint(CDebugSymbols *debugSymbols) +: symbols(debugSymbols) +{ + callback = NULL; + breakpointId = ++lastBreakpointId; + breakpointType = BREAKPOINT_TYPE_UNKNOWN; +} + +CDebugBreakpoint::~CDebugBreakpoint() +{ +} + +void CDebugBreakpoint::Serialize(Hjson::Value hjsonRoot) +{ +} + +void CDebugBreakpoint::Deserialize(Hjson::Value hjsonRoot) +{ +} + +const char *CDebugBreakpoint::GetPlatformNameEndpointString() +{ + return symbols->debugInterface->GetPlatformNameEndpointString(); +} + +void CDebugBreakpoint::GetDetailsJson(nlohmann::json &j) +{ + j["breakpointId"] = breakpointId; + j["platform"] = GetPlatformNameEndpointString(); +} diff --git a/src/DebugInterface/Symbols/CDebugBreakpoint.h b/src/DebugInterface/Symbols/CDebugBreakpoint.h new file mode 100644 index 0000000..506e654 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpoint.h @@ -0,0 +1,54 @@ +#ifndef _CDebugBreakpoint_h_ +#define _CDebugBreakpoint_h_ + +#include "SYS_Main.h" +#include "DebuggerDefs.h" +#include "hjson.h" +#include "json.hpp" +#include + +#define BREAKPOINT_TYPE_ADDR 0 +#define BREAKPOINT_TYPE_DATA 1 +#define BREAKPOINT_TYPE_RASTER_LINE 2 +#define NUM_DEFAULT_BREAKPOINT_TYPES 3 +#define BREAKPOINT_TYPE_UNKNOWN 0xFF + +#define ADDR_BREAKPOINT_ACTION_STOP BV01 +#define ADDR_BREAKPOINT_ACTION_SET_BACKGROUND BV02 +#define ADDR_BREAKPOINT_ACTION_STOP_ON_RASTER BV03 + +#define MEMORY_BREAKPOINT_ACCESS_WRITE BV01 +#define MEMORY_BREAKPOINT_ACCESS_READ BV02 + +class CDebugSymbols; +class CDebugBreakpointEventCallback; + +#define UNKNOWN_BREAKPOINT_ID 0 + +// generic breakpoint +class CDebugBreakpoint +{ +public: + CDebugBreakpoint(CDebugSymbols *debugSymbols); + virtual ~CDebugBreakpoint(); + + virtual void Serialize(Hjson::Value hjsonRoot); + virtual void Deserialize(Hjson::Value hjsonRoot); + + u64 breakpointId; + u8 breakpointType; + + CDebugSymbols *symbols; + + // return json for web service callback + virtual void GetDetailsJson(nlohmann::json &j); + virtual const char *GetPlatformNameEndpointString(); + + CDebugBreakpointEventCallback *callback; + +private: + static u64 lastBreakpointId; +}; + +#endif +//_CDebugBreakpoint_h_ diff --git a/src/DebugInterface/Symbols/CDebugBreakpointAddr.cpp b/src/DebugInterface/Symbols/CDebugBreakpointAddr.cpp new file mode 100644 index 0000000..3f59748 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointAddr.cpp @@ -0,0 +1,49 @@ +#include "CDebugBreakpointAddr.h" + +CDebugBreakpointAddr::CDebugBreakpointAddr(int addr) +: CDebugBreakpoint(NULL) +{ + this->breakpointType = BREAKPOINT_TYPE_ADDR; + this->isActive = true; + this->addr = addr; + this->actions = ADDR_BREAKPOINT_ACTION_STOP; + this->data = 0x00; +} + +CDebugBreakpointAddr::CDebugBreakpointAddr(CDebugSymbols *debugSymbols, int addr) +: CDebugBreakpoint(debugSymbols) +{ + this->breakpointType = BREAKPOINT_TYPE_ADDR; + this->isActive = true; + this->addr = addr; + this->actions = ADDR_BREAKPOINT_ACTION_STOP; + this->data = 0x00; +} + +void CDebugBreakpointAddr::Serialize(Hjson::Value hjsonRoot) +{ + hjsonRoot["IsActive"] = isActive; + hjsonRoot["Addr"] = addr; + hjsonRoot["Actions"] = actions; + hjsonRoot["Data"] = data; +} + +void CDebugBreakpointAddr::Deserialize(Hjson::Value hjsonRoot) +{ + isActive = (bool)hjsonRoot["IsActive"]; + addr = hjsonRoot["Addr"]; + actions = hjsonRoot["Actions"]; + data = hjsonRoot["Data"]; +} + +void CDebugBreakpointAddr::GetDetailsJson(nlohmann::json &j) +{ + CDebugBreakpoint::GetDetailsJson(j); + j["type"] = "addr"; +// j["triggerAddr"] = addr; +} + +CDebugBreakpointAddr::~CDebugBreakpointAddr() +{ +} + diff --git a/src/DebugInterface/Symbols/CDebugBreakpointAddr.h b/src/DebugInterface/Symbols/CDebugBreakpointAddr.h new file mode 100644 index 0000000..900e3f9 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointAddr.h @@ -0,0 +1,27 @@ +#ifndef _CDebugBreakpointAddr_h_ +#define _CDebugBreakpointAddr_h_ + +#include "CDebugBreakpoint.h" + +class CDebugBreakpointAddr : public CDebugBreakpoint +{ +public: + CDebugBreakpointAddr(int addr); + CDebugBreakpointAddr(CDebugSymbols *debugSymbols, int addr); + virtual ~CDebugBreakpointAddr(); + + bool isActive; + + int addr; + u32 actions; + u8 data; + + virtual void Serialize(Hjson::Value hjsonRoot); + virtual void Deserialize(Hjson::Value hjsonRoot); + + virtual void GetDetailsJson(nlohmann::json &j); +}; + + +#endif +//_CDebugBreakpoint_h_ diff --git a/src/DebugInterface/Symbols/CDebugBreakpointData.cpp b/src/DebugInterface/Symbols/CDebugBreakpointData.cpp new file mode 100644 index 0000000..ccb9241 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointData.cpp @@ -0,0 +1,48 @@ +#include "CDebugBreakpointData.h" +#include "CDebugBreakpointsData.h" + +CDebugBreakpointData::CDebugBreakpointData(int addr, + u32 dataAccess, DataBreakpointComparison comparison, int value) +: CDebugBreakpointAddr(NULL, addr) +{ + this->breakpointType = BREAKPOINT_TYPE_DATA; + this->dataAccess = dataAccess; + this->value = value; + this->comparison = comparison; +} + +CDebugBreakpointData::CDebugBreakpointData(CDebugSymbols *debugSymbols, int addr, + u32 dataAccess, DataBreakpointComparison comparison, int value) +: CDebugBreakpointAddr(debugSymbols, addr) +{ + this->breakpointType = BREAKPOINT_TYPE_DATA; + this->dataAccess = dataAccess; + this->value = value; + this->comparison = comparison; +} + +void CDebugBreakpointData::Serialize(Hjson::Value hjsonRoot) +{ + CDebugBreakpointAddr::Serialize(hjsonRoot); + + hjsonRoot["MemoryAccess"] = dataAccess; + hjsonRoot["Value"] = value; + hjsonRoot["Comparison"] = (int)comparison; +} + +void CDebugBreakpointData::Deserialize(Hjson::Value hjsonRoot) +{ + CDebugBreakpointAddr::Deserialize(hjsonRoot); + + dataAccess = hjsonRoot["MemoryAccess"]; + value = hjsonRoot["Value"]; + comparison = (DataBreakpointComparison) ((int)hjsonRoot["Comparison"]); +} + +void CDebugBreakpointData::GetDetailsJson(nlohmann::json &j) +{ + CDebugBreakpoint::GetDetailsJson(j); + j["type"] = "data"; +// j["triggerValue"] = value; +// j["triggerComparison"] = CDebugBreakpointsData::DataBreakpointComparisonToStr(comparison); +} diff --git a/src/DebugInterface/Symbols/CDebugBreakpointData.h b/src/DebugInterface/Symbols/CDebugBreakpointData.h new file mode 100644 index 0000000..b27654a --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointData.h @@ -0,0 +1,26 @@ +#ifndef _CDebugBreakpointData_h_ +#define _CDebugBreakpointData_h_ + +#include "CDebugBreakpointAddr.h" + +// TODO: refactor this to 2 breakpoints (make list?) +class CDebugBreakpointData : public CDebugBreakpointAddr +{ +public: + CDebugBreakpointData(int addr, + u32 dataAccess, DataBreakpointComparison comparison, int value); + CDebugBreakpointData(CDebugSymbols *symbols, int addr, + u32 dataAccess, DataBreakpointComparison comparison, int value); + + u32 dataAccess; + int value; + DataBreakpointComparison comparison; + + virtual void Serialize(Hjson::Value hjsonRoot); + virtual void Deserialize(Hjson::Value hjsonRoot); + + virtual void GetDetailsJson(nlohmann::json &j); +}; + +#endif +//_CDebugBreakpoint_h_ diff --git a/src/DebugInterface/Symbols/CDebugBreakpointEventCallback.cpp b/src/DebugInterface/Symbols/CDebugBreakpointEventCallback.cpp new file mode 100644 index 0000000..b1e4ddc --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointEventCallback.cpp @@ -0,0 +1,10 @@ +#include "CDebugBreakpointEventCallback.h" + +bool CDebugBreakpointEventCallback::DebugBreakpointEvaluateCallback(CDebugBreakpoint *breakpoint) +{ + // Note, this return allows plugins to set breakpoints that will not cause code to stop. + // true = means that the breakpoint is confirmed, so the mechanism will perform an action, such as pausing the code. + // false = means that the breakpoint does not need to be processed, and the mechanism will not perform any breakpoint-specific actions. + + return true; +} diff --git a/src/DebugInterface/Symbols/CDebugBreakpointEventCallback.h b/src/DebugInterface/Symbols/CDebugBreakpointEventCallback.h new file mode 100644 index 0000000..5769b97 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointEventCallback.h @@ -0,0 +1,15 @@ +#ifndef _CDebugBreakpointEventCallback_h_ +#define _CDebugBreakpointEventCallback_h_ + +#include "CDebugBreakpoint.h" + +class CDebugBreakpoint; + +class CDebugBreakpointEventCallback +{ +public: + // returns if we should skip evaluation of breakpoint (i.e. stop code running) + virtual bool DebugBreakpointEvaluateCallback(CDebugBreakpoint *breakpoint); +}; + +#endif diff --git a/src/DebugInterface/Symbols/CDebugBreakpointRasterLine.cpp b/src/DebugInterface/Symbols/CDebugBreakpointRasterLine.cpp new file mode 100644 index 0000000..79cf87e --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointRasterLine.cpp @@ -0,0 +1,21 @@ +#include "CDebugBreakpointRasterLine.h" + +CDebugBreakpointRasterLine::CDebugBreakpointRasterLine(int rasterLine) +: CDebugBreakpointAddr(rasterLine) +{ + this->breakpointType = BREAKPOINT_TYPE_RASTER_LINE; +} + +CDebugBreakpointRasterLine::CDebugBreakpointRasterLine(CDebugSymbols *debugSymbols, int rasterLine) +: CDebugBreakpointAddr(debugSymbols, rasterLine) +{ + this->breakpointType = BREAKPOINT_TYPE_RASTER_LINE; +} + +void CDebugBreakpointRasterLine::GetDetailsJson(nlohmann::json &j) +{ + CDebugBreakpoint::GetDetailsJson(j); + j["type"] = "rasterLine"; +// j["triggerRasterLine"] = addr; +} + diff --git a/src/DebugInterface/Symbols/CDebugBreakpointRasterLine.h b/src/DebugInterface/Symbols/CDebugBreakpointRasterLine.h new file mode 100644 index 0000000..38e656f --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointRasterLine.h @@ -0,0 +1,16 @@ +#ifndef _CDebugBreakpointRasterLine_h_ +#define _CDebugBreakpointRasterLine_h_ + +#include "CDebugBreakpointAddr.h" + +class CDebugBreakpointRasterLine : public CDebugBreakpointAddr +{ +public: + CDebugBreakpointRasterLine(int rasterLine); + CDebugBreakpointRasterLine(CDebugSymbols *debugSymbols, int rasterLine); + + virtual void GetDetailsJson(nlohmann::json &j); +}; + + +#endif diff --git a/src/DebugInterface/Symbols/CDebugBreakpointsAddr.cpp b/src/DebugInterface/Symbols/CDebugBreakpointsAddr.cpp new file mode 100644 index 0000000..57cf8d3 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointsAddr.cpp @@ -0,0 +1,459 @@ +#include "CDebugBreakpointAddr.h" +#include "CDebugBreakpointsAddr.h" +#include "CViewDisassembly.h" +#include "CDebugInterface.h" +#include "CDebugSymbols.h" +#include "CDebugSymbolsSegment.h" +#include "CDebugSymbolsCodeLabel.h" +#include "GUI_Main.h" + +#include "CDebugBreakpointEventCallback.h" +#include "CDebuggerServer.h" +#include "CViewC64.h" + +// std::map memoryBreakpoints; + +CDebugBreakpointsAddr::CDebugBreakpointsAddr(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr) +{ + this->breakpointsType = breakpointType; + this->breakpointsTypeStr = breakpointTypeStr; + this->segment = segment; + this->symbols = segment->symbols; + this->addressFormatStr = addressFormatStr; + this->minAddr = minAddr; + this->maxAddr = maxAddr; + comboFilterState = {0, false}; + comboFilterTextBuf[0] = 0; + + renderBreakpointsMutex = new CSlrMutex("CDebugBreakpointsAddr::renderBreakpointsMutex"); + + addressNameJsonStr = "addr"; + addBreakpointPopupHeadlineStr = "Add PC Breakpoint"; + addBreakpointPopupAddrStr = "Address"; + addBreakpointPopupAddrInputFlags = ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase; + addBreakpointsTableColumnAddrStr = "Address"; + + temporaryBreakpointPC = -1; + + // TODO: workaround, remove me when ImGui bug is fixed: https://github.com/ocornut/imgui/issues/1655 + imGuiColumnsWidthWorkaroundFrame = 0; + + imGuiOpenPopupFrame = 999; +} + +// address -1 means no breakpoint +void CDebugBreakpointsAddr::SetTemporaryBreakpointPC(int address) +{ + this->temporaryBreakpointPC = address; +} + +int CDebugBreakpointsAddr::GetTemporaryBreakpointPC() +{ + return this->temporaryBreakpointPC; +} + +void CDebugBreakpointsAddr::ClearBreakpoints() +{ + while(!breakpoints.empty()) + { + std::map::iterator it = breakpoints.begin(); + CDebugBreakpointAddr *breakpoint = it->second; + + breakpoints.erase(it); + delete breakpoint; + } +} + +CDebugBreakpoint *CDebugBreakpointsAddr::CreateEmptyBreakpoint() +{ + return new CDebugBreakpointAddr(symbols, 0); +} + +void CDebugBreakpointsAddr::Serialize(Hjson::Value hjsonBreakpoints) +{ + for (std::map::iterator it = breakpoints.begin(); it != breakpoints.end(); it++) + { + CDebugBreakpointAddr *breakpoint = it->second; + Hjson::Value hjsonBreakpoint; + breakpoint->Serialize(hjsonBreakpoint); + + CDebugSymbolsCodeLabel *label = segment->FindLabel(breakpoint->addr); + if (label) + { + hjsonBreakpoint["Label"] = label->GetLabelText(); + } + + hjsonBreakpoints.push_back(hjsonBreakpoint); + } +} + +void CDebugBreakpointsAddr::Deserialize(Hjson::Value hjsonBreakpoints) +{ + for (int index = 0; index < hjsonBreakpoints.size(); ++index) + { + Hjson::Value hjsonBreakpoint = hjsonBreakpoints[index]; + CDebugBreakpointAddr *breakpoint = (CDebugBreakpointAddr*)CreateEmptyBreakpoint(); + breakpoint->Deserialize(hjsonBreakpoint); + + // check label + Hjson::Value hjsonBreakpointLabel = hjsonBreakpoint["Label"]; + if (hjsonBreakpointLabel != Hjson::Type::Undefined) + { + const char *labelStr = hjsonBreakpoint["Label"]; + CDebugSymbolsCodeLabel *label = segment->FindLabelByText(labelStr); + if (label) + { + breakpoint->addr = label->address; + } + } + + AddBreakpoint(breakpoint); + } +} + +void CDebugBreakpointsAddr::AddBreakpoint(CDebugBreakpointAddr *breakpoint) +{ + // check if breakpoint is already in the map and remove it, can be with other addr so we can't use find + for (std::map::iterator it = breakpoints.begin(); it != breakpoints.end(); it++) + { + CDebugBreakpointAddr *existingBreakpoint = it->second; + + if (existingBreakpoint == breakpoint) + { + breakpoints.erase(it); + break; + } + } + + // check if there's a breakpoint with the same address and delete it (we are replacing it) + std::map::iterator it = breakpoints.find(breakpoint->addr); + if (it != breakpoints.end()) + { + CDebugBreakpointAddr *existingBreakpoint = it->second; + breakpoints.erase(it); + delete existingBreakpoint; + } + + // set symbols + breakpoint->symbols = symbols; + + // add a breakpoint + breakpoints[breakpoint->addr] = breakpoint; +} + +CDebugBreakpointAddr *CDebugBreakpointsAddr::GetBreakpoint(int addr) +{ + std::map::iterator it = breakpoints.find(addr); + if (it == breakpoints.end()) + return NULL; + + return it->second; +} + +u64 CDebugBreakpointsAddr::DeleteBreakpoint(int addr) +{ + std::map::iterator it = breakpoints.find(addr); + if (it != breakpoints.end()) + { + CDebugBreakpointAddr *breakpoint = it->second; + u64 breakpointId = breakpoint->breakpointId; + breakpoints.erase(it); + delete breakpoint; + + return breakpointId; + } + + return UNKNOWN_BREAKPOINT_ID; +} + +void CDebugBreakpointsAddr::DeleteBreakpoint(CDebugBreakpointAddr *breakpoint) +{ + this->DeleteBreakpoint(breakpoint->addr); +} + +void CDebugBreakpointsAddr::RemoveBreakpoint(CDebugBreakpointAddr *breakpoint) +{ + std::map::iterator it = breakpoints.find(breakpoint->addr); + if (it != breakpoints.end()) + { + breakpoints.erase(it); + } + + UpdateRenderBreakpoints(); +} + + +// TODO: create a condition parser (tree for condition) and parse the condition text +CDebugBreakpointAddr *CDebugBreakpointsAddr::EvaluateBreakpoint(int addr) +{ + std::map::iterator it = breakpoints.find(addr); + if (it != breakpoints.end()) + { + CDebugBreakpointAddr *breakpoint = it->second; + if (breakpoint->isActive == false) + return NULL; + + if (breakpoint->callback) + { + if (breakpoint->callback->DebugBreakpointEvaluateCallback(breakpoint) == false) + return NULL; + } + + // flag breakpoint to Server API + if (viewC64->debuggerServer) + { + if (breakpoint && viewC64->debuggerServer->AreClientsConnected()) + { + nlohmann::json j; + breakpoint->GetDetailsJson(j); + j[addressNameJsonStr] = addr; + viewC64->debuggerServer->BroadcastEvent("breakpoint", j); + } + } + + return breakpoint; + } + + return NULL; +} + +// +bool CDebugBreakpointsAddr::ComboFilterShouldOpenPopupCallback(const char *label, char *buffer, int bufferlen, + const char **hints, int num_hints, ImGui::ComboFilterState *s) +{ + // do not need to open combo popup when number is hex + if (FUN_IsHexNumber(buffer)) + { + return false; + } + + if (hints == NULL) + { + return false; + } + + if (num_hints == 0) + { + return false; + } + + return (buffer[0] != 0) && strcmp(buffer, hints[s->activeIdx]); +} + +void CDebugBreakpointsAddr::RenderImGui() +{ +// LOGD("CDebugBreakpointsAddr::RenderImGui"); + + char *buf = SYS_GetCharBuf(); + + ImVec4 colorNotActive(0.5, 0.5, 0.5, 1); + ImVec4 colorActive(1.0, 1.0, 1.0, 1); + + symbols->LockMutex(); + + CDebugBreakpointAddr *deleteBreakpoint = NULL; + + sprintf(buf, "##BreakpointsAddrTable_%s", symbols->dataAdapter->adapterID); + + // active | address | symbol | delete + if (ImGui::BeginTable(buf, 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Borders)) + { + u32 i = 0; + +// ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(0.7f, 0.7f, 0.7f, 0.65f))); + + ImGui::TableNextColumn(); + ImGui::Text("Active"); + ImGui::TableNextColumn(); + ImGui::Text(addBreakpointsTableColumnAddrStr); + ImGui::TableNextColumn(); + ImGui::Text("Label"); + ImGui::TableNextColumn(); + ImGui::Text(""); + +// ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, 0); + + for (std::map::iterator it = breakpoints.begin(); it != breakpoints.end(); it++) + { + CDebugBreakpointAddr *bp = it->second; + + sprintf(buf, "##chkBoxAddr%x%d", this, i); + + ImGui::TableNextColumn(); + if (ImGui::Checkbox(buf, &bp->isActive)) + { + symbols->UpdateRenderBreakpoints(); + } + + ImGui::TableNextColumn(); + ImVec4 color = bp->isActive ? colorActive : colorNotActive; + + ImGui::TextColored(color, addressFormatStr, bp->addr); + + ImGui::TableNextColumn(); + CDebugSymbolsCodeLabel *label = NULL; + if (symbols->currentSegment) + { + label = symbols->currentSegment->FindLabel(bp->addr); + } + + ImGui::TextColored(color, label ? label->GetLabelText() : ""); + + ImGui::TableNextColumn(); + sprintf(buf, "X##%x%d", this, i); + if (ImGui::Button(buf)) + { + // delete breakpoint + deleteBreakpoint = bp; + } + + i++; + } + + ImGui::EndTable(); + } + + if (deleteBreakpoint) + { + DeleteBreakpoint(deleteBreakpoint); + symbols->UpdateRenderBreakpoints(); + } + + + /// + + // shold we evaluate Enter press as adding the breakpoint or closing the combo? + bool skipClosePopupByEnterPressInThisFrame = false; + + if (ImGui::Button("+") || (ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))) + { + ImGui::OpenPopup("addAddrBreakpointPopup"); + + addBreakpointPopupAddr = 0; + addBreakpointPopupSymbol[0] = '\0'; + comboFilterTextBuf[0] = 0; + + imGuiOpenPopupFrame = 0; + skipClosePopupByEnterPressInThisFrame = true; + } + + if (ImGui::BeginPopup("addAddrBreakpointPopup")) + { + ImGui::Text(addBreakpointPopupHeadlineStr); +// ImGui::SameLine(); +// ImGui::Text("Address: %04x", ) + ImGui::Separator(); + + if (imGuiOpenPopupFrame < 2) + { + ImGui::SetKeyboardFocusHere(); + imGuiOpenPopupFrame++; + } + + sprintf(buf, "##addPCBreakpointPopupAddress_%s", symbols->dataAdapter->adapterID); + + bool buttonAddClicked = false; + if (symbols->currentSegment) + { + const char **hints = symbols->currentSegment->codeLabelsArray; + int numHints = symbols->currentSegment->numCodeLabelsInArray; + + // https://github.com/ocornut/imgui/issues/1658 | IM_ARRAYSIZE(hints) + if( ComboFilter(buf, comboFilterTextBuf, IM_ARRAYSIZE(comboFilterTextBuf), hints, numHints, comboFilterState, this) ) + { + LOGD("SELECTED %d comboTextBuf='%s'", comboFilterState.activeIdx, comboFilterTextBuf); + skipClosePopupByEnterPressInThisFrame = false; //true; + + // if that is not address then replace by selected symbol + if (FUN_IsHexNumber(comboFilterTextBuf)) + { + FUN_ToUpperCaseStr(comboFilterTextBuf); + addBreakpointPopupAddr = FUN_HexStrToValue(comboFilterTextBuf); + } + else if (hints != NULL && numHints > 0 && comboFilterState.activeIdx < numHints) + { + strcpy(comboFilterTextBuf, hints[comboFilterState.activeIdx]); + } + } + + ImGui::SameLine(); + if (ImGui::Button("Add")) + { + buttonAddClicked = true; + } + } + + bool finalizeAddingBreakpoint = buttonAddClicked + || (!skipClosePopupByEnterPressInThisFrame && ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter))); + +// if (ImGui::Button("Create PC Breakpoint")) +// { +// finalizeAddingBreakpoint = true; +// } + + if (finalizeAddingBreakpoint) + { + CDebugSymbolsCodeLabel *label = symbols->currentSegment->FindLabelByText(comboFilterTextBuf); + if (label) + { + addBreakpointPopupAddr = label->address; + } + else if (FUN_IsHexNumber(comboFilterTextBuf)) + { + FUN_ToUpperCaseStr(comboFilterTextBuf); + addBreakpointPopupAddr = FUN_HexStrToValue(comboFilterTextBuf); + } + else + { + char *buf = SYS_GetCharBuf(); + sprintf(buf, "Invalid address or symbol:\n%s", comboFilterTextBuf); + guiMain->ShowMessageBox("Can't add breakpoint", buf); + SYS_ReleaseCharBuf(buf); + addBreakpointPopupAddr = -1; + } + + if (addBreakpointPopupAddr >= 0) + { + addBreakpointPopupAddr = URANGE(minAddr, addBreakpointPopupAddr, maxAddr); + + CDebugBreakpointAddr *breakpoint = (CDebugBreakpointAddr*)CreateEmptyBreakpoint(); + breakpoint->addr = addBreakpointPopupAddr; + AddBreakpoint(breakpoint); + UpdateRenderBreakpoints(); + + ImGui::CloseCurrentPopup(); + } + } + + //// + + ImGui::EndPopup(); + } + + symbols->UnlockMutex(); + + SYS_ReleaseCharBuf(buf); +} + +void CDebugBreakpointsAddr::UpdateRenderBreakpoints() +{ + renderBreakpointsMutex->Lock(); + symbols->LockMutex(); + + renderBreakpoints.clear(); + for (std::map::iterator it = breakpoints.begin(); + it != breakpoints.end(); it++) + { + CDebugBreakpointAddr *breakpoint = it->second; + renderBreakpoints[breakpoint->addr] = breakpoint; + } + + symbols->UnlockMutex(); + this->renderBreakpointsMutex->Unlock(); +} + +CDebugBreakpointsAddr::~CDebugBreakpointsAddr() +{ + ClearBreakpoints(); +} + diff --git a/src/DebugInterface/Symbols/CDebugBreakpointsAddr.h b/src/DebugInterface/Symbols/CDebugBreakpointsAddr.h new file mode 100644 index 0000000..75a55be --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointsAddr.h @@ -0,0 +1,71 @@ +#ifndef _CDebugBreakpointsAddr_h_ +#define _CDebugBreakpointsAddr_h_ + +#include "CDebugBreakpointAddr.h" +#include "GUI_Main.h" +#include "CDebugSymbols.h" +#include "imguiComboFilter.h" + +class CDebugBreakpointsAddr : public ImGui::ComboFilterCallback +{ +public: + CDebugBreakpointsAddr(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr); + ~CDebugBreakpointsAddr(); + + int breakpointsType; + const char *breakpointsTypeStr; + const char *addressNameJsonStr; + const char *addressFormatStr; + int minAddr, maxAddr; + const char *addBreakpointPopupHeadlineStr; + const char *addBreakpointPopupAddrStr; + ImGuiInputTextFlags addBreakpointPopupAddrInputFlags; + const char *addBreakpointsTableColumnAddrStr; + + CDebugSymbolsSegment *segment; + CDebugSymbols *symbols; + + std::map breakpoints; + + // copy of the breakpoints used for rendering that is not synchronised, to offload mutex switching for emulators during renderings + CSlrMutex *renderBreakpointsMutex; + std::map renderBreakpoints; + + virtual void UpdateRenderBreakpoints(); + + // factory + virtual CDebugBreakpoint *CreateEmptyBreakpoint(); + + virtual void AddBreakpoint(CDebugBreakpointAddr *addrBreakpoint); + CDebugBreakpointAddr *GetBreakpoint(int addr); + virtual void RemoveBreakpoint(CDebugBreakpointAddr *breakpoint); + virtual void DeleteBreakpoint(CDebugBreakpointAddr *addrBreakpoint); + u64 DeleteBreakpoint(int addr); + + virtual CDebugBreakpointAddr *EvaluateBreakpoint(int addr); + + virtual void ClearBreakpoints(); + virtual void RenderImGui(); + + // for stepping over JSR, set temporary breakpoint after the JSR and run code + int temporaryBreakpointPC; + virtual int GetTemporaryBreakpointPC(); + virtual void SetTemporaryBreakpointPC(int address); + + + virtual bool ComboFilterShouldOpenPopupCallback(const char *label, char *buffer, int bufferlen, + const char **hints, int num_hints, ImGui::ComboFilterState *s); + + virtual void Serialize(Hjson::Value hjsonBreakpoints); + virtual void Deserialize(Hjson::Value hjsonBreakpoints); + +protected: + int addBreakpointPopupAddr; + char addBreakpointPopupSymbol[256]; + int imGuiColumnsWidthWorkaroundFrame; + int imGuiOpenPopupFrame; + ImGui::ComboFilterState comboFilterState = {0, false}; + char comboFilterTextBuf[MAX_LABEL_TEXT_BUFFER_SIZE]; +}; +#endif + diff --git a/src/DebugInterface/Symbols/CDebugBreakpointsData.cpp b/src/DebugInterface/Symbols/CDebugBreakpointsData.cpp new file mode 100644 index 0000000..4e96052 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointsData.cpp @@ -0,0 +1,383 @@ +#include "CDebugBreakpointsData.h" +#include "CViewDisassembly.h" +#include "CDebugInterface.h" +#include "CDebugSymbols.h" +#include "CDebugSymbolsSegment.h" +#include "CDebugSymbolsCodeLabel.h" +#include "GUI_Main.h" + +#include "CDebugBreakpointEventCallback.h" +#include "CDebuggerServer.h" +#include "CViewC64.h" + +const char *comparisonMethodsStr[MEMORY_BREAKPOINT_ARRAY_SIZE] = { "==", "!=", "<", "<=", ">", ">=" }; + +CDebugBreakpointData *CDebugBreakpointsData::EvaluateBreakpoint(int addr, int value, u32 memoryAccess) +{ + std::map::iterator it = breakpoints.find(addr); + if (it != breakpoints.end()) + { + CDebugBreakpointData *dataBreakpoint = (CDebugBreakpointData *)it->second; + if (dataBreakpoint->isActive == false) + return NULL; + + // check memory access (read/write) + if (!IS_SET(dataBreakpoint->dataAccess, memoryAccess)) + { + return NULL; + } + + CDebugBreakpointData *evaluateBreakpoint = NULL; + if (dataBreakpoint->comparison == DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL) + { + if (value == dataBreakpoint->value) + { + evaluateBreakpoint = dataBreakpoint; + } + } + else if (dataBreakpoint->comparison == DataBreakpointComparison::MEMORY_BREAKPOINT_NOT_EQUAL) + { + if (value != dataBreakpoint->value) + { + evaluateBreakpoint = dataBreakpoint; + } + } + else if (dataBreakpoint->comparison == DataBreakpointComparison::MEMORY_BREAKPOINT_LESS) + { + if (value < dataBreakpoint->value) + { + evaluateBreakpoint = dataBreakpoint; + } + } + else if (dataBreakpoint->comparison == DataBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL) + { + if (value <= dataBreakpoint->value) + { + evaluateBreakpoint = dataBreakpoint; + } + } + else if (dataBreakpoint->comparison == DataBreakpointComparison::MEMORY_BREAKPOINT_GREATER) + { + if (value > dataBreakpoint->value) + { + evaluateBreakpoint = dataBreakpoint; + } + } + else if (dataBreakpoint->comparison == DataBreakpointComparison::MEMORY_BREAKPOINT_GREATER_OR_EQUAL) + { + if (value >= dataBreakpoint->value) + { + evaluateBreakpoint = dataBreakpoint; + } + } + + if (evaluateBreakpoint && evaluateBreakpoint->callback) + { + if (evaluateBreakpoint->callback->DebugBreakpointEvaluateCallback(dataBreakpoint) == false) + return NULL; + } + + // flag breakpoint to Server API + if (viewC64->debuggerServer) + { + if (evaluateBreakpoint && viewC64->debuggerServer->AreClientsConnected()) + { + nlohmann::json j; + evaluateBreakpoint->GetDetailsJson(j); + j["addr"] = addr; + j["value"] = value; + if (memoryAccess == MEMORY_BREAKPOINT_ACCESS_WRITE) + { + j["access"] = "write"; + } + else if (memoryAccess == MEMORY_BREAKPOINT_ACCESS_READ) + { + j["access"] = "read"; + } + viewC64->debuggerServer->BroadcastEvent("breakpoint", j); + } + } + + return evaluateBreakpoint; + } + + return NULL; +} + +void CDebugBreakpointsData::RenderImGui() +{ +// LOGD("CDebugBreakpointsData::RenderImGui"); + + char *buf = SYS_GetCharBuf(); + + ImVec4 colorNotActive(0.5, 0.5, 0.5, 1); + ImVec4 colorActive(1.0, 1.0, 1.0, 1); + + sprintf(buf, "##BreakpointsDataTable_%s", symbols->dataAdapter->adapterID); + + symbols->LockMutex(); + + CDebugBreakpointAddr *deleteBreakpoint = NULL; + + // active | address | <= | FF | symbol | delete + if (ImGui::BeginTable(buf, 6, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders)) //| ImGuiTableFlags_Sortable TODO + { + u32 i = 0; + +// ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(0.7f, 0.7f, 0.7f, 0.65f))); + + ImGui::TableNextColumn(); + ImGui::Text("Active"); + ImGui::TableNextColumn(); + ImGui::Text("Address"); + ImGui::TableNextColumn(); + ImGui::Text("Comparison"); + ImGui::TableNextColumn(); + ImGui::Text("Value"); + ImGui::TableNextColumn(); + ImGui::Text("Label"); + ImGui::TableNextColumn(); + ImGui::Text(""); + +// ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, 0); + + for (std::map::iterator it = breakpoints.begin(); it != breakpoints.end(); it++) + { + CDebugBreakpointData *bp = (CDebugBreakpointData*)it->second; + + sprintf(buf, "##chkBoxMem%x%d", this, i); + + ImGui::TableNextColumn(); + if (ImGui::Checkbox(buf, &bp->isActive)) + { + // we do not need to update anything + } + + ImGui::TableNextColumn(); + ImVec4 color = bp->isActive ? colorActive : colorNotActive; + ImGui::TextColored(color, addressFormatStr, bp->addr); + + ImGui::TableNextColumn(); + const char *comparisonStr = DataBreakpointComparisonToStr(bp->comparison); + ImGui::TextColored(color, comparisonStr, bp->addr); + + ImGui::TableNextColumn(); + ImGui::TextColored(color, "%02X", bp->value); + + ImGui::TableNextColumn(); + CDebugSymbolsCodeLabel *label = NULL; + if (symbols->currentSegment) + { + label = symbols->currentSegment->FindLabel(bp->addr); + } + ImGui::TextColored(color, label ? label->GetLabelText() : ""); + + ImGui::TableNextColumn(); + sprintf(buf, "X##%x%d", this, i); + if (ImGui::Button(buf)) + { + // delete breakpoint + deleteBreakpoint = bp; + } + + i++; + } + + ImGui::EndTable(); + } + + if (deleteBreakpoint) + { + DeleteBreakpoint(deleteBreakpoint); + symbols->UpdateRenderBreakpoints(); + } + + // shold we evaluate Enter press as adding the breakpoint or closing the combo? + bool skipClosePopupByEnterPressInThisFrame = false; + + if (ImGui::Button("+") || (ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))) + { + ImGui::OpenPopup("addMemBreakpointPopup"); + + addBreakpointPopupAddr = 0; + addBreakpointPopupSymbol[0] = '\0'; + addBreakpointPopupValue = 0xFF; + addBreakpointPopupComparisonMethod = DataBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL; + comboFilterTextBuf[0] = 0; //memcpy(buf, hints[0], strlen(hints[0]) + 1); + + imGuiOpenPopupFrame = 0; + skipClosePopupByEnterPressInThisFrame = true; + } + + if (ImGui::BeginPopup("addMemBreakpointPopup")) + { + ImGui::Text(addBreakpointPopupHeadlineStr); + ImGui::Separator(); + + if (imGuiOpenPopupFrame < 2) + { + ImGui::SetKeyboardFocusHere(); + imGuiOpenPopupFrame++; + } + + sprintf(buf, "##addMemBreakpointPopupAddress_%s", symbols->dataAdapter->adapterID); + + if (symbols->currentSegment) + { + const char **hints = symbols->currentSegment->codeLabelsArray; + int numHints = symbols->currentSegment->numCodeLabelsInArray; + + // https://github.com/ocornut/imgui/issues/1658 | IM_ARRAYSIZE(hints) + if( ComboFilter(buf, comboFilterTextBuf, IM_ARRAYSIZE(comboFilterTextBuf), hints, numHints, comboFilterState, this) ) + { + LOGD("SELECTED %d comboTextBuf='%s'", comboFilterState.activeIdx, comboFilterTextBuf); + skipClosePopupByEnterPressInThisFrame = true; + + // TODO: fix this logic, we need to first check if label exists, if yes then use label first even if label is some hexcode string + + // if that is not address then replace by selected symbol + if (FUN_IsHexNumber(comboFilterTextBuf)) + { + FUN_ToUpperCaseStr(comboFilterTextBuf); + addBreakpointPopupAddr = FUN_HexStrToValue(comboFilterTextBuf); + } + else if (hints != NULL && numHints > 0 && comboFilterState.activeIdx < numHints) + { + strcpy(comboFilterTextBuf, hints[comboFilterState.activeIdx]); + } + } + } + + ImGui::SameLine(); + + // + const char *selectedComparisonStr = DataBreakpointComparisonToStr((DataBreakpointComparison)addBreakpointPopupComparisonMethod); + + sprintf(buf, "##addMemBreakpointPopupComboComparison%x", this); + if (ImGui::BeginCombo(buf, selectedComparisonStr)) + { + skipClosePopupByEnterPressInThisFrame = true; + for (int n = 0; n < MEMORY_BREAKPOINT_ARRAY_SIZE; n++) + { + bool is_selected = (addBreakpointPopupComparisonMethod == n); + if (ImGui::Selectable(comparisonMethodsStr[n], is_selected)) + { + addBreakpointPopupComparisonMethod = n; + } + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + ImGui::SameLine(); + + sprintf(buf, "##addMemBreakpointPopupValue%x", this); + ImGui::InputScalar(buf, ImGuiDataType_::ImGuiDataType_U8, &addBreakpointPopupValue, NULL, NULL, "%02X", + ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); + +// ImGui::SameLine(); + + bool finalizeAddingBreakpoint = !skipClosePopupByEnterPressInThisFrame && ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)); + + if (ImGui::Button("Create Breakpoint")) + { + finalizeAddingBreakpoint = true; + } + + if (finalizeAddingBreakpoint) + { + CDebugSymbolsCodeLabel *label = symbols->currentSegment->FindLabelByText(comboFilterTextBuf); + if (label) + { + addBreakpointPopupAddr = label->address; + } + else if (FUN_IsHexNumber(comboFilterTextBuf)) + { + FUN_ToUpperCaseStr(comboFilterTextBuf); + addBreakpointPopupAddr = FUN_HexStrToValue(comboFilterTextBuf); + } + else + { + char *buf = SYS_GetCharBuf(); + sprintf(buf, "Invalid address or symbol:\n%s", comboFilterTextBuf); + guiMain->ShowMessageBox("Can't add breakpoint", buf); + SYS_ReleaseCharBuf(buf); + addBreakpointPopupAddr = -1; + } + + if (addBreakpointPopupAddr >= 0) + { + addBreakpointPopupAddr = URANGE(minAddr, addBreakpointPopupAddr, maxAddr); + addBreakpointPopupValue = URANGE(0, addBreakpointPopupValue, 0xFF); + + CDebugBreakpointData *breakpoint = new CDebugBreakpointData(addBreakpointPopupAddr, MEMORY_BREAKPOINT_ACCESS_WRITE, + (DataBreakpointComparison)addBreakpointPopupComparisonMethod, + addBreakpointPopupValue); + AddBreakpoint(breakpoint); + UpdateRenderBreakpoints(); + + ImGui::CloseCurrentPopup(); + } + } + + ImGui::EndPopup(); + } + + symbols->UnlockMutex(); + + SYS_ReleaseCharBuf(buf); +} + +const char *CDebugBreakpointsData::DataBreakpointComparisonToStr(DataBreakpointComparison comparison) +{ + switch(comparison) + { + case DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL: + return "=="; + case DataBreakpointComparison::MEMORY_BREAKPOINT_NOT_EQUAL: + return "!="; + case DataBreakpointComparison::MEMORY_BREAKPOINT_LESS: + return "<"; + case DataBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL: + return "<="; + case DataBreakpointComparison::MEMORY_BREAKPOINT_GREATER: + return ">"; + case DataBreakpointComparison::MEMORY_BREAKPOINT_GREATER_OR_EQUAL: + return ">="; + default: + return "???"; + } +} + +DataBreakpointComparison CDebugBreakpointsData::StrToDataBreakpointComparison(const char *comparisonStr) +{ + for (int i = 0; i < MEMORY_BREAKPOINT_ARRAY_SIZE; i++) + { + if (!strcmp(comparisonStr, comparisonMethodsStr[i])) + { + return DataBreakpointComparison(i); + } + } + + return (DataBreakpointComparison)MEMORY_BREAKPOINT_ARRAY_SIZE; +} + + +CDebugBreakpointsData::CDebugBreakpointsData(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr) +: CDebugBreakpointsAddr(breakpointType, breakpointTypeStr, segment, addressFormatStr, minAddr, maxAddr) +{ + addBreakpointPopupHeadlineStr = "Add Memory Breakpoint"; + addBreakpointPopupAddrStr = "Address"; +} + +CDebugBreakpoint *CDebugBreakpointsData::CreateEmptyBreakpoint() +{ + return new CDebugBreakpointData(symbols, 0, 0, DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL, 0); +} + +CDebugBreakpointsData::~CDebugBreakpointsData() +{ + ClearBreakpoints(); +} + diff --git a/src/DebugInterface/Symbols/CDebugBreakpointsData.h b/src/DebugInterface/Symbols/CDebugBreakpointsData.h new file mode 100644 index 0000000..0a9f507 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointsData.h @@ -0,0 +1,29 @@ +#ifndef _CDebugBreakpointsData_h_ +#define _CDebugBreakpointsData_h_ + +#include "CDebugBreakpointsAddr.h" +#include "CDebugBreakpointData.h" + +class CDebugBreakpointsData : public CDebugBreakpointsAddr +{ +public: + CDebugBreakpointsData(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr); + ~CDebugBreakpointsData(); + + // factory + virtual CDebugBreakpoint *CreateEmptyBreakpoint(); + + virtual CDebugBreakpointData *EvaluateBreakpoint(int addr, int value, u32 memoryAccess); + + virtual void RenderImGui(); + + static const char *DataBreakpointComparisonToStr(DataBreakpointComparison comparison); + static DataBreakpointComparison StrToDataBreakpointComparison(const char *comparisonStr); + +protected: + int addBreakpointPopupValue; + int addBreakpointPopupComparisonMethod; +}; + +#endif + diff --git a/src/DebugInterface/Symbols/CDebugBreakpointsRasterLine.cpp b/src/DebugInterface/Symbols/CDebugBreakpointsRasterLine.cpp new file mode 100644 index 0000000..251fe5c --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointsRasterLine.cpp @@ -0,0 +1,12 @@ +#include "CDebugBreakpointsRasterLine.h" +#include "CDebugBreakpointRasterLine.h" + +CDebugBreakpointsRasterLine::CDebugBreakpointsRasterLine(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr) +: CDebugBreakpointsAddr(breakpointType, breakpointTypeStr, segment, addressFormatStr, minAddr, maxAddr) +{ +} + +CDebugBreakpoint *CDebugBreakpointsRasterLine::CreateEmptyBreakpoint() +{ + return new CDebugBreakpointRasterLine(symbols, 0); +} diff --git a/src/DebugInterface/Symbols/CDebugBreakpointsRasterLine.h b/src/DebugInterface/Symbols/CDebugBreakpointsRasterLine.h new file mode 100644 index 0000000..2ffc657 --- /dev/null +++ b/src/DebugInterface/Symbols/CDebugBreakpointsRasterLine.h @@ -0,0 +1,14 @@ +#ifndef _CDebugBreakpointsRasterLine_h_ +#define _CDebugBreakpointsRasterLine_h_ + +#include "CDebugBreakpointsAddr.h" + +class CDebugBreakpointsRasterLine : public CDebugBreakpointsAddr +{ +public: + CDebugBreakpointsRasterLine(int breakpointType, const char *breakpointTypeStr, CDebugSymbolsSegment *segment, const char *addressFormatStr, int minAddr, int maxAddr); + virtual CDebugBreakpoint *CreateEmptyBreakpoint(); +}; + +#endif + diff --git a/src/DebugInterface/Symbols/CDebugMemory.cpp b/src/DebugInterface/Symbols/CDebugMemory.cpp index e0883cc..30426da 100644 --- a/src/DebugInterface/Symbols/CDebugMemory.cpp +++ b/src/DebugInterface/Symbols/CDebugMemory.cpp @@ -102,14 +102,10 @@ void CDebugMemory::CellWrite(int addr, uint8 value, int pc, int writeRasterLine, if (cell) { - cell->MarkCellWrite(value); - - cell->writePC = pc; - cell->writeRasterLine = writeRasterLine; - cell->writeRasterCycle = writeRasterCycle; - - cell->writeCycle = debugInterface->GetCurrentCpuInstructionCycleCounter(); - cell->writeFrame = debugInterface->GetEmulationFrameNumber(); + u64 writeCycle = debugInterface->GetCurrentCpuInstructionCycleCounter(); + u32 writeFrame = debugInterface->GetEmulationFrameNumber(); + + cell->MarkCellWrite(value, writeCycle, writeFrame, pc, writeRasterLine, writeRasterCycle); } } @@ -120,9 +116,9 @@ void CDebugMemory::CellExecute(int addr, uint8 opcode) if (cell) { - cell->MarkCellExecuteCode(opcode); - cell->executeCycle = debugInterface->GetCurrentCpuInstructionCycleCounter(); - cell->executeFrame = debugInterface->GetEmulationFrameNumber(); + u64 executeCycle = debugInterface->GetCurrentCpuInstructionCycleCounter(); + u32 executeFrame = debugInterface->GetEmulationFrameNumber(); + cell->MarkCellExecuteCode(opcode, executeCycle, executeFrame); } uint8 l = opcodes[opcode].addressingLength; @@ -160,3 +156,10 @@ void CDebugMemory::CellExecute(int addr, uint8 opcode) } } +void CDebugMemory::ClearEventsAfterCycle(u64 cycle) +{ + for (int i = 0; i < numCells; i++) + { + memoryCells[i]->ClearEventsAfterCycle(cycle); + } +} diff --git a/src/DebugInterface/Symbols/CDebugMemory.h b/src/DebugInterface/Symbols/CDebugMemory.h index 94d1c62..2e09461 100644 --- a/src/DebugInterface/Symbols/CDebugMemory.h +++ b/src/DebugInterface/Symbols/CDebugMemory.h @@ -69,6 +69,8 @@ class CDebugMemory void CellWrite(int addr, uint8 value, int pc, int rasterX, int rasterY); void CellExecute(int addr, uint8 opcode); + void ClearEventsAfterCycle(u64 cycle); + private: CDebugMemoryCell **memoryCells; int numCells; diff --git a/src/DebugInterface/Symbols/CDebugMemoryCell.cpp b/src/DebugInterface/Symbols/CDebugMemoryCell.cpp index a29a1b9..da69de2 100644 --- a/src/DebugInterface/Symbols/CDebugMemoryCell.cpp +++ b/src/DebugInterface/Symbols/CDebugMemoryCell.cpp @@ -1,9 +1,13 @@ #include "CDebugMemoryCell.h" #include "CDebugMemory.h" +#include "DBG_Log.h" const float alphaSplit = 0.55f; const float colorSplit = 0.5f; +// WIP: store events in circlebuf and display (draw plots of memory value changes) +//#define EXPERIMENTAL_EVENTS_HISTORY + #if defined(RUN_ATARI) // TODO FIXME: colorExecuteCodeR @@ -119,20 +123,20 @@ inline void ColorFromValue(u8 v, float *r, float *g, float *b, float *a) /// -void _markCellReadStyleDebugger(CDebugMemoryCell *cell) +void _markMemoryCellColorReadStyleDebugger(CDebugMemoryCell *cell) { cell->sg = 0.3f; cell->sb = 1.0f; cell->sa = 1.0f; } -void _markCellWriteStyleDebugger(CDebugMemoryCell *cell) +void _markMemoryCellColorWriteStyleDebugger(CDebugMemoryCell *cell) { cell->sr = 1.0f; cell->sa = 1.0f; } -void _markCellExecuteCodeStyleDebugger(CDebugMemoryCell *cell) +void _markMemoryCellColorExecuteCodeStyleDebugger(CDebugMemoryCell *cell) { cell->sr = 0.0f; cell->sg = 1.0f; @@ -140,7 +144,7 @@ void _markCellExecuteCodeStyleDebugger(CDebugMemoryCell *cell) cell->sa = 1.0f; } -void _markCellExecuteArgumentStyleDebugger(CDebugMemoryCell *cell) +void _markMemoryCellColorExecuteArgumentStyleDebugger(CDebugMemoryCell *cell) { cell->sr = 0.0f; cell->sg = 0.3f; @@ -148,19 +152,19 @@ void _markCellExecuteArgumentStyleDebugger(CDebugMemoryCell *cell) cell->sa = 1.0f; } -void _markCellReadStyleICU(CDebugMemoryCell *cell) +void _markMemoryCellColorReadStyleICU(CDebugMemoryCell *cell) { cell->sg = 1.0f; cell->sa = 1.0f; } -void _markCellWriteStyleICU(CDebugMemoryCell *cell) +void _markMemoryCellColorWriteStyleICU(CDebugMemoryCell *cell) { cell->sr = 1.0f; cell->sa = 1.0f; } -void _markCellExecuteCodeStyleICU(CDebugMemoryCell *cell) +void _markMemoryCellColorExecuteCodeStyleICU(CDebugMemoryCell *cell) { cell->sr = 0.0f; cell->sg = 1.0f; @@ -168,7 +172,7 @@ void _markCellExecuteCodeStyleICU(CDebugMemoryCell *cell) cell->sa = 1.0f; } -void _markCellExecuteArgumentStyleICU(CDebugMemoryCell *cell) +void _markMemoryCellColorExecuteArgumentStyleICU(CDebugMemoryCell *cell) { cell->sr = 0.0f; cell->sg = 1.0f; @@ -176,25 +180,25 @@ void _markCellExecuteArgumentStyleICU(CDebugMemoryCell *cell) cell->sa = 1.0f; } -typedef void (*MarkCellReadFunc)(CDebugMemoryCell *cell); -typedef void (*MarkCellWriteFunc)(CDebugMemoryCell *cell); -typedef void (*MarkCellExecuteCodeFunc)(CDebugMemoryCell *cell); -typedef void (*MarkCellExecuteArgumentFunc)(CDebugMemoryCell *cell); +typedef void (*MarkMemoryCellColorReadFunc)(CDebugMemoryCell *cell); +typedef void (*MarkMemoryCellColorWriteFunc)(CDebugMemoryCell *cell); +typedef void (*MarkMemoryCellColorExecuteCodeFunc)(CDebugMemoryCell *cell); +typedef void (*MarkMemoryCellColorExecuteArgumentFunc)(CDebugMemoryCell *cell); -MarkCellReadFunc markCellRead = _markCellReadStyleDebugger; -MarkCellWriteFunc markCellWrite = _markCellWriteStyleDebugger; -MarkCellExecuteCodeFunc markCellExecuteCode = _markCellExecuteCodeStyleDebugger; -MarkCellExecuteArgumentFunc markCellExecuteArgument = _markCellExecuteArgumentStyleDebugger; +MarkMemoryCellColorReadFunc markMemoryCellColorRead = _markMemoryCellColorReadStyleDebugger; +MarkMemoryCellColorWriteFunc markMemoryCellColorWrite = _markMemoryCellColorWriteStyleDebugger; +MarkMemoryCellColorExecuteCodeFunc markMemoryCellColorExecuteCode = _markMemoryCellColorExecuteCodeStyleDebugger; +MarkMemoryCellColorExecuteArgumentFunc markMemoryCellColorExecuteArgument = _markMemoryCellColorExecuteArgumentStyleDebugger; void C64DebuggerSetMemoryMapMarkersStyle(uint8 memoryMapMarkersStyle) { float darken = 0.5f; if (memoryMapMarkersStyle == MEMORY_MAP_MARKER_STYLE_DEFAULT) { - markCellRead = _markCellReadStyleDebugger; - markCellWrite = _markCellWriteStyleDebugger; - markCellExecuteCode = _markCellExecuteCodeStyleDebugger; - markCellExecuteArgument = _markCellExecuteArgumentStyleDebugger; + markMemoryCellColorRead = _markMemoryCellColorReadStyleDebugger; + markMemoryCellColorWrite = _markMemoryCellColorWriteStyleDebugger; + markMemoryCellColorExecuteCode = _markMemoryCellColorExecuteCodeStyleDebugger; + markMemoryCellColorExecuteArgument = _markMemoryCellColorExecuteArgumentStyleDebugger; colorExecuteCodeR = 0.0f * darken; colorExecuteCodeG = 1.0f * darken; @@ -209,10 +213,10 @@ void C64DebuggerSetMemoryMapMarkersStyle(uint8 memoryMapMarkersStyle) } else if (memoryMapMarkersStyle == MEMORY_MAP_MARKER_STYLE_ICU) { - markCellRead = _markCellReadStyleICU; - markCellWrite = _markCellWriteStyleICU; - markCellExecuteCode = _markCellExecuteCodeStyleICU; - markCellExecuteArgument = _markCellExecuteArgumentStyleICU; + markMemoryCellColorRead = _markMemoryCellColorReadStyleICU; + markMemoryCellColorWrite = _markMemoryCellColorWriteStyleICU; + markMemoryCellColorExecuteCode = _markMemoryCellColorExecuteCodeStyleICU; + markMemoryCellColorExecuteArgument = _markMemoryCellColorExecuteArgumentStyleICU; colorExecuteCodeR = 0.0f * darken; colorExecuteCodeG = 1.0f * darken; @@ -238,6 +242,7 @@ void C64DebuggerSetMemoryMapMarkersStyle(uint8 memoryMapMarkersStyle) } +#define DEFAULT_MEMORY_CELL_HISTORY_ITEMS 32 CDebugMemoryCell::CDebugMemoryCell(int addr) { @@ -258,6 +263,12 @@ CDebugMemoryCell::CDebugMemoryCell(int addr) readPC = readRasterCycle = readRasterLine = -1; writeCycle = readCycle = executeCycle = -1; writeFrame = readFrame = executeFrame = -1; + + circlebuf_init(&valuesHistory); + circlebuf_reserve(&valuesHistory, sizeof(DebugMemoryCellHistoryValue) * DEFAULT_MEMORY_CELL_HISTORY_ITEMS); + + circlebuf_init(&executeHistory); + circlebuf_reserve(&executeHistory, sizeof(DebugMemoryCellHistoryEvent) * DEFAULT_MEMORY_CELL_HISTORY_ITEMS); } CDebugMemoryCell::~CDebugMemoryCell() @@ -294,30 +305,109 @@ void CDebugMemoryCell::ClearReadWriteDebugMarkers() void CDebugMemoryCell::MarkCellRead() { - markCellRead(this); + markMemoryCellColorRead(this); isRead = true; } void CDebugMemoryCell::MarkCellWrite(uint8 value) { //LOGTODO("remove argument marker based on previous code length"); - + MarkCellWrite(value, 0, 0, 0, 0, 0); +} + +void CDebugMemoryCell::MarkCellWrite(uint8 value, u64 writeCycle, u32 writeFrame, int writePC, int writeRasterLine, int writeRasterCycle) +{ isExecuteCode = false; isExecuteArgument = false; isWrite = true; - markCellWrite(this); + + this->writePC = writePC; + this->writeRasterLine = writeRasterLine; + this->writeRasterCycle = writeRasterCycle; + + this->writeCycle = writeCycle; + this->writeFrame = writeFrame; + + markMemoryCellColorWrite(this); + +#if defined(EXPERIMENTAL_EVENTS_HISTORY) + DebugMemoryCellHistoryValue h; + h.value = value; + h.cycle = writeCycle; + h.frame = writeFrame; + h.pc = writePC; + + if (valuesHistory.size >= DEFAULT_MEMORY_CELL_HISTORY_ITEMS * sizeof(DebugMemoryCellHistoryValue)) + { + DebugMemoryCellHistoryValue hPop; + circlebuf_pop_front(&valuesHistory, &hPop, sizeof(DebugMemoryCellHistoryValue)); + } + circlebuf_push_back(&valuesHistory, &h, sizeof(DebugMemoryCellHistoryValue)); +#endif + } -void CDebugMemoryCell::MarkCellExecuteCode(uint8 opcode) +void CDebugMemoryCell::MarkCellExecuteCode(uint8 opcode, u64 executeCycle, u32 executeFrame) { isExecuteCode = true; - markCellExecuteCode(this); + + this->executeCycle = executeCycle; + this->executeFrame = executeFrame; + + markMemoryCellColorExecuteCode(this); + +#if defined(EXPERIMENTAL_EVENTS_HISTORY) + DebugMemoryCellHistoryEvent h; + h.cycle = executeCycle; + h.frame = executeFrame; + + if (executeHistory.size >= DEFAULT_MEMORY_CELL_HISTORY_ITEMS * sizeof(DebugMemoryCellHistoryEvent)) + { + DebugMemoryCellHistoryEvent hPop; + circlebuf_pop_front(&executeHistory, &hPop, sizeof(DebugMemoryCellHistoryEvent)); + } + circlebuf_push_back(&executeHistory, &h, sizeof(DebugMemoryCellHistoryEvent)); +#endif + } void CDebugMemoryCell::MarkCellExecuteArgument() { isExecuteArgument = true; - markCellExecuteArgument(this); + markMemoryCellColorExecuteArgument(this); +} + +void CDebugMemoryCell::ClearEventsAfterCycle(u64 cycle) +{ + // value write events + while(valuesHistory.size > 0) + { + DebugMemoryCellHistoryValue h; + circlebuf_peek_back(&valuesHistory, &h, sizeof(DebugMemoryCellHistoryValue)); + if (h.cycle > cycle) + { + circlebuf_pop_back(&valuesHistory, &h, sizeof(DebugMemoryCellHistoryValue)); + } + else + { + break; + } + } + + // execute events + while(executeHistory.size > 0) + { + DebugMemoryCellHistoryEvent h; + circlebuf_peek_back(&executeHistory, &h, sizeof(DebugMemoryCellHistoryEvent)); + if (h.cycle > cycle) + { + circlebuf_pop_back(&executeHistory, &h, sizeof(DebugMemoryCellHistoryEvent)); + } + else + { + break; + } + } } void CDebugMemoryCell::UpdateCellColors(u8 v, bool showExecutePC, int pc) diff --git a/src/DebugInterface/Symbols/CDebugMemoryCell.h b/src/DebugInterface/Symbols/CDebugMemoryCell.h index fef47cc..afbd234 100644 --- a/src/DebugInterface/Symbols/CDebugMemoryCell.h +++ b/src/DebugInterface/Symbols/CDebugMemoryCell.h @@ -2,6 +2,23 @@ #define _CDebugMemoryMapCell_h_ #include "SYS_Defs.h" +#include "M_Circlebuf.h" + +struct DebugMemoryCellHistoryValue +{ + u64 cycle; + u32 frame; + int pc; + u8 value; +}; +// sizeof is 25 + +struct DebugMemoryCellHistoryEvent +{ + u64 cycle; + u32 frame; +}; +// sizeof is 12 class CDebugMemoryCell { @@ -31,9 +48,12 @@ class CDebugMemoryCell void MarkCellRead(); void MarkCellWrite(uint8 value); - void MarkCellExecuteCode(uint8 opcode); + void MarkCellWrite(uint8 value, u64 writeCycle, u32 writeFrame, int writePC, int writeRasterLine, int writeRasterCycle); + void MarkCellExecuteCode(uint8 opcode, u64 executeCycle, u32 executeFrame); void MarkCellExecuteArgument(); + void ClearEventsAfterCycle(u64 cycle); + void ClearDebugMarkers(); void ClearReadWriteDebugMarkers(); @@ -54,6 +74,14 @@ class CDebugMemoryCell // last execute cycle u64 executeCycle; u32 executeFrame; + + // history + + // previous values: cycle, frame and value + struct circlebuf valuesHistory; + + // previous executes: cycle, frame (i.e. when this address was previously executed) + struct circlebuf executeHistory; }; diff --git a/src/DebugInterface/Symbols/CDebugSymbols.cpp b/src/DebugInterface/Symbols/CDebugSymbols.cpp index e12da3b..a700f9e 100644 --- a/src/DebugInterface/Symbols/CDebugSymbols.cpp +++ b/src/DebugInterface/Symbols/CDebugSymbols.cpp @@ -463,18 +463,18 @@ void CDebugSymbols::ParseBreakpoints(CByteBuffer *byteBuffer) LOGD(".. adding breakOnPC %4.4x", address); - std::map::iterator it = currentSegment->breakpointsPC->breakpoints.find(address); + std::map::iterator it = currentSegment->breakpointsPC->breakpoints.find(address); if (it == currentSegment->breakpointsPC->breakpoints.end()) { // not found - CBreakpointAddr *addrBreakpoint = new CBreakpointAddr(address); + CDebugBreakpointAddr *addrBreakpoint = new CDebugBreakpointAddr(this, address); addrBreakpoint->actions = ADDR_BREAKPOINT_ACTION_STOP; currentSegment->breakpointsPC->breakpoints[address] = addrBreakpoint; } else { LOGD("...... exists %4.4x", address); - CBreakpointAddr *addrBreakpoint = it->second; + CDebugBreakpointAddr *addrBreakpoint = it->second; SET_BIT(addrBreakpoint->actions, ADDR_BREAKPOINT_ACTION_STOP); } } @@ -496,11 +496,11 @@ void CDebugSymbols::ParseBreakpoints(CByteBuffer *byteBuffer) LOGD(".. adding setBkg %4.4x %2.2x", address, value); - std::map::iterator it = currentSegment->breakpointsPC->breakpoints.find(address); + std::map::iterator it = currentSegment->breakpointsPC->breakpoints.find(address); if (it == currentSegment->breakpointsPC->breakpoints.end()) { // not found - CBreakpointAddr *addrBreakpoint = new CBreakpointAddr(address); + CDebugBreakpointAddr *addrBreakpoint = new CDebugBreakpointAddr(this, address); addrBreakpoint->actions = ADDR_BREAKPOINT_ACTION_SET_BACKGROUND; addrBreakpoint->data = value; currentSegment->breakpointsPC->breakpoints[address] = addrBreakpoint; @@ -508,7 +508,7 @@ void CDebugSymbols::ParseBreakpoints(CByteBuffer *byteBuffer) else { LOGD("...... exists %4.4x", address); - CBreakpointAddr *addrBreakpoint = it->second; + CDebugBreakpointAddr *addrBreakpoint = it->second; addrBreakpoint->data = value; SET_BIT(addrBreakpoint->actions, ADDR_BREAKPOINT_ACTION_SET_BACKGROUND); } @@ -567,31 +567,31 @@ void CDebugSymbols::ParseBreakpoints(CByteBuffer *byteBuffer) int value = arg->ToIntFromHex(); - MemoryBreakpointComparison memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; + DataBreakpointComparison memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; if (op->Equals("==") || op->Equals("=")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; } else if (op->Equals("!=")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_NOT_EQUAL; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_NOT_EQUAL; } else if (op->Equals("<")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_LESS; } else if (op->Equals("<=") || op->Equals("=<")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL; } else if (op->Equals(">")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_GREATER; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_GREATER; } else if (op->Equals(">=") || op->Equals("=>")) { - memBreakComparison = MemoryBreakpointComparison::MEMORY_BREAKPOINT_GREATER_OR_EQUAL; + memBreakComparison = DataBreakpointComparison::MEMORY_BREAKPOINT_GREATER_OR_EQUAL; } else { @@ -604,8 +604,8 @@ void CDebugSymbols::ParseBreakpoints(CByteBuffer *byteBuffer) op->DebugPrint("..... op="); LOGD("..... value=%2.2x", value); - CBreakpointMemory *memBreakpoint = new CBreakpointMemory(address, MEMORY_BREAKPOINT_ACCESS_WRITE, memBreakComparison, value); - currentSegment->breakpointsMemory->breakpoints[address] = memBreakpoint; + CDebugBreakpointData *memBreakpoint = new CDebugBreakpointData(this, address, MEMORY_BREAKPOINT_ACCESS_WRITE, memBreakComparison, value); + currentSegment->breakpointsData->breakpoints[address] = memBreakpoint; } else { @@ -1545,7 +1545,7 @@ void CDebugSymbols::SelectPreviousSegment() if (this->currentSegmentNum == 0) { - this->currentSegmentNum = this->segments.size()-1; + this->currentSegmentNum = (int)this->segments.size()-1; } else { @@ -1558,6 +1558,29 @@ void CDebugSymbols::SelectPreviousSegment() guiMain->UnlockMutex(); } +// returns if segment found +bool CDebugSymbols::SetSegment(CSlrString *segmentName) +{ + guiMain->LockMutex(); + debugInterface->LockMutex(); + + for (CDebugSymbolsSegment *segment : segments) + { + if (segment->name->CompareWith(segmentName)) + { + debugInterface->UnlockMutex(); + guiMain->UnlockMutex(); + currentSegment = segment; + return true; + } + } + + debugInterface->UnlockMutex(); + guiMain->UnlockMutex(); + return false; +} + + void CDebugSymbols::ClearTemporaryBreakpoint() { for (std::vector::iterator it = segments.begin(); it != segments.end(); it++) diff --git a/src/DebugInterface/Symbols/CDebugSymbols.h b/src/DebugInterface/Symbols/CDebugSymbols.h index 19f32b2..d02c7bb 100644 --- a/src/DebugInterface/Symbols/CDebugSymbols.h +++ b/src/DebugInterface/Symbols/CDebugSymbols.h @@ -52,6 +52,7 @@ class CDebugSymbols // void SelectNextSegment(); void SelectPreviousSegment(); + bool SetSegment(CSlrString *segmentName); virtual void ClearTemporaryBreakpoint(); virtual void UpdateRenderBreakpoints(); diff --git a/src/DebugInterface/Symbols/CDebugSymbolsSegment.cpp b/src/DebugInterface/Symbols/CDebugSymbolsSegment.cpp index c0d8b77..eee55b5 100644 --- a/src/DebugInterface/Symbols/CDebugSymbolsSegment.cpp +++ b/src/DebugInterface/Symbols/CDebugSymbolsSegment.cpp @@ -35,11 +35,11 @@ void CDebugSymbolsSegment::Init() breakOnPC = true; breakOnMemory = true; - breakpointsPC = new CDebugBreakpointsAddr(BREAKPOINT_TYPE_CPU_PC, "CpuPC", this, "%04X", 0, 0xFFFF); - breakpointsByType[BREAKPOINT_TYPE_CPU_PC] = breakpointsPC; + breakpointsPC = new CDebugBreakpointsAddr(BREAKPOINT_TYPE_ADDR, "CpuPC", this, "%04X", 0, 0xFFFF); + breakpointsByType[BREAKPOINT_TYPE_ADDR] = breakpointsPC; - breakpointsMemory = new CDebugBreakpointsMemory(BREAKPOINT_TYPE_MEMORY, "Memory", this, "%04X", 0, 0xFFFF); - breakpointsByType[BREAKPOINT_TYPE_MEMORY] = breakpointsMemory; + breakpointsData = new CDebugBreakpointsData(BREAKPOINT_TYPE_DATA, "Memory", this, "%04X", 0, 0xFFFF); + breakpointsByType[BREAKPOINT_TYPE_DATA] = breakpointsData; } CDebugSymbolsSegment::~CDebugSymbolsSegment() @@ -70,15 +70,15 @@ CDebugSymbolsSegment::~CDebugSymbolsSegment() void CDebugSymbolsSegment::UpdateRenderBreakpoints() { breakpointsPC->UpdateRenderBreakpoints(); - breakpointsMemory->UpdateRenderBreakpoints(); + breakpointsData->UpdateRenderBreakpoints(); } void CDebugSymbolsSegment::AddBreakpointPC(int address) { - CBreakpointAddr *addrBreakpoint = this->breakpointsPC->GetBreakpoint(address); + CDebugBreakpointAddr *addrBreakpoint = this->breakpointsPC->GetBreakpoint(address); if (addrBreakpoint == NULL) { - addrBreakpoint = new CBreakpointAddr(address); + addrBreakpoint = new CDebugBreakpointAddr(symbols, address); addrBreakpoint->actions = ADDR_BREAKPOINT_ACTION_STOP; this->breakpointsPC->AddBreakpoint(addrBreakpoint); } @@ -90,10 +90,10 @@ void CDebugSymbolsSegment::AddBreakpointPC(int address) void CDebugSymbolsSegment::AddBreakpointSetBackground(int address, int value) { - CBreakpointAddr *addrBreakpoint = this->breakpointsPC->GetBreakpoint(address); + CDebugBreakpointAddr *addrBreakpoint = this->breakpointsPC->GetBreakpoint(address); if (addrBreakpoint == NULL) { - addrBreakpoint = new CBreakpointAddr(address); + addrBreakpoint = new CDebugBreakpointAddr(address); addrBreakpoint->actions = ADDR_BREAKPOINT_ACTION_SET_BACKGROUND; addrBreakpoint->data = value; this->breakpointsPC->AddBreakpoint(addrBreakpoint); @@ -104,18 +104,18 @@ void CDebugSymbolsSegment::AddBreakpointSetBackground(int address, int value) } } -void CDebugSymbolsSegment::AddBreakpointMemory(int address, u32 memoryAccess, MemoryBreakpointComparison comparison, int value) +CDebugBreakpointData *CDebugSymbolsSegment::AddBreakpointMemory(int address, u32 memoryAccess, DataBreakpointComparison comparison, int value) { - CBreakpointMemory *memBreakpoint = new CBreakpointMemory(address, memoryAccess, comparison, value); - this->breakpointsMemory->AddBreakpoint(memBreakpoint); - + CDebugBreakpointData *memBreakpoint = new CDebugBreakpointData(address, memoryAccess, comparison, value); + this->breakpointsData->AddBreakpoint(memBreakpoint); this->breakOnMemory = true; + return memBreakpoint; } void CDebugSymbolsSegment::ClearBreakpoints() { breakpointsPC->ClearBreakpoints(); - breakpointsMemory->ClearBreakpoints(); + breakpointsData->ClearBreakpoints(); } // code labels @@ -274,28 +274,29 @@ CDebugSymbolsCodeLabel *CDebugSymbolsSegment::FindNearLabel(int address, int *of // scan labels to find most near const int maxLabelAddrOffset = c64SettingsDisassemblyNearLabelMaxOffset; -; + for (int i = 0; i < maxLabelAddrOffset; i++) { - // scan right - int addrR = address + i; - if (addrR < symbols->dataAdapter->AdapterGetDataLength()) + // scan left + int addrL = address - i; + if (addrL >= 0) { - label = FindLabel(addrR); + label = FindLabel(addrL); if (label) { - *offset = -i; + *offset = +i; return label; } } - // scan left - int addrL = address - i; - if (addrL >= 0) + + // scan right + int addrR = address + i; + if (addrR < symbols->dataAdapter->AdapterGetDataLength()) { - label = FindLabel(addrL); + label = FindLabel(addrR); if (label) { - *offset = +i; + *offset = -i; return label; } } @@ -348,7 +349,6 @@ CDebugSymbolsCodeLabel *CDebugSymbolsSegment::FindLabelByText(const char *text) { char *buf = SYS_GetCharBuf(); strncpy(buf, text, MAX_STRING_LENGTH-1); - FUN_ToUpperCaseStr(buf); u64 hashCode = GetHashCode64(buf); SYS_ReleaseCharBuf(buf); diff --git a/src/DebugInterface/Symbols/CDebugSymbolsSegment.h b/src/DebugInterface/Symbols/CDebugSymbolsSegment.h index e83eecc..61d0542 100644 --- a/src/DebugInterface/Symbols/CDebugSymbolsSegment.h +++ b/src/DebugInterface/Symbols/CDebugSymbolsSegment.h @@ -2,7 +2,12 @@ #define _CDebugSymbolsSegment_h_ #include "SYS_Defs.h" -#include "CDebugBreakpoints.h" +#include "CDebugBreakpoint.h" +#include "CDebugBreakpointAddr.h" +#include "CDebugBreakpointData.h" +#include "CDebugBreakpointRasterLine.h" +#include "CDebugBreakpointsAddr.h" +#include "CDebugBreakpointsData.h" #include "hjson.h" #include @@ -36,7 +41,7 @@ class CDebugSymbolsSegment bool breakOnPC; CDebugBreakpointsAddr *breakpointsPC; bool breakOnMemory; - CDebugBreakpointsMemory *breakpointsMemory; + CDebugBreakpointsData *breakpointsData; virtual void Init(); virtual void UpdateRenderBreakpoints(); @@ -45,7 +50,7 @@ class CDebugSymbolsSegment bool supportBreakpoints; virtual void AddBreakpointPC(int address); virtual void AddBreakpointSetBackground(int address, int value); - virtual void AddBreakpointMemory(int address, u32 memoryAccess, MemoryBreakpointComparison comparison, int value); + virtual CDebugBreakpointData *AddBreakpointMemory(int address, u32 memoryAccess, DataBreakpointComparison comparison, int value); virtual void ClearBreakpoints(); diff --git a/src/Emulators/atari800/AtariInterface/AtariWrapper.cpp b/src/Emulators/atari800/AtariInterface/AtariWrapper.cpp index fe23852..d81dff1 100644 --- a/src/Emulators/atari800/AtariInterface/AtariWrapper.cpp +++ b/src/Emulators/atari800/AtariInterface/AtariWrapper.cpp @@ -59,7 +59,7 @@ void atrd_mark_atari_cell_read(uint16 addr) if (segment) { u8 value = MEMORY_SafeGetByte(addr); - CBreakpointMemory *breakpoint = segment->breakpointsMemory->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_READ); + CDebugBreakpointData *breakpoint = segment->breakpointsData->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_READ); if (breakpoint != NULL) { debugInterfaceAtari->SetDebugMode(DEBUGGER_MODE_PAUSED); @@ -84,7 +84,7 @@ void atrd_mark_atari_cell_write(uint16 addr, uint8 value) CDebugSymbolsSegment *segment = debugInterfaceAtari->symbols->currentSegment; if (segment) { - CBreakpointMemory *breakpoint = segment->breakpointsMemory->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_WRITE); + CDebugBreakpointData *breakpoint = segment->breakpointsData->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_WRITE); if (breakpoint != NULL) { debugInterfaceAtari->SetDebugMode(DEBUGGER_MODE_PAUSED); @@ -134,7 +134,7 @@ void atrd_check_pc_breakpoint(uint16 pc) else { debugInterface->LockMutex(); - CBreakpointAddr *addrBreakpoint = segment->breakpointsPC->EvaluateBreakpoint(pc); + CDebugBreakpointAddr *addrBreakpoint = segment->breakpointsPC->EvaluateBreakpoint(pc); if (addrBreakpoint != NULL) { if (IS_SET(addrBreakpoint->actions, ADDR_BREAKPOINT_ACTION_SET_BACKGROUND)) diff --git a/src/Emulators/atari800/AtariInterface/CDebugInterfaceAtari.cpp b/src/Emulators/atari800/AtariInterface/CDebugInterfaceAtari.cpp index f831f8c..0590341 100644 --- a/src/Emulators/atari800/AtariInterface/CDebugInterfaceAtari.cpp +++ b/src/Emulators/atari800/AtariInterface/CDebugInterfaceAtari.cpp @@ -20,6 +20,7 @@ extern "C" { #endif #include "CDebugInterfaceAtari.h" +#include "CDebuggerApiAtari.h" #include "RES_ResourceManager.h" #include "CByteBuffer.h" #include "CSlrString.h" @@ -40,7 +41,6 @@ extern "C" { #include "CViewDataMap.h" #include "CDebugEventsHistory.h" #include "CDebugMemory.h" - #include "CAudioChannelAtari.h" //44100/50*4/8 @@ -48,8 +48,6 @@ extern "C" { CDebugInterfaceAtari *debugInterfaceAtari; -#if defined(RUN_ATARI) - extern "C" { void ATRD_SetConfigFileName(const char *fileName); void atrd_reset_av_sync(); @@ -180,6 +178,11 @@ const char *CDebugInterfaceAtari::GetPlatformNameString() return "Atari XL/XE"; } +const char *CDebugInterfaceAtari::GetPlatformNameEndpointString() +{ + return "atari800"; +} + float CDebugInterfaceAtari::GetEmulationFPS() { return this->numEmulationFPS; @@ -928,14 +931,14 @@ extern "C" { void Colours_SetVideoSystem(int mode); void CARTRIDGE_Remove(void); } -void CDebugInterfaceAtari::Reset() +void CDebugInterfaceAtari::ResetSoft() { LOGM("CDebugInterfaceAtari::Reset"); CPU_Reset(); } -void CDebugInterfaceAtari::HardReset() +void CDebugInterfaceAtari::ResetHard() { LOGM("CDebugInterfaceAtari::HardReset"); @@ -1019,7 +1022,7 @@ void CDebugInterfaceAtari::DetachEverything() { SIO_DisableDrive(1); CARTRIDGE_Remove(); - HardReset(); + ResetHard(); } void CDebugInterfaceAtari::DetachDriveDisk() @@ -1030,7 +1033,7 @@ void CDebugInterfaceAtari::DetachDriveDisk() void CDebugInterfaceAtari::DetachCartridge() { CARTRIDGE_Remove(); - HardReset(); + ResetHard(); } // @@ -1376,70 +1379,8 @@ void CDebugInterfaceAtari::SupportsBreakpoints(bool *writeBreakpoint, bool *read *readBreakpoint = false; } -#else -// dummy interface for atari - -CDebugInterfaceAtari::CDebugInterfaceAtari(CViewC64 *viewC64) //, uint8 *memory) -: CDebugInterface(viewC64) +CDebuggerApi *CDebugInterfaceAtari::GetDebuggerApi() { + return new CDebuggerApiAtari(this); } -CDebugInterfaceAtari::~CDebugInterfaceAtari() {} -void CDebugInterfaceAtari::RestartEmulation() {} -int CDebugInterfaceAtari::GetEmulatorType() { return EMULATOR_TYPE_ATARI800; } -CSlrString *CDebugInterfaceAtari::GetEmulatorVersionString() { return NULL; } -CSlrString *CDebugInterfaceAtari::GetPlatformNameString() { return NULL; } -void CDebugInterfaceAtari::RunEmulationThread() {} -void CDebugInterfaceAtari::DoFrame() {} -void CDebugInterfaceAtari::SetByte(uint16 addr, uint8 val) {} -uint8 CDebugInterfaceAtari::GetByte(uint16 addr) { return 0; } -void CDebugInterfaceAtari::GetMemory(uint8 *buffer, int addrStart, int addrEnd) {} -int CDebugInterfaceAtari::GetCpuPC() { return -1; } -void CDebugInterfaceAtari::GetWholeMemoryMap(uint8 *buffer) {} -void CDebugInterfaceAtari::GetWholeMemoryMapFromRam(uint8 *buffer) {} -void CDebugInterfaceAtari::GetCpuRegs(u16 *PC, u8 *A,u8 *X, u8 *Y, u8 *P,u8 *S,u8 *IRQ) {} -int CDebugInterfaceAtari::GetScreenSizeX() { return -1; } -int CDebugInterfaceAtari::GetScreenSizeY() { return -1; } -void CDebugInterfaceAtari::SetDebugMode(uint8 debugMode) {} -uint8 CDebugInterfaceAtari::GetDebugMode() { return 0; } -void CDebugInterfaceAtari::MakeJmpNoReset(CDataAdapter *dataAdapter, uint16 addr) {} -void CDebugInterfaceAtari::MakeJmpAndReset(uint16 addr) {} -int CDebugInterfaceAtari::MapMTKeyToAKey(uint32 mtKeyCode, int shiftctrl, int key_control) { return -1; } -bool CDebugInterfaceAtari::KeyboardDown(uint32 mtKeyCode) { return false; } -bool CDebugInterfaceAtari::KeyboardUp(uint32 mtKeyCode) { return false; } -void CDebugInterfaceAtari::JoystickDown(int port, uint32 axis) {} -void CDebugInterfaceAtari::JoystickUp(int port, uint32 axis) {} -void CDebugInterfaceAtari::Reset() {} -void CDebugInterfaceAtari::HardReset() {} -bool CDebugInterfaceAtari::LoadExecutable(char *fullFilePath) { return false; } -bool CDebugInterfaceAtari::MountDisk(char *fullFilePath, int diskNo, bool readOnly) { return false; } -bool CDebugInterfaceAtari::InsertCartridge(char *fullFilePath, bool readOnly) { return false; } -bool CDebugInterfaceAtari::AttachTape(char *fullFilePath, bool readOnly) { return false; } -bool CDebugInterfaceAtari::LoadFullSnapshot(char *filePath) { return false; } -void CDebugInterfaceAtari::SaveFullSnapshot(char *filePath) {} -void CDebugInterfaceAtari::SetVideoSystem(u8 videoSystem) {} -void CDebugInterfaceAtari::SetMachineType(u8 machineType) {} -void CDebugInterfaceAtari::SetRamSizeOption(u8 ramSizeOption) {} -CViewDisassembly *CDebugInterfaceAtari::GetViewMainCpuDisassembly() { return NULL; } -CViewDisassembly *CDebugInterfaceAtari::GetViewDriveDisassembly(int driveNo) { return NULL; } -CDataAdapter *CDebugInterfaceAtari::GetDataAdapter() { return NULL; } -float CDebugInterfaceAtari::GetEmulationFPS() { return 0; } -u64 CDebugInterfaceAtari::GetMainCpuCycleCounter() { return 0; } -u64 CDebugInterfaceAtari::GetPreviousCpuInstructionCycleCounter() { return 0; } -void CDebugInterfaceAtari::ResetMainCpuDebugCycleCounter() {} -u64 CDebugInterfaceAtari::GetMainCpuDebugCycleCounter() { return 0; } -bool CDebugInterfaceAtari::IsDriveDirtyForSnapshot() { return false; } -void CDebugInterfaceAtari::ClearDriveDirtyForSnapshotFlag() {} -bool CDebugInterfaceAtari::LoadChipsSnapshotSynced(CByteBuffer *byteBuffer) { return NULL; } -bool CDebugInterfaceAtari::SaveChipsSnapshotSynced(CByteBuffer *byteBuffer) { return NULL; } -bool CDebugInterfaceAtari::LoadDiskDataSnapshotSynced(CByteBuffer *byteBuffer) { return NULL; } -bool CDebugInterfaceAtari::SaveDiskDataSnapshotSynced(CByteBuffer *byteBuffer) { return NULL; } -void CDebugInterfaceAtari::RefreshScreenNoCallback() {} -void CDebugInterfaceAtari::DetachEverything() {} -void CDebugInterfaceAtari::DetachDriveDisk() {} -void CDebugInterfaceAtari::DetachCartridge() {} -void CDebugInterfaceAtari::SetPokeyStereo(bool isStereo) {} -bool CDebugInterfaceAtari::GetSettingIsWarpSpeed() { return false; } -void CDebugInterfaceAtari::SetSettingIsWarpSpeed(bool isWarpSpeed) {} - -#endif diff --git a/src/Emulators/atari800/AtariInterface/CDebugInterfaceAtari.h b/src/Emulators/atari800/AtariInterface/CDebugInterfaceAtari.h index c5e2831..efb8719 100644 --- a/src/Emulators/atari800/AtariInterface/CDebugInterfaceAtari.h +++ b/src/Emulators/atari800/AtariInterface/CDebugInterfaceAtari.h @@ -27,6 +27,7 @@ class CDebugInterfaceAtari : public CDebugInterface virtual int GetEmulatorType(); virtual CSlrString *GetEmulatorVersionString(); virtual const char *GetPlatformNameString(); + virtual const char *GetPlatformNameEndpointString(); virtual float GetEmulationFPS(); float numEmulationFPS; @@ -60,8 +61,8 @@ class CDebugInterfaceAtari : public CDebugInterface virtual uint8 GetDebugMode(); // - virtual void Reset(); - virtual void HardReset(); + virtual void ResetSoft(); + virtual void ResetHard(); // this is main emulation cpu cycle counter virtual u64 GetMainCpuCycleCounter(); @@ -149,6 +150,8 @@ class CDebugInterfaceAtari : public CDebugInterface virtual void SupportsBreakpoints(bool *writeBreakpoint, bool *readBreakpoint); + virtual CDebuggerApi *GetDebuggerApi(); + // virtual uint8 GetByteFromRamC64(uint16 addr); // virtual void MakeJmpC64(uint16 addr); diff --git a/src/Emulators/atari800/AtariInterface/CDebuggerApiAtari.cpp b/src/Emulators/atari800/AtariInterface/CDebuggerApiAtari.cpp index 6b9bb75..41decb2 100644 --- a/src/Emulators/atari800/AtariInterface/CDebuggerApiAtari.cpp +++ b/src/Emulators/atari800/AtariInterface/CDebuggerApiAtari.cpp @@ -14,7 +14,7 @@ CDebuggerApiAtari::CDebuggerApiAtari(CDebugInterface *debugInterface) : CDebuggerApi(debugInterface) { - this->debugInterfaceNes = (CDebugInterfaceNes*)debugInterface; + this->debugInterfaceAtari = (CDebugInterfaceNes*)debugInterface; } void CDebuggerApiAtari::StartThread(CSlrThread *run) @@ -24,105 +24,100 @@ void CDebuggerApiAtari::StartThread(CSlrThread *run) void CDebuggerApiAtari::CreateNewPicture(u8 mode, u8 backgroundColor) { - SYS_FatalExit("CDebuggerApiAtari::CreateNewPicture: not implemented"); + LOGTODO("CDebuggerApiAtari::CreateNewPicture: not implemented"); } void CDebuggerApiAtari::ClearScreen() { - SYS_FatalExit("CDebuggerApiAtari::ClearScreen: not implemented"); + LOGTODO("CDebuggerApiAtari::ClearScreen: not implemented"); } bool CDebuggerApiAtari::ConvertImageToScreen(char *filePath) { - SYS_FatalExit("CDebuggerApiAtari::ConvertImageToScreen: not implemented"); + LOGTODO("CDebuggerApiAtari::ConvertImageToScreen: not implemented"); return false; } bool CDebuggerApiAtari::ConvertImageToScreen(CImageData *imageData) { - SYS_FatalExit("CDebuggerApiAtari::ConvertImageToScreen: not implemented"); + LOGTODO("CDebuggerApiAtari::ConvertImageToScreen: not implemented"); return false; } void CDebuggerApiAtari::ClearReferenceImage() { - SYS_FatalExit("CDebuggerApiAtari::ClearReferenceImage: not implemented"); + LOGTODO("CDebuggerApiAtari::ClearReferenceImage: not implemented"); } void CDebuggerApiAtari::LoadReferenceImage(char *filePath) { - SYS_FatalExit("CDebuggerApiAtari::LoadReferenceImage: not implemented"); + LOGTODO("CDebuggerApiAtari::LoadReferenceImage: not implemented"); } void CDebuggerApiAtari::LoadReferenceImage(CImageData *imageData) { - SYS_FatalExit("CDebuggerApiAtari::LoadReferenceImage: not implemented"); + LOGTODO("CDebuggerApiAtari::LoadReferenceImage: not implemented"); } void CDebuggerApiAtari::SetReferenceImageLayerVisible(bool isVisible) { - SYS_FatalExit("CDebuggerApiAtari::SetReferenceImageLayerVisible: not implemented"); + LOGTODO("CDebuggerApiAtari::SetReferenceImageLayerVisible: not implemented"); } CImageData *CDebuggerApiAtari::GetReferenceImage() { - SYS_FatalExit("CDebuggerApiAtari::GetReferenceImage: not implemented"); + LOGTODO("CDebuggerApiAtari::GetReferenceImage: not implemented"); return NULL; } CImageData *CDebuggerApiAtari::GetScreenImage(int *width, int *height) { - SYS_FatalExit("CDebuggerApiAtari::GetScreenImage: not implemented"); + LOGTODO("CDebuggerApiAtari::GetScreenImage: not implemented"); return NULL; } CImageData *CDebuggerApiAtari::GetScreenImageWithoutBorders() { - SYS_FatalExit("CDebuggerApiAtari::GetScreenImageWithoutBorders: not implemented"); + LOGTODO("CDebuggerApiAtari::GetScreenImageWithoutBorders: not implemented"); return NULL; } void CDebuggerApiAtari::ZoomDisplay(float newScale) { - SYS_FatalExit("CDebuggerApiAtari::ZoomDisplay: not implemented"); + LOGTODO("CDebuggerApiAtari::ZoomDisplay: not implemented"); } u8 CDebuggerApiAtari::PaintPixel(int x, int y, u8 color) { - SYS_FatalExit("CDebuggerApiAtari::PaintPixel: not implemented"); + LOGTODO("CDebuggerApiAtari::PaintPixel: not implemented"); return PAINT_RESULT_ERROR; } u8 CDebuggerApiAtari::PaintReferenceImagePixel(int x, int y, u8 color) { - SYS_FatalExit("CDebuggerApiAtari::PaintReferenceImagePixel: not implemented"); + LOGTODO("CDebuggerApiAtari::PaintReferenceImagePixel: not implemented"); return PAINT_RESULT_ERROR; } u8 CDebuggerApiAtari::PaintReferenceImagePixel(int x, int y, u8 r, u8 g, u8 b, u8 a) { - SYS_FatalExit("CDebuggerApiAtari::PaintReferenceImagePixel: not implemented"); + LOGTODO("CDebuggerApiAtari::PaintReferenceImagePixel: not implemented"); return PAINT_RESULT_ERROR; } -void CDebuggerApiAtari::ResetMachine() -{ - SYS_FatalExit("CDebuggerApiAtari::ResetMachine: not implemented"); -} - void CDebuggerApiAtari::MakeJmp(int addr) { - SYS_FatalExit("CDebuggerApiAtari::MakeJMP: not implemented"); + LOGTODO("CDebuggerApiAtari::MakeJMP: not implemented"); } void CDebuggerApiAtari::SetByteWithIo(int addr, u8 v) { - SYS_FatalExit("CDebuggerApiAtari::SetByteWithIo: not implemented"); + LOGTODO("CDebuggerApiAtari::SetByteWithIo: not implemented"); } void CDebuggerApiAtari::SetByteToRam(int addr, u8 v) { - SYS_FatalExit("CDebuggerApiAtari::SetByteToRam: not implemented"); + LOGTODO("CDebuggerApiAtari::SetByteToRam: not implemented"); } void CDebuggerApiAtari::SetWord(int addr, u16 v) @@ -133,24 +128,29 @@ void CDebuggerApiAtari::SetWord(int addr, u16 v) void CDebuggerApiAtari::DetachEverything() { - SYS_FatalExit("CDebuggerApiAtari::DetachEverything: not implemented"); + debugInterfaceAtari->DetachEverything(); } int CDebuggerApiAtari::Assemble(int addr, char *assembleText) { - SYS_FatalExit("CDebuggerApiAtari::Assemble: not implemented"); + LOGTODO("CDebuggerApiAtari::Assemble: not implemented"); return -1; } -void CDebuggerApiAtari::SaveBinary(u16 fromAddr, u16 toAddr, char *filePath) +nlohmann::json CDebuggerApiAtari::GetCpuStatusJson() { - // TODO: we can implement this generic via SetRam(... - SYS_FatalExit("CDebuggerApiAtari::SaveBinary: not implemented"); -} + u16 pc; + u8 a, x, y, p, sp, irq; + debugInterfaceAtari->GetCpuRegs(&pc, &a, &x, &y, &p, &sp, &irq); + + nlohmann::json cpuStatus; + cpuStatus["pc"] = pc; + cpuStatus["a"] = a; + cpuStatus["x"] = x; + cpuStatus["y"] = y; + cpuStatus["sp"] = sp; + cpuStatus["p"] = p; + cpuStatus["irq"] = irq; -int CDebuggerApiAtari::LoadBinary(u16 fromAddr, char *filePath) -{ - // TODO: we can implement this generic via SetRam(... - SYS_FatalExit("CDebuggerApiAtari::LoadBinary: not implemented"); - return -1; + return cpuStatus; } diff --git a/src/Emulators/atari800/AtariInterface/CDebuggerApiAtari.h b/src/Emulators/atari800/AtariInterface/CDebuggerApiAtari.h index 44cda31..402d482 100644 --- a/src/Emulators/atari800/AtariInterface/CDebuggerApiAtari.h +++ b/src/Emulators/atari800/AtariInterface/CDebuggerApiAtari.h @@ -16,9 +16,7 @@ class CDebuggerApiAtari : public CDebuggerApi { public: CDebuggerApiAtari(CDebugInterface *debugInterface); - CDebugInterfaceNes *debugInterfaceNes; - - virtual void ResetMachine(); + CDebugInterfaceNes *debugInterfaceAtari; virtual void CreateNewPicture(u8 mode, u8 backgroundColor); virtual void StartThread(CSlrThread *run); @@ -58,10 +56,9 @@ class CDebuggerApiAtari : public CDebuggerApi // virtual int Assemble(int addr, char *assembleText); - + // - virtual void SaveBinary(u16 fromAddr, u16 toAddr, char *fileName); - virtual int LoadBinary(u16 fromAddr, char *filePath); + virtual nlohmann::json GetCpuStatusJson(); }; #endif diff --git a/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNes.cpp b/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNes.cpp index 989ffba..79d3745 100644 --- a/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNes.cpp +++ b/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNes.cpp @@ -18,6 +18,7 @@ #include "EmulatorsConfig.h" #include "CDebugInterfaceNes.h" #include "CDebugInterfaceNesTasks.h" +#include "CDebuggerApiNestopia.h" #include "RES_ResourceManager.h" #include "CByteBuffer.h" #include "CSlrString.h" @@ -156,6 +157,11 @@ const char *CDebugInterfaceNes::GetPlatformNameString() return "NES"; } +const char *CDebugInterfaceNes::GetPlatformNameEndpointString() +{ + return "nes"; +} + bool CDebugInterfaceNes::IsPal() { return nesd_is_pal(); @@ -449,17 +455,17 @@ void CDebugInterfaceNes::ClearDebugMarkers() symbols->memory->ClearDebugMarkers(); } -void CDebugInterfaceNes::Reset() +void CDebugInterfaceNes::ResetSoft() { LOGM("CDebugInterfaceNes::Reset"); CDebugInterfaceNesTaskReset *task = new CDebugInterfaceNesTaskReset(this); this->AddCpuDebugInterruptTask(task); } -void CDebugInterfaceNes::HardReset() +void CDebugInterfaceNes::ResetHard() { - LOGM("CDebugInterfaceNes::HardReset"); - CDebugInterfaceNesTaskHardReset *task = new CDebugInterfaceNesTaskHardReset(this); + LOGM("CDebugInterfaceNes::ResetHard"); + CDebugInterfaceNesTaskResetHard *task = new CDebugInterfaceNesTaskResetHard(this); this->AddCpuDebugInterruptTask(task); } @@ -471,6 +477,16 @@ void CDebugInterfaceNes::ResetClockCounters() machine.cpu.nesdMainCpuPreviousInstructionCycle = 0; } +void CDebugInterfaceNes::DetachEverything() +{ + this->LockMutex(); + + nesd_unload_cartridge(); + ResetHard(); + + this->UnlockMutex(); +} + bool CDebugInterfaceNes::LoadExecutable(char *fullFilePath) { LOGM("CDebugInterfaceNes::LoadExecutable: %s", fullFilePath); @@ -735,3 +751,8 @@ void CDebugInterfaceNes::SupportsBreakpoints(bool *writeBreakpoint, bool *readBr *readBreakpoint = false; } +CDebuggerApi *CDebugInterfaceNes::GetDebuggerApi() +{ + return new CDebuggerApiNestopia(this); +} + diff --git a/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNes.h b/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNes.h index 6b6bbe8..3497f2b 100644 --- a/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNes.h +++ b/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNes.h @@ -28,6 +28,7 @@ class CDebugInterfaceNes : public CDebugInterface virtual int GetEmulatorType(); virtual CSlrString *GetEmulatorVersionString(); virtual const char *GetPlatformNameString(); + virtual const char *GetPlatformNameEndpointString(); virtual bool IsPal(); virtual double GetCpuClockFrequency(); @@ -72,8 +73,8 @@ class CDebugInterfaceNes : public CDebugInterface virtual uint8 GetDebugMode(); // - virtual void Reset(); - virtual void HardReset(); + virtual void ResetSoft(); + virtual void ResetHard(); // this is main emulation cpu cycle counter virtual u64 GetMainCpuCycleCounter(); @@ -88,6 +89,8 @@ class CDebugInterfaceNes : public CDebugInterface virtual bool InsertCartridge(char *fullFilePath); virtual bool AttachTape(char *fullFilePath, bool readOnly); + virtual void DetachEverything(); + // virtual bool LoadFullSnapshot(char *filePath); virtual void SaveFullSnapshot(char *filePath); @@ -143,6 +146,8 @@ class CDebugInterfaceNes : public CDebugInterface virtual void StepOneCycle(); virtual void SupportsBreakpoints(bool *writeBreakpoint, bool *readBreakpoint); + + virtual CDebuggerApi *GetDebuggerApi(); // virtual uint8 GetByteFromRamC64(uint16 addr); // virtual void MakeJmpC64(uint16 addr); diff --git a/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNesTasks.cpp b/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNesTasks.cpp index 7ccc10e..f642cd9 100644 --- a/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNesTasks.cpp +++ b/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNesTasks.cpp @@ -89,12 +89,12 @@ void CDebugInterfaceNesTaskReset::ExecuteTask() } // -CDebugInterfaceNesTaskHardReset::CDebugInterfaceNesTaskHardReset(CDebugInterfaceNes *debugInterface) +CDebugInterfaceNesTaskResetHard::CDebugInterfaceNesTaskResetHard(CDebugInterfaceNes *debugInterface) { this->debugInterface = debugInterface; } -void CDebugInterfaceNesTaskHardReset::ExecuteTask() +void CDebugInterfaceNesTaskResetHard::ExecuteTask() { nesd_reset(); diff --git a/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNesTasks.h b/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNesTasks.h index 32794bb..db01814 100644 --- a/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNesTasks.h +++ b/src/Emulators/nestopiaue/NestopiaInterface/CDebugInterfaceNesTasks.h @@ -39,10 +39,10 @@ class CDebugInterfaceNesTaskReset : public CDebugInterfaceTask virtual void ExecuteTask(); }; -class CDebugInterfaceNesTaskHardReset : public CDebugInterfaceTask +class CDebugInterfaceNesTaskResetHard : public CDebugInterfaceTask { public: - CDebugInterfaceNesTaskHardReset(CDebugInterfaceNes *debugInterface); + CDebugInterfaceNesTaskResetHard(CDebugInterfaceNes *debugInterface); CDebugInterfaceNes *debugInterface; virtual void ExecuteTask(); }; diff --git a/src/Emulators/nestopiaue/NestopiaInterface/CDebuggerApiNestopia.cpp b/src/Emulators/nestopiaue/NestopiaInterface/CDebuggerApiNestopia.cpp index 7a6b015..05c8491 100644 --- a/src/Emulators/nestopiaue/NestopiaInterface/CDebuggerApiNestopia.cpp +++ b/src/Emulators/nestopiaue/NestopiaInterface/CDebuggerApiNestopia.cpp @@ -24,105 +24,100 @@ void CDebuggerApiNestopia::StartThread(CSlrThread *run) void CDebuggerApiNestopia::CreateNewPicture(u8 mode, u8 backgroundColor) { - SYS_FatalExit("CDebuggerApiNestopia::CreateNewPicture: not implemented"); + LOGTODO("CDebuggerApiNestopia::CreateNewPicture: not implemented"); } void CDebuggerApiNestopia::ClearScreen() { - SYS_FatalExit("CDebuggerApiNestopia::ClearScreen: not implemented"); + LOGTODO("CDebuggerApiNestopia::ClearScreen: not implemented"); } bool CDebuggerApiNestopia::ConvertImageToScreen(char *filePath) { - SYS_FatalExit("CDebuggerApiNestopia::ConvertImageToScreen: not implemented"); + LOGTODO("CDebuggerApiNestopia::ConvertImageToScreen: not implemented"); return false; } bool CDebuggerApiNestopia::ConvertImageToScreen(CImageData *imageData) { - SYS_FatalExit("CDebuggerApiNestopia::ConvertImageToScreen: not implemented"); + LOGTODO("CDebuggerApiNestopia::ConvertImageToScreen: not implemented"); return false; } void CDebuggerApiNestopia::ClearReferenceImage() { - SYS_FatalExit("CDebuggerApiNestopia::ClearReferenceImage: not implemented"); + LOGTODO("CDebuggerApiNestopia::ClearReferenceImage: not implemented"); } void CDebuggerApiNestopia::LoadReferenceImage(char *filePath) { - SYS_FatalExit("CDebuggerApiNestopia::LoadReferenceImage: not implemented"); + LOGTODO("CDebuggerApiNestopia::LoadReferenceImage: not implemented"); } void CDebuggerApiNestopia::LoadReferenceImage(CImageData *imageData) { - SYS_FatalExit("CDebuggerApiNestopia::LoadReferenceImage: not implemented"); + LOGTODO("CDebuggerApiNestopia::LoadReferenceImage: not implemented"); } void CDebuggerApiNestopia::SetReferenceImageLayerVisible(bool isVisible) { - SYS_FatalExit("CDebuggerApiNestopia::SetReferenceImageLayerVisible: not implemented"); + LOGTODO("CDebuggerApiNestopia::SetReferenceImageLayerVisible: not implemented"); } CImageData *CDebuggerApiNestopia::GetReferenceImage() { - SYS_FatalExit("CDebuggerApiNestopia::GetReferenceImage: not implemented"); + LOGTODO("CDebuggerApiNestopia::GetReferenceImage: not implemented"); return NULL; } CImageData *CDebuggerApiNestopia::GetScreenImage(int *width, int *height) { - SYS_FatalExit("CDebuggerApiNestopia::GetScreenImage: not implemented"); + LOGTODO("CDebuggerApiNestopia::GetScreenImage: not implemented"); return NULL; } CImageData *CDebuggerApiNestopia::GetScreenImageWithoutBorders() { - SYS_FatalExit("CDebuggerApiNestopia::GetScreenImageWithoutBorders: not implemented"); + LOGTODO("CDebuggerApiNestopia::GetScreenImageWithoutBorders: not implemented"); return NULL; } void CDebuggerApiNestopia::ZoomDisplay(float newScale) { - SYS_FatalExit("CDebuggerApiNestopia::ZoomDisplay: not implemented"); + LOGTODO("CDebuggerApiNestopia::ZoomDisplay: not implemented"); } u8 CDebuggerApiNestopia::PaintPixel(int x, int y, u8 color) { - SYS_FatalExit("CDebuggerApiNestopia::PaintPixel: not implemented"); + LOGTODO("CDebuggerApiNestopia::PaintPixel: not implemented"); return PAINT_RESULT_ERROR; } u8 CDebuggerApiNestopia::PaintReferenceImagePixel(int x, int y, u8 color) { - SYS_FatalExit("CDebuggerApiNestopia::PaintReferenceImagePixel: not implemented"); + LOGTODO("CDebuggerApiNestopia::PaintReferenceImagePixel: not implemented"); return PAINT_RESULT_ERROR; } u8 CDebuggerApiNestopia::PaintReferenceImagePixel(int x, int y, u8 r, u8 g, u8 b, u8 a) { - SYS_FatalExit("CDebuggerApiNestopia::PaintReferenceImagePixel: not implemented"); + LOGTODO("CDebuggerApiNestopia::PaintReferenceImagePixel: not implemented"); return PAINT_RESULT_ERROR; } -void CDebuggerApiNestopia::ResetMachine() -{ - SYS_FatalExit("CDebuggerApiNestopia::ResetMachine: not implemented"); -} - void CDebuggerApiNestopia::MakeJmp(int addr) { - SYS_FatalExit("CDebuggerApiNestopia::MakeJMP: not implemented"); + LOGTODO("CDebuggerApiNestopia::MakeJMP: not implemented"); } void CDebuggerApiNestopia::SetByteWithIo(int addr, u8 v) { - SYS_FatalExit("CDebuggerApiNestopia::SetByteWithIo: not implemented"); + LOGTODO("CDebuggerApiNestopia::SetByteWithIo: not implemented"); } void CDebuggerApiNestopia::SetByteToRam(int addr, u8 v) { - SYS_FatalExit("CDebuggerApiNestopia::SetByteToRam: not implemented"); + LOGTODO("CDebuggerApiNestopia::SetByteToRam: not implemented"); } void CDebuggerApiNestopia::SetWord(int addr, u16 v) @@ -133,24 +128,29 @@ void CDebuggerApiNestopia::SetWord(int addr, u16 v) void CDebuggerApiNestopia::DetachEverything() { - SYS_FatalExit("CDebuggerApiNestopia::DetachEverything: not implemented"); + debugInterfaceNes->DetachEverything(); } int CDebuggerApiNestopia::Assemble(int addr, char *assembleText) { - SYS_FatalExit("CDebuggerApiNestopia::Assemble: not implemented"); + LOGTODO("CDebuggerApiNestopia::Assemble: not implemented"); return -1; } -void CDebuggerApiNestopia::SaveBinary(u16 fromAddr, u16 toAddr, char *filePath) +nlohmann::json CDebuggerApiNestopia::GetCpuStatusJson() { - // TODO: we can implement this generic via SetRam(... - SYS_FatalExit("CDebuggerApiNestopia::SaveBinary: not implemented"); -} + u16 pc; + u8 a, x, y, p, sp, irq; + debugInterfaceNes->GetCpuRegs(&pc, &a, &x, &y, &p, &sp, &irq); + + nlohmann::json cpuStatus; + cpuStatus["pc"] = pc; + cpuStatus["a"] = a; + cpuStatus["x"] = x; + cpuStatus["y"] = y; + cpuStatus["sp"] = sp; + cpuStatus["p"] = p; + cpuStatus["irq"] = irq; -int CDebuggerApiNestopia::LoadBinary(u16 fromAddr, char *filePath) -{ - // TODO: we can implement this generic via SetRam(... - SYS_FatalExit("CDebuggerApiNestopia::LoadBinary: not implemented"); - return -1; + return cpuStatus; } diff --git a/src/Emulators/nestopiaue/NestopiaInterface/CDebuggerApiNestopia.h b/src/Emulators/nestopiaue/NestopiaInterface/CDebuggerApiNestopia.h index 5c7404b..62325d6 100644 --- a/src/Emulators/nestopiaue/NestopiaInterface/CDebuggerApiNestopia.h +++ b/src/Emulators/nestopiaue/NestopiaInterface/CDebuggerApiNestopia.h @@ -18,8 +18,6 @@ class CDebuggerApiNestopia : public CDebuggerApi CDebuggerApiNestopia(CDebugInterface *debugInterface); CDebugInterfaceNes *debugInterfaceNes; - virtual void ResetMachine(); - virtual void CreateNewPicture(u8 mode, u8 backgroundColor); virtual void StartThread(CSlrThread *run); @@ -60,8 +58,7 @@ class CDebuggerApiNestopia : public CDebuggerApi virtual int Assemble(int addr, char *assembleText); // - virtual void SaveBinary(u16 fromAddr, u16 toAddr, char *fileName); - virtual int LoadBinary(u16 fromAddr, char *filePath); + virtual nlohmann::json GetCpuStatusJson(); }; #endif diff --git a/src/Emulators/nestopiaue/NestopiaInterface/NesWrapper.cpp b/src/Emulators/nestopiaue/NestopiaInterface/NesWrapper.cpp index a043b22..681c2b1 100644 --- a/src/Emulators/nestopiaue/NestopiaInterface/NesWrapper.cpp +++ b/src/Emulators/nestopiaue/NestopiaInterface/NesWrapper.cpp @@ -326,6 +326,33 @@ bool nesd_insert_cartridge(char *filePath) return true; } +bool nesd_unload_cartridge() +{ + debugInterfaceNes->LockMutex(); + nesd_sound_lock("nesd_insert_cartridge"); + + machine->Unload(); + + if (machine->Unload()) + { + LOGError("Nestopia: Unload failed"); + nesd_sound_unlock("nesd_insert_cartridge"); + debugInterfaceNes->UnlockMutex(); + return false; + } + + nesd_set_defaults(); + machine->Power(true); + + debugInterfaceNes->ResetEmulationFrameCounter(); + debugInterfaceNes->ResetClockCounters(); + + nesd_sound_unlock("nesd_insert_cartridge"); + debugInterfaceNes->UnlockMutex(); + return true; + +} + // threaded frame render sync is queueing samples, meaning sync is too fast... but why? see NestopiaUE_Run struct circlebuf audioBufferCircle; @@ -1558,7 +1585,7 @@ void nesd_mark_cell_read(uint16 addr) if (segment) { u8 value = nesd_peek_safe_io(addr); - CBreakpointMemory *breakpoint = segment->breakpointsMemory->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_READ); + CDebugBreakpointData *breakpoint = segment->breakpointsData->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_READ); if (breakpoint != NULL) { debugInterfaceNes->SetDebugMode(DEBUGGER_MODE_PAUSED); @@ -1583,7 +1610,7 @@ void nesd_mark_cell_write(uint16 addr, uint8 value) CDebugSymbolsSegment *segment = debugInterfaceNes->symbols->currentSegment; if (segment) { - CBreakpointMemory *breakpoint = segment->breakpointsMemory->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_WRITE); + CDebugBreakpointData *breakpoint = segment->breakpointsData->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_WRITE); if (breakpoint != NULL) { debugInterfaceNes->SetDebugMode(DEBUGGER_MODE_PAUSED); @@ -1627,7 +1654,7 @@ void nesd_check_pc_breakpoint(uint16 pc) else { debugInterface->LockMutex(); - CBreakpointAddr *addrBreakpoint = segment->breakpointsPC->EvaluateBreakpoint(pc); + CDebugBreakpointAddr *addrBreakpoint = segment->breakpointsPC->EvaluateBreakpoint(pc); if (addrBreakpoint != NULL) { diff --git a/src/Emulators/nestopiaue/NestopiaInterface/NesWrapper.h b/src/Emulators/nestopiaue/NestopiaInterface/NesWrapper.h index 389008e..004b033 100644 --- a/src/Emulators/nestopiaue/NestopiaInterface/NesWrapper.h +++ b/src/Emulators/nestopiaue/NestopiaInterface/NesWrapper.h @@ -13,6 +13,7 @@ bool NestopiaUE_PostInitialize(); bool NestopiaUE_Run(); bool nesd_insert_cartridge(char *filePath); +bool nesd_unload_cartridge(); void nesd_reset(); unsigned char *nesd_get_ram(); diff --git a/src/Emulators/vice/ViceInterface/Adapters/CDataAdapterViceC64Reu.cpp b/src/Emulators/vice/ViceInterface/Adapters/CDataAdapterViceC64Reu.cpp index edecdce..48c0110 100644 --- a/src/Emulators/vice/ViceInterface/Adapters/CDataAdapterViceC64Reu.cpp +++ b/src/Emulators/vice/ViceInterface/Adapters/CDataAdapterViceC64Reu.cpp @@ -1,6 +1,7 @@ #include "CDebugInterfaceVice.h" #include "CDataAdapterViceC64Reu.h" +// TODO: not implemented REU data adapter CDataAdapterViceC64Reu::CDataAdapterViceC64Reu(CDebugSymbols *debugSymbols) : CDebugDataAdapter("ViceReu", debugSymbols) { diff --git a/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.cpp b/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.cpp index 4505119..02da9c6 100644 --- a/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.cpp +++ b/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.cpp @@ -32,6 +32,7 @@ extern "C" { #include "RES_ResourceManager.h" #include "CDebugInterfaceVice.h" +#include "CDebuggerApiVice.h" #include "CDebugMemory.h" #include "CByteBuffer.h" #include "CSlrString.h" @@ -61,6 +62,7 @@ extern "C" { #include "CWaveformData.h" #include "CViewDataMap.h" #include "CDebugEventsHistory.h" +#include "CDebuggerServerApiVice.h" // 44100/50*5 #define SID_WAVEFORM_LENGTH 4410*8 @@ -340,7 +342,7 @@ void CDebugInterfaceVice::RunEmulationThread() // update sid type SetSidTypeAsync(c64SettingsSIDEngineModel); - + // audioChannel->Start(); vice_main_loop_run(); @@ -551,7 +553,7 @@ void CDebugInterfaceVice::ClearDebugMarkers() symbolsCartridgeC64->memory->ClearDebugMarkers(); } -void CDebugInterfaceVice::Reset() +void CDebugInterfaceVice::ResetSoft() { vsync_suspend_speed_eval(); @@ -570,15 +572,17 @@ void CDebugInterfaceVice::Reset() } } -void CDebugInterfaceVice::HardReset() +void CDebugInterfaceVice::ResetHard() { - LOGD("CDebugInterfaceVice::HardReset"); + LOGD("CDebugInterfaceVice::ResetHard"); vsync_suspend_speed_eval(); keyboard_clear_keymatrix(); machine_trigger_reset(MACHINE_RESET_MODE_HARD); this->ResetEmulationFrameCounter(); + this->ClearHistory(); + c64d_maincpu_clk = 6; c64d_update_c64_model(); @@ -716,6 +720,88 @@ void CDebugInterfaceVice::JoystickUp(int port, uint32 axis) c64d_joystick_key_up(axis, port+1); } +extern "C" { +int set_mouse_enabled(int val, void *param); +int joyport_set_device(int port, int id); +void c64d_mouse_set_type(int mt); +int c64d_mouse_type_to_joyportid(int mouseType); +void mousedrv_button_left(int pressed); +void mousedrv_button_right(int pressed); +void mousedrv_button_middle(int pressed); +void mousedrv_button_up(int pressed); +void mousedrv_button_down(int pressed); +void mouse_move(int x, int y); +void c64d_mouse_set_position(int x, int y); +}; + +#define JOYPORT_ID_NONE 0 +#define JOYPORT_ID_JOYSTICK 1 + +void CDebugInterfaceVice::EmulatedMouseUpdateSettings() +{ + // reset mouse + set_mouse_enabled(0, NULL); + + // set mouse enabled as per settings + if (c64SettingsEmulatedMouseC64Enabled) + { + if (set_mouse_enabled((c64SettingsEmulatedMouseC64Enabled ? 1:0), NULL) < 0) + { + return; + } + c64d_mouse_set_type(c64SettingsEmulatedMouseC64Type); + + // set ports + joyport_set_device(0, JOYPORT_ID_JOYSTICK); + joyport_set_device(1, JOYPORT_ID_JOYSTICK); + + if (c64SettingsEmulatedMouseC64Enabled) + { + int joyportId = c64d_mouse_type_to_joyportid(c64SettingsEmulatedMouseC64Type); + joyport_set_device(c64SettingsEmulatedMouseC64Port, joyportId); + } + } +} + +bool CDebugInterfaceVice::EmulatedMouseEnable(bool enable) +{ + c64SettingsEmulatedMouseC64Enabled = enable; + EmulatedMouseUpdateSettings(); + return true; +} + +void CDebugInterfaceVice::EmulatedMouseSetType(int mouseType) +{ + c64SettingsEmulatedMouseC64Type = mouseType; + EmulatedMouseUpdateSettings(); +} + +void CDebugInterfaceVice::EmulatedMouseSetPort(int port) +{ + c64SettingsEmulatedMouseC64Port = port; + EmulatedMouseUpdateSettings(); +} + +void CDebugInterfaceVice::EmulatedMouseSetPosition(int newX, int newY) +{ + c64d_mouse_set_position(newX, newY); +} + +void CDebugInterfaceVice::EmulatedMouseButtonLeft(bool isPressed) +{ + mousedrv_button_left(isPressed ? 1:0); +} + +void CDebugInterfaceVice::EmulatedMouseButtonMiddle(bool isPressed) +{ + mousedrv_button_middle(isPressed ? 1:0); +} + +void CDebugInterfaceVice::EmulatedMouseButtonRight(bool isPressed) +{ + mousedrv_button_right(isPressed ? 1:0); +} + int CDebugInterfaceVice::GetCpuPC() { return viceCurrentC64PC; @@ -1745,7 +1831,7 @@ void CDebugInterfaceVice::GetVICColors(uint8 *cD021, uint8 *cD022, uint8 *cD023, void CDebugInterfaceVice::GetVICSpriteColors(uint8 *cD021, uint8 *cD025, uint8 *cD026, uint8 *spriteColors) { - SYS_FatalExit("CDebugInterfaceVice::GetVICSpriteColors: not implemented"); + LOGTODO("CDebugInterfaceVice::GetVICSpriteColors: not implemented"); } void CDebugInterfaceVice::GetCBMColor(uint8 colorNum, uint8 *r, uint8 *g, uint8 *b) @@ -2226,7 +2312,7 @@ bool CDebugInterfaceVice::LoadFullSnapshot(CByteBuffer *byteBuffer) void CDebugInterfaceVice::SaveFullSnapshot(CByteBuffer *snapshotBuffer) { - SYS_FatalExit("CDebugInterfaceVice::LoadFullSnapshot: not implemented"); + LOGTODO("CDebugInterfaceVice::LoadFullSnapshot: not implemented"); } @@ -2503,6 +2589,8 @@ bool CDebugInterfaceVice::ExecuteCodeMonitorCommand(CSlrString *commandStr) return true; } +// d1541II + void CDebugInterfaceVice::ScanFolderForRoms(const char *folderPath) { char *buf = SYS_GetCharBuf(); @@ -2522,69 +2610,69 @@ void CDebugInterfaceVice::ScanFolderForRoms(const char *folderPath) const char *DOS1541_ROM_NAME = "dos1541"; const char *DOS1541II_ROM_NAME = "dos1541ii"; const char *DOS1541II_ROM_NAME_2 = "d1541ii"; - + // kernal sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, KERNAL_ROM_NAME); if (SYS_FileExists(buf)) { - if (c64SettingsPathToRomC64Kernal) - delete c64SettingsPathToRomC64Kernal; - c64SettingsPathToRomC64Kernal = new CSlrString(buf); - foundKernal = true; + if (c64SettingsPathToRomC64Kernal) + delete c64SettingsPathToRomC64Kernal; + c64SettingsPathToRomC64Kernal = new CSlrString(buf); + foundKernal = true; } if (!SYS_FileExists(c64SettingsPathToRomC64Kernal)) { - delete c64SettingsPathToRomC64Kernal; - c64SettingsPathToRomC64Kernal = NULL; - foundKernal = false; + delete c64SettingsPathToRomC64Kernal; + c64SettingsPathToRomC64Kernal = NULL; + foundKernal = false; } // basic sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, BASIC_ROM_NAME); if (SYS_FileExists(buf)) { - if (c64SettingsPathToRomC64Basic) - delete c64SettingsPathToRomC64Basic; - c64SettingsPathToRomC64Basic = new CSlrString(buf); - foundBasic = true; + if (c64SettingsPathToRomC64Basic) + delete c64SettingsPathToRomC64Basic; + c64SettingsPathToRomC64Basic = new CSlrString(buf); + foundBasic = true; } if (!SYS_FileExists(c64SettingsPathToRomC64Basic)) { - delete c64SettingsPathToRomC64Basic; - c64SettingsPathToRomC64Basic = NULL; - foundBasic = false; + delete c64SettingsPathToRomC64Basic; + c64SettingsPathToRomC64Basic = NULL; + foundBasic = false; } // chargen sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, CHARGEN_ROM_NAME); if (SYS_FileExists(buf)) { - if (c64SettingsPathToRomC64Chargen) - delete c64SettingsPathToRomC64Chargen; - c64SettingsPathToRomC64Chargen = new CSlrString(buf); - foundChargen = true; + if (c64SettingsPathToRomC64Chargen) + delete c64SettingsPathToRomC64Chargen; + c64SettingsPathToRomC64Chargen = new CSlrString(buf); + foundChargen = true; } if (!SYS_FileExists(c64SettingsPathToRomC64Chargen)) { - delete c64SettingsPathToRomC64Chargen; - c64SettingsPathToRomC64Chargen = NULL; - foundChargen = false; + delete c64SettingsPathToRomC64Chargen; + c64SettingsPathToRomC64Chargen = NULL; + foundChargen = false; } // drive 1541 sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, DOS1541_ROM_NAME); if (SYS_FileExists(buf)) { - if (c64SettingsPathToRomC64Drive1541) - delete c64SettingsPathToRomC64Drive1541; - c64SettingsPathToRomC64Drive1541 = new CSlrString(buf); - foundDos1541 = true; + if (c64SettingsPathToRomC64Drive1541) + delete c64SettingsPathToRomC64Drive1541; + c64SettingsPathToRomC64Drive1541 = new CSlrString(buf); + foundDos1541 = true; } if (!SYS_FileExists(c64SettingsPathToRomC64Drive1541)) { - delete c64SettingsPathToRomC64Drive1541; - c64SettingsPathToRomC64Drive1541 = NULL; - foundDos1541 = false; + delete c64SettingsPathToRomC64Drive1541; + c64SettingsPathToRomC64Drive1541 = NULL; + foundDos1541 = false; } // drive 1541-II @@ -2609,28 +2697,27 @@ void CDebugInterfaceVice::ScanFolderForRoms(const char *folderPath) } if (!SYS_FileExists(c64SettingsPathToRomC64Drive1541ii)) { - delete c64SettingsPathToRomC64Drive1541ii; - c64SettingsPathToRomC64Drive1541ii = NULL; - foundDos1541ii = false; + delete c64SettingsPathToRomC64Drive1541ii; + c64SettingsPathToRomC64Drive1541ii = NULL; + foundDos1541ii = false; } - // Made more user-friendly: show filenames and path // prepare message box sprintf(buf, "C64 ROMs Status:\n\n" - "Folder: '%s'\n\n" - "Kernal ROM (File: '%s'): %s\n" - "Basic ROM (File: '%s'): %s\n" - "Chargen ROM (File: '%s'): %s\n" - "Drive 1541 ROM (File: '%s'): %s\n" - "Drive 1541-II ROM (File: '%s'): %s\n\n" - "Please ensure that all required ROM files are in the specified folder.", - folderPath, - KERNAL_ROM_NAME, foundKernal ? "FOUND" : (c64SettingsPathToRomC64Kernal ? "MISSING, using previous version" : "MISSING, no version available"), - BASIC_ROM_NAME, foundBasic ? "FOUND" : (c64SettingsPathToRomC64Basic ? "MISSING, using previous version" : "MISSING, no version available"), - CHARGEN_ROM_NAME, foundChargen ? "FOUND" : (c64SettingsPathToRomC64Chargen ? "MISSING, using previous version" : "MISSING, no version available"), - DOS1541_ROM_NAME, foundDos1541 ? "FOUND" : (c64SettingsPathToRomC64Drive1541 ? "MISSING, using previous version" : "MISSING, no version available"), - DOS1541II_ROM_NAME, foundDos1541ii ? "FOUND" : (c64SettingsPathToRomC64Drive1541ii ? "MISSING, using previous version" : "MISSING, no version available")); + "Folder: '%s'\n\n" + "Kernal ROM (File: '%s'): %s\n" + "Basic ROM (File: '%s'): %s\n" + "Chargen ROM (File: '%s'): %s\n" + "Drive 1541 ROM (File: '%s'): %s\n" + "Drive 1541-II ROM (File: '%s'): %s\n\n" + "Please ensure that all required ROM files are in the specified folder.", + folderPath, + KERNAL_ROM_NAME, foundKernal ? "FOUND" : (c64SettingsPathToRomC64Kernal ? "MISSING, using previous version" : "MISSING, no version available"), + BASIC_ROM_NAME, foundBasic ? "FOUND" : (c64SettingsPathToRomC64Basic ? "MISSING, using previous version" : "MISSING, no version available"), + CHARGEN_ROM_NAME, foundChargen ? "FOUND" : (c64SettingsPathToRomC64Chargen ? "MISSING, using previous version" : "MISSING, no version available"), + DOS1541_ROM_NAME, foundDos1541 ? "FOUND" : (c64SettingsPathToRomC64Drive1541 ? "MISSING, using previous version" : "MISSING, no version available"), + DOS1541II_ROM_NAME, foundDos1541ii ? "FOUND" : (c64SettingsPathToRomC64Drive1541ii ? "MISSING, using previous version" : "MISSING, no version available")); ShowMessageBox("C64 ROMs folder scan", buf); @@ -2676,7 +2763,7 @@ void CDebugInterfaceVice::UpdateRomsTrap() this->UnlockMutex(); - HardReset(); + ResetHard(); DiskDriveReset(); SetDebugMode(DEBUGGER_MODE_RUNNING); } @@ -2787,14 +2874,34 @@ void CDebugInterfaceVice::SupportsBreakpoints(bool *writeBreakpoint, bool *readB *readBreakpoint = true; } -// SID +CDebuggerApi *CDebugInterfaceVice::GetDebuggerApi() +{ + return new CDebuggerApiVice(this); +} + +CDebuggerServerApi *CDebugInterfaceVice::GetDebuggerServerApi() +{ + if (debuggerServerApi) + return debuggerServerApi; + + debuggerServerApi = new CDebuggerServerApiVice(this); + return debuggerServerApi; +} + +// SID poke/peek +// Note: SID is specific, as setting one register may cause strange effects. So we push all registers at once. CPool CSidData::poolSidData(6000, sizeof(CSidData)); CSidData::CSidData() { - memset(sidRegs[0], 0x00, C64_NUM_SID_REGISTERS); - memset(sidRegs[1], 0x00, C64_NUM_SID_REGISTERS); - memset(sidRegs[2], 0x00, C64_NUM_SID_REGISTERS); + for (int i = 0; i < SOUND_SIDS_MAX; i++) + { + for (int reg = 0; reg < C64_NUM_SID_REGISTERS; reg++) + { + sidRegs[i][reg] = 0x00; + shouldSetSidReg[i][reg] = true; + } + } } extern "C" { @@ -2818,7 +2925,10 @@ void CSidData::RestoreSids() { for (int registerNum = 0; registerNum < C64_NUM_SID_REGISTERS; registerNum++) { - sid_store_chip(registerNum, sidRegs[sidNum][registerNum], sidNum); + if (shouldSetSidReg[sidNum][registerNum]) + { + sid_store_chip(registerNum, sidRegs[sidNum][registerNum], sidNum); + } } } c64d_skip_sound_run_sound_in_sound_store = FALSE; @@ -2892,7 +3002,7 @@ bool CSidData::LoadRegs(const char *fileName) /// default keymap void ViceKeyMapInitDefault() { - SYS_FatalExit("ViceKeyMapInitDefault"); + SYS_FatalExit("ViceKeyMapInitDefault not implemented"); // C64 keyboard matrix: diff --git a/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.cpp~ b/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.cpp~ new file mode 100644 index 0000000..6951dc2 --- /dev/null +++ b/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.cpp~ @@ -0,0 +1,2998 @@ +extern "C" { +#include "vice.h" +#include "main.h" +#include "vicetypes.h" +#include "mos6510.h" +#include "montypes.h" +#include "attach.h" +#include "keyboard.h" +#include "drivecpu.h" +#include "machine.h" +#include "vsync.h" +#include "interrupt.h" +#include "c64-snapshot.h" +#include "viciitypes.h" +#include "vicii.h" +#include "vicii-mem.h" +#include "drivetypes.h" +#include "drive.h" +#include "cia.h" +#include "c64.h" +#include "sid.h" +#include "sid-resources.h" +#include "drive.h" +#include "datasette.h" +#include "c64mem.h" +#include "c64model.h" +#include "driverom.h" +#include "ui.h" +#include "resources.h" +#include "ViceWrapper.h" +} + +#include "RES_ResourceManager.h" +#include "CDebugInterfaceVice.h" +#include "CDebugMemory.h" +#include "CByteBuffer.h" +#include "CSlrString.h" +#include "CDataAdaptersVice.h" +#include "SYS_CommandLine.h" +#include "CGuiMain.h" +#include "SYS_Main.h" +#include "SYS_KeyCodes.h" +#include "SND_SoundEngine.h" +#include "SYS_FileSystem.h" +#include "C64Tools.h" +#include "C64KeyMap.h" +#include "C64SettingsStorage.h" +#include "C64SIDFrequencies.h" +#include "CViewC64.h" +#include "CViewC64StateSID.h" +#include "CViewC64SidTrackerHistory.h" +#include "CViewDrive1541Browser.h" +#include "CAudioChannelVice.h" +#include "CDebuggerEmulatorPlugin.h" +#include "CSnapshotsManager.h" + +#include "CDataAdapterViceDrive1541.h" +#include "CDataAdapterDrive1541Minimal.h" +#include "CDebugSymbolsC64.h" +#include "CDebugSymbolsDrive1541.h" +#include "CWaveformData.h" +#include "CViewDataMap.h" +#include "CDebugEventsHistory.h" + +// 44100/50*5 +#define SID_WAVEFORM_LENGTH 4410*8 + +extern "C" { +void vsync_suspend_speed_eval(void); +void c64d_reset_sound_clk(); +void sound_suspend(void); +void sound_resume(void); +int c64d_sound_run_sound_when_paused(void); +int set_suspend_time(int val, void *param); + +void c64d_set_debug_mode(int newMode); +void c64d_patch_kernal_fast_boot(); +void c64d_init_memory(uint8 *c64memory); + +int resources_get_int(const char *name, int *value_return); + +disk_image_t *c64d_get_drive_disk_image(int driveId); +} + +void c64d_update_c64_model(); +void c64d_update_c64_machine_from_model_type(int modelType); +void c64d_update_c64_screen_height_from_model_type(int modelType); + +void ViceWrapperInit(CDebugInterfaceVice *debugInterface); + +CDebugInterfaceVice *debugInterfaceVice = NULL; + +CDebugInterfaceVice::CDebugInterfaceVice(CViewC64 *viewC64, uint8 *c64memory, bool patchKernalFastBoot) +: CDebugInterfaceC64(viewC64) +{ + LOGM("CDebugInterfaceVice: VICE %s init", VERSION); + + CreateScreenData(); + + audioChannel = NULL; + snapshotsManager = new CSnapshotsManager(this); + + for (int sidNum = 0; sidNum < C64_MAX_NUM_SIDS; sidNum++) + { + for (int i = 0; i < 3; i++) + { + sidChannelWaveform[sidNum][i] = new CWaveformData(SID_WAVEFORM_LENGTH); + } + sidMixWaveform[sidNum] = new CWaveformData(SID_WAVEFORM_LENGTH); + } + + ViceWrapperInit(this); + + ReadEmbeddedRoms(); + + // set patch kernal flag + // SetPatchKernalFastBoot(patchKernalFastBoot); + if (patchKernalFastBoot) + { + c64d_patch_kernal_fast_boot_flag = 1; + } + else + { + c64d_patch_kernal_fast_boot_flag = 0; + } + + numSids = 1; + + // PAL + machineType = MACHINE_TYPE_PAL; + debugInterfaceVice->numEmulationFPS = 50; + + // init C64 memory, will be attached to a memmaped file if needed + if (c64memory == NULL) + { + this->c64memory = (uint8 *)malloc(C64_RAM_SIZE); + } + else + { + this->c64memory = c64memory; + } + + c64d_init_memory(this->c64memory); + + mutexSidDataHistory = new CSlrMutex("mutexSidDataHistory"); + sidDataHistoryCurrentStep = 0; + sidDataHistorySteps = 1; + sidDataToRestore = NULL; + + driveFlushThread = NULL; + + InitViceMainProgram(); + + // create default symbols and data adapters + + // C64 + symbolsC64 = new CDebugSymbolsC64(this); + symbols = symbolsC64; + + dataAdapterViceC64 = new CDataAdapterViceC64(symbols); + dataAdapterC64 = dataAdapterViceC64; + symbols->SetDataAdapter(dataAdapterC64); + symbols->CreateDefaultSegment(); + + dataAdapterViceC64DirectRam = new CDataAdapterViceC64DirectRam(symbols); + dataAdapterC64DirectRam = dataAdapterViceC64DirectRam; + + // Drive1541 + symbolsDrive1541 = new CDebugSymbolsDrive1541(this); + + dataAdapterViceDrive1541 = new CDataAdapterViceDrive1541(symbolsDrive1541); + dataAdapterDrive1541 = dataAdapterViceDrive1541; + + symbolsDrive1541->SetDataAdapter(dataAdapterDrive1541); + symbolsDrive1541->CreateDefaultSegment(); + + dataAdapterViceDrive1541DirectRam = new CDataAdapterViceDrive1541DirectRam(symbolsDrive1541); + dataAdapterDrive1541DirectRam = dataAdapterViceDrive1541DirectRam; + + // + dataAdapterDrive1541MinimalRam = new CDataAdapterDrive1541Minimal(symbolsDrive1541, dataAdapterViceDrive1541); + + // Drive1541DiskContents + symbolsDrive1541DiskContents = new CDebugSymbols(this, false); + dataAdapterViceDrive1541DiskContents = new CDataAdapterViceDrive1541DiskContents(symbolsDrive1541DiskContents, 0); + dataAdapterDrive1541DiskContents = dataAdapterViceDrive1541DiskContents; + + symbolsDrive1541DiskContents->SetDataAdapter(dataAdapterViceDrive1541DiskContents); + symbolsDrive1541DiskContents->CreateDefaultSegment(); + + // C64Cartridge + symbolsCartridgeC64 = new CDebugSymbols(this, false); + dataAdapterViceC64Cartridge = new CDataAdapterViceC64Cartridge(symbolsCartridgeC64, CCartridgeDataAdapterViceType::C64CartridgeDataAdapterViceTypeRamL); + dataAdapterCartridgeC64 = dataAdapterViceC64Cartridge; + + symbolsCartridgeC64->SetDataAdapter(dataAdapterViceC64Cartridge); + symbolsCartridgeC64->CreateDefaultSegment(); + + C64KeyMap *keyMap = C64KeyMapGetDefault(); + InitKeyMap(keyMap); + + isCodeMonitorOpened = false; +} + +CDebugInterfaceVice::~CDebugInterfaceVice() +{ +} + +void CDebugInterfaceVice::InitViceMainProgram() +{ + int ret = vice_main_program(sysArgc, sysArgv, c64SettingsC64Model); + if (ret != 0) + { + LOGError("Vice failed, err=%d", ret); + } + + // note, vice changes and strips argv, we need to update the argc to be properly later parsed by other emulators + for (int i = 1; i < sysArgc; i++) + { + if (sysArgv[i] == NULL) + { + sysArgc = i; + break; + } + } +} + +extern "C" { + void c64d_patch_kernal_fast_boot(); + void c64d_un_patch_kernal_fast_boot(); + void c64d_update_rom(); +}; + +float CDebugInterfaceVice::GetEmulationFPS() +{ + return numEmulationFPS; +} + +void CDebugInterfaceVice::SetPatchKernalFastBoot(bool isPatchKernal) +{ + LOGM("CDebugInterfaceVice::SetPatchKernalFastBoot: %d", isPatchKernal); + + c64d_un_patch_kernal_fast_boot(); + + if (isPatchKernal) + { + c64d_patch_kernal_fast_boot_flag = 1; + c64d_patch_kernal_fast_boot(); + } + else + { + c64d_patch_kernal_fast_boot_flag = 0; + } + + c64d_update_rom(); +} + +void CDebugInterfaceVice::SetSkipDrawingSprites(bool isSkipDrawingSprites) +{ + LOGM("CDebugInterfaceVice::SetSkipDrawingSprites: %s", STRBOOL(isSkipDrawingSprites)); + + if (isSkipDrawingSprites) + { + c64d_skip_drawing_sprites = 1; + } + else + { + c64d_skip_drawing_sprites = 0; + } +} + +void CDebugInterfaceVice::SetRunSIDWhenInWarp(bool isRunningSIDInWarp) +{ + c64d_setting_run_sid_when_in_warp = isRunningSIDInWarp ? 1 : 0; +} + +void CDebugInterfaceVice::SetRunSIDEmulation(bool isSIDEmulationOn) +{ + // this does not stop sound via playback_enable, but just skips the SID emulation + // thus, the CPU emulation will be in correct sync + + LOGD("CDebugInterfaceVice::SetRunSIDEmulation: %s", STRBOOL(isSIDEmulationOn)); + c64d_setting_run_sid_emulation = isSIDEmulationOn ? 1 : 0; +} + +void CDebugInterfaceVice::SetAudioVolume(float volume) +{ + LOGD("CDebugInterfaceVice::SetAudioVolume: %f", volume); + c64d_set_volume(volume); +} + +int CDebugInterfaceVice::GetEmulatorType() +{ + return EMULATOR_TYPE_C64_VICE; +} + +CSlrString *CDebugInterfaceVice::GetEmulatorVersionString() +{ + char *buf = SYS_GetCharBuf(); + sprintf(buf, "Vice %s", VERSION); // by The VICE Team + CSlrString *versionString = new CSlrString(buf); + SYS_ReleaseCharBuf(buf); + + return versionString; +} + +#if defined(WIN32) +extern "C" { + int uilib_cpu_is_smp(void); + int set_single_cpu(int val, void *param); // 1=set to first CPU, 0=set to all CPUs +} +#endif + +void CDebugInterfaceVice::RunEmulationThread() +{ + LOGM("CDebugInterfaceVice::RunEmulationThread"); + CDebugInterface::RunEmulationThread(); + + isRunning = true; + +#if defined(WIN32) + if (c64SettingsUseOnlyFirstCPU) + { + if (uilib_cpu_is_smp() == 1) + { + LOGD("CDebugInterfaceVice: set UseOnlyFirstCPU"); + set_single_cpu(1, NULL); + } + } +#endif + + // vice blocks d64 for read when mounted and does the flush only on disk unmount or quit. this leads to not saved data immediately. + // thus, we do not block d64 for read and avoid that data is not flushed we check periodically if there's a need to flush data + + if (driveFlushThread == NULL) + { + driveFlushThread = new CThreadViceDriveFlush(this, 2500); // every 2.5s + SYS_StartThread(driveFlushThread); + } + + // update sid type + SetSidTypeAsync(c64SettingsSIDEngineModel); + +// audioChannel->Start(); + + vice_main_loop_run(); + +// audioChannel->Stop(); + + isRunning = false; + LOGM("CDebugInterfaceVice::RunEmulationThread: finished"); +} + +void CDebugInterfaceVice::SetSidDataHistorySteps(int numSteps) +{ + sidDataHistorySteps = numSteps; +} + +void CDebugInterfaceVice::UpdateSidDataHistory() +{ + mutexSidDataHistory->Lock(); + + CSidData *sidData; + if (sidDataHistory.size() > c64SettingsSidDataHistoryMaxSize) + { + sidData = sidDataHistory.back(); + sidDataHistory.pop_back(); + } + else + { + sidData = new CSidData(); + } + + if (sidDataToRestore) + { + sidData->CopyFrom(sidDataToRestore); + } + else + { + sidData->PeekFromSids(); + } + + sidDataHistory.push_front(sidData); + + sidDataHistoryCurrentStep++; + + if (sidDataHistoryCurrentStep >= sidDataHistorySteps) + { + sidDataHistoryCurrentStep = 0; + + // TODO: make a proper callback for this: + viewC64->viewC64SidTrackerHistory->VSyncStepsAdded(); + } + mutexSidDataHistory->Unlock(); +} + +extern "C" { + void c64d_joystick_latch_matrix_workaround(); + void vsync_sync_reset(void); +}; + +void CDebugInterfaceVice::DoVSync() +{ +// LOGD("CDebugInterfaceVice::DoVSync: store sid history for sid tracker view"); + UpdateSidDataHistory(); + CDebugInterfaceC64::DoVSync(); +} + +void CDebugInterfaceVice::DoFrame() +{ + CDebugInterfaceC64::DoFrame(); +} + +void CDebugInterfaceVice::RefreshSync() +{ + vsync_sync_reset(); +} + +void CDebugInterfaceVice::RestartAudio() +{ + audioChannel->Start(); + RefreshSync(); +} + +CThreadViceDriveFlush::CThreadViceDriveFlush(CDebugInterfaceVice *debugInterface, int flushCheckIntervalInMS) +{ + this->debugInterface = debugInterface; + this->flushCheckIntervalInMS = flushCheckIntervalInMS; +} + +void CThreadViceDriveFlush::ThreadRun(void *data) +{ +// LOGD("CViceDriveFlushThread started"); + while(true) + { + if (isRunning) + { + SYS_Sleep(flushCheckIntervalInMS); + + if (!isRunning) + continue; + + debugInterface->LockMutex(); + if (debugInterface->snapshotsManager->snapshotToRestore + || debugInterface->snapshotsManager->pauseNumFrame != -1) + { + debugInterface->UnlockMutex(); + SYS_Sleep(flushCheckIntervalInMS * 4); + continue; + } + + // LOGD("CViceDriveFlushThread: flushing drive"); + drive_gcr_data_writeback_all(); + debugInterface->UnlockMutex(); + // LOGD("CViceDriveFlushThread: flushing drive finished"); + + } + + } +} + +extern "C" { + void c64d_shutdown_vice(); +} + +void CDebugInterfaceVice::Shutdown() +{ + LOGD("CDebugInterfaceVice::Shutdown"); + + this->LockMutex(); + drive_gcr_data_writeback_all(); + this->UnlockMutex(); + + c64d_shutdown_vice(); + + while(isRunning) + { + SYS_Sleep(50); + } + + CDebugInterfaceC64::Shutdown(); + + LOGD("Vice Shutdown finished"); +} + +void CDebugInterfaceVice::InitKeyMap(C64KeyMap *keyMap) +{ + LOGD("CDebugInterfaceVice::InitKeyMap"); + c64d_keyboard_keymap_clear(); + + for (std::map::iterator it = keyMap->keyCodes.begin(); + it != keyMap->keyCodes.end(); it++) + { + C64KeyCode *key = it->second; + + if (key->matrixRow < 0) + { + // restore, caps lock, ... + keyboard_parse_set_neg_row(key->keyCode, key->matrixRow, key->matrixCol); + } + else + { + + //LOGD("... %04x %3d %3d %d", key->keyCode, key->matrixRow, key->matrixCol, key->shift); + keyboard_parse_set_pos_row(key->keyCode, key->matrixRow, key->matrixCol, key->shift); + } + } + + +} + +uint8 *CDebugInterfaceVice::GetCharRom() +{ + return mem_chargen_rom; +} + +int CDebugInterfaceVice::GetScreenSizeX() +{ + int screenWidth, screenHeight, gfxPosX, gfxPosY; + GetViciiGeometry(&screenWidth, &screenHeight, &gfxPosX, &gfxPosY); + return screenWidth; +} + +int CDebugInterfaceVice::GetScreenSizeY() +{ + int screenWidth, screenHeight, gfxPosX, gfxPosY; + GetViciiGeometry(&screenWidth, &screenHeight, &gfxPosX, &gfxPosY); + return screenHeight; //-16; +} + +bool CDebugInterfaceVice::IsCpuJam() +{ + if (c64d_is_cpu_in_jam_state == 1) + { + return true; + } + + return false; +} + +void CDebugInterfaceVice::ForceRunAndUnJamCpu() +{ + c64d_is_cpu_in_jam_state = 0; + this->SetDebugMode(DEBUGGER_MODE_RUNNING); +} + +void CDebugInterfaceVice::ClearDebugMarkers() +{ + symbols->memory->ClearDebugMarkers(); + symbolsDrive1541->memory->ClearDebugMarkers(); + symbolsCartridgeC64->memory->ClearDebugMarkers(); +} + +void CDebugInterfaceVice::Reset() +{ + vsync_suspend_speed_eval(); + + keyboard_clear_keymatrix(); + + machine_trigger_reset(MACHINE_RESET_MODE_SOFT); + this->ResetEmulationFrameCounter(); + c64d_maincpu_clk = 6; + + c64d_update_c64_model(); + + if (c64d_is_cpu_in_jam_state == 1) + { + this->SetDebugMode(DEBUGGER_MODE_RUNNING); + c64d_is_cpu_in_jam_state = 0; + } +} + +void CDebugInterfaceVice::HardReset() +{ + LOGD("CDebugInterfaceVice::HardReset"); + vsync_suspend_speed_eval(); + + keyboard_clear_keymatrix(); + + machine_trigger_reset(MACHINE_RESET_MODE_HARD); + this->ResetEmulationFrameCounter(); + c64d_maincpu_clk = 6; + + c64d_update_c64_model(); + + if (c64d_is_cpu_in_jam_state == 1) + { + this->SetDebugMode(DEBUGGER_MODE_RUNNING); + c64d_is_cpu_in_jam_state = 0; + } +} + +void CDebugInterfaceVice::DiskDriveReset() +{ + LOGM("CDebugInterfaceVice::DiskDriveReset()"); + + drivecpu_reset(drive_context[0]); +} + +extern "C" { + unsigned int c64d_get_vice_maincpu_clk(); + unsigned int c64d_get_vice_maincpu_current_instruction_clk(); + void c64d_refresh_screen_no_callback(); +} + +u64 CDebugInterfaceVice::GetMainCpuCycleCounter() +{ + return c64d_get_vice_maincpu_clk(); +} + +u64 CDebugInterfaceVice::GetCurrentCpuInstructionCycleCounter() +{ + return c64d_get_vice_maincpu_current_instruction_clk(); +} + +u64 CDebugInterfaceVice::GetPreviousCpuInstructionCycleCounter() +{ + u64 viceMainCpuClk = c64d_get_vice_maincpu_clk(); + u64 previousInstructionClk = c64d_maincpu_previous_instruction_clk; + u64 previous2InstructionClk = c64d_maincpu_previous2_instruction_clk; + LOGD(">>>>>>>>>................ previous_inst_clk=%d previous2InstructionClk=%d | mainclk=%d", previousInstructionClk, previous2InstructionClk, viceMainCpuClk); + + if (previousInstructionClk == viceMainCpuClk) + { + LOGWarning("previousInstructionClk=%d == viceMainCpuClk=%d, previousInstructionClk will be previous2InstructionClk=%d", previousInstructionClk, viceMainCpuClk, previous2InstructionClk); + + // snapshot was recently restored and debug pause was moved forward or we have no data (i.e. snapshot restored etc) + previousInstructionClk = previous2InstructionClk; + } + + return previousInstructionClk; +} + +void CDebugInterfaceVice::ResetMainCpuDebugCycleCounter() +{ + c64d_maincpu_clk = 0; +} + +extern "C" { + unsigned int c64d_get_vice_maincpu_clk(); +}; + +u64 CDebugInterfaceVice::GetMainCpuDebugCycleCounter() +{ + return c64d_maincpu_clk; +} + +extern "C" { + void c64d_refresh_screen_no_callback(); +} + +void CDebugInterfaceVice::ResetEmulationFrameCounter() +{ + this->ClearHistory(); + CDebugInterfaceC64::ResetEmulationFrameCounter(); +} + +unsigned int CDebugInterfaceVice::GetEmulationFrameNumber() +{ + return CDebugInterfaceC64::GetEmulationFrameNumber(); +} + +void CDebugInterfaceVice::RefreshScreenNoCallback() +{ + c64d_refresh_screen_no_callback(); +} + +extern "C" { + void c64d_joystick_key_down(int key, unsigned int joyport); + void c64d_joystick_key_up(int key, unsigned int joyport); +} + +bool CDebugInterfaceVice::KeyboardDown(uint32 mtKeyCode) +{ + for (std::list::iterator it = this->plugins.begin(); it != this->plugins.end(); it++) + { + CDebuggerEmulatorPlugin *plugin = *it; + mtKeyCode = plugin->KeyDown(mtKeyCode); + + if (mtKeyCode == 0) + return false; + } + + if (keyboard_key_pressed((unsigned long)mtKeyCode) == 1) + return true; + + return false; +} + +bool CDebugInterfaceVice::KeyboardUp(uint32 mtKeyCode) +{ + for (std::list::iterator it = this->plugins.begin(); it != this->plugins.end(); it++) + { + CDebuggerEmulatorPlugin *plugin = *it; + mtKeyCode = plugin->KeyUp(mtKeyCode); + + if (mtKeyCode == 0) + return false; + } + + if (keyboard_key_released((unsigned long)mtKeyCode) == 1) + return true; + + return false; +} + +void CDebugInterfaceVice::JoystickDown(int port, uint32 axis) +{ +// LOGD("CDebugInterfaceVice::JoystickDown %d %d", port, axis); + c64d_joystick_key_down(axis, port+1); +} + +void CDebugInterfaceVice::JoystickUp(int port, uint32 axis) +{ +// LOGD("CDebugInterfaceVice::JoystickUp %d %d", port, axis); + c64d_joystick_key_up(axis, port+1); +} + +int CDebugInterfaceVice::GetCpuPC() +{ + return viceCurrentC64PC; +} + +int CDebugInterfaceVice::GetDrive1541PC() +{ + return viceCurrentDiskPC[0]; +} + +extern "C" { +// from c64cpu.c + void c64d_get_maincpu_regs(uint8 *a, uint8 *x, uint8 *y, uint8 *p, uint8 *sp, uint16 *pc, + uint8 *instructionCycle); + void c64d_get_drivecpu_regs(int driveNum, uint8 *a, uint8 *x, uint8 *y, uint8 *p, uint8 *sp, uint16 *pc); +} + +void CDebugInterfaceVice::GetC64CpuState(C64StateCPU *state) +{ + c64d_get_maincpu_regs(&(state->a), &(state->x), &(state->y), &(state->processorFlags), &(state->sp), &(state->pc), + &(state->instructionCycle)); + + state->lastValidPC = state->pc; +} + +void CDebugInterfaceVice::GetDrive1541CpuState(C64StateCPU *state) +{ + c64d_get_drivecpu_regs(0, &(state->a), &(state->x), &(state->y), &(state->processorFlags), &(state->sp), &(state->pc)); + + state->lastValidPC = viceCurrentDiskPC[0]; + + //LOGD("drive pc: %04x", state->pc); +} + +extern "C" { + void c64d_get_vic_simple_state(struct C64StateVIC *simpleStateVic); +} + +void CDebugInterfaceVice::GetVICState(C64StateVIC *state) +{ + c64d_get_vic_simple_state(state); +} + +void CDebugInterfaceVice::GetDrive1541State(C64StateDrive1541 *state) +{ + drive_t *drive = drive_context[0]->drive; + state->headTrackPosition = drive->current_half_track + drive->side * 70; + +} + +void CDebugInterfaceVice::InsertD64(CSlrString *path) +{ + int diskId = 0; + + LockIoMutex(); + char *asciiPath = path->GetStdASCII(); + + SYS_FixFileNameSlashes(asciiPath); + + int rc = file_system_attach_disk(8, asciiPath); + + if (rc == -1) + { + viewC64->ShowMessageError("Inserting disk failed"); + } + + delete [] asciiPath; + + // TODO: add drive ID + ((CDataAdapterViceDrive1541DiskContents*)dataAdapterDrive1541DiskContents)->DiskAttached(); + + UnlockIoMutex(); +} + +void CDebugInterfaceVice::DetachDriveDisk() +{ + file_system_detach_disk(8); + ((CDataAdapterViceDrive1541DiskContents*)debugInterfaceVice->dataAdapterDrive1541DiskContents)->DiskDetached(); +} + +// REU +extern "C" { + int set_reu_enabled(int value, void *param); + int set_reu_size(int val, void *param); + int set_reu_filename(const char *name, void *param); + int reu_bin_save(const char *filename); +}; + +void CDebugInterfaceVice::SetReuEnabled(bool isEnabled) +{ + LOGD("CDebugInterfaceVice::SetReuEnabled: %s", STRBOOL(isEnabled)); + set_reu_enabled((isEnabled ? 1:0), NULL); +} + +void CDebugInterfaceVice::SetReuSize(int reuSize) +{ + snapshotsManager->LockMutex(); + set_reu_size(reuSize, NULL); + snapshotsManager->UnlockMutex(); +} + +bool CDebugInterfaceVice::LoadReu(char *filePath) +{ + resources_set_string("REUfilename", filePath); + +// if (set_reu_filename(filePath, NULL) == 0) +// return true; +// return false; + + return true; +} + +bool CDebugInterfaceVice::SaveReu(char *filePath) +{ + snapshotsManager->LockMutex(); + if (reu_bin_save(filePath) == 0) + { + snapshotsManager->UnlockMutex(); + return true; + } + + snapshotsManager->UnlockMutex(); + return false; +} + + +extern "C" { + int c64d_get_warp_mode(); + int set_warp_mode(int val, void *param); +} + +bool CDebugInterfaceVice::GetSettingIsWarpSpeed() +{ + return c64d_get_warp_mode() == 0 ? false : true; +} + +void CDebugInterfaceVice::SetSettingIsWarpSpeed(bool isWarpSpeed) +{ + set_warp_mode(isWarpSpeed ? 1 : 0, NULL); +} + +/// + +void CDebugInterfaceVice::GetSidTypes(std::vector *sidTypes) +{ + // 0-2 + sidTypes->push_back(new CSlrString("6581 (ReSID)")); + sidTypes->push_back(new CSlrString("8580 (ReSID)")); + sidTypes->push_back(new CSlrString("8580 + digi boost (ReSID)")); + + // 3-4 + sidTypes->push_back(new CSlrString("6581 (FastSID)")); + sidTypes->push_back(new CSlrString("8580 (FastSID)")); + + // 5-14 + sidTypes->push_back(new CSlrString("6581R3 4885 (ReSID-fp)")); + sidTypes->push_back(new CSlrString("6581R3 0486S (ReSID-fp)")); + sidTypes->push_back(new CSlrString("6581R3 3984 (ReSID-fp)")); + sidTypes->push_back(new CSlrString("6581R4AR 3789 (ReSID-fp)")); + sidTypes->push_back(new CSlrString("6581R3 4485 (ReSID-fp)")); + sidTypes->push_back(new CSlrString("6581R4 1986S (ReSID-fp)")); + sidTypes->push_back(new CSlrString("8580R5 3691 (ReSID-fp)")); + sidTypes->push_back(new CSlrString("8580R5 3691 + digi (ReSID-fp)")); + sidTypes->push_back(new CSlrString("8580R5 1489 (ReSID-fp)")); + sidTypes->push_back(new CSlrString("8580R5 1489 + digi (ReSID-fp)")); +} + + +void CDebugInterfaceVice::GetSidTypes(std::vector *sidTypes) +{ + // 0-2 + sidTypes->push_back("6581 (ReSID)"); + sidTypes->push_back("8580 (ReSID)"); + sidTypes->push_back("8580 + digi boost (ReSID)"); + + // 3-4 + sidTypes->push_back("6581 (FastSID)"); + sidTypes->push_back("8580 (FastSID)"); + + // 5-14 + sidTypes->push_back("6581R3 4885 (ReSID-fp)"); + sidTypes->push_back("6581R3 0486S (ReSID-fp)"); + sidTypes->push_back("6581R3 3984 (ReSID-fp)"); + sidTypes->push_back("6581R4AR 3789 (ReSID-fp)"); + sidTypes->push_back("6581R3 4485 (ReSID-fp)"); + sidTypes->push_back("6581R4 1986S (ReSID-fp)"); + sidTypes->push_back("8580R5 3691 (ReSID-fp)"); + sidTypes->push_back("8580R5 3691 + digi (ReSID-fp)"); + sidTypes->push_back("8580R5 1489 (ReSID-fp)"); + sidTypes->push_back("8580R5 1489 + digi (ReSID-fp)"); + +#if defined(WIN32) + // 15 hardsid + sidTypes->push_back("HardSID"); +#endif + +} + +int c64_change_sid_type_value_to_set = 0; +static void c64_change_sid_type_trap(WORD addr, void *v) +{ + gSoundEngine->LockMutex("c64_change_sid_type_trap"); + + LOGD("c64_change_sid_type_trap: sidType=%d", c64_change_sid_type_value_to_set); + debugInterfaceVice->SetSidTypeAsync(c64_change_sid_type_value_to_set); + + gSoundEngine->UnlockMutex("c64_change_sid_type_trap"); +} + +void CDebugInterfaceVice::SetSidType(int sidType) +{ + LOGM("CDebugInterfaceVice::SetSidType: %d", sidType); + + c64_change_sid_type_value_to_set = sidType; + interrupt_maincpu_trigger_trap(c64_change_sid_type_trap, NULL); +} + +void CDebugInterfaceVice::SetSidTypeAsync(int sidType) +{ + LOGD("CDebugInterfaceVice::SetSidTypeAsync: sidType=%d", sidType); + + snapshotsManager->LockMutex(); + + switch(sidType) + { + default: + case 0: + sid_set_engine_model(SID_ENGINE_RESID, SID_MODEL_6581); + break; + case 1: + sid_set_engine_model(SID_ENGINE_RESID, SID_MODEL_8580); + break; + case 2: + sid_set_engine_model(SID_ENGINE_RESID, SID_MODEL_8580D); + break; + case 3: + sid_set_engine_model(SID_ENGINE_FASTSID, SID_MODEL_6581); + break; + case 4: + sid_set_engine_model(SID_ENGINE_FASTSID, SID_MODEL_8580); + break; + case 5: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_6581R3_4885); + break; + case 6: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_6581R3_0486S); + break; + case 7: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_6581R3_3984); + break; + case 8: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_6581R4AR_3789); + break; + case 9: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_6581R3_4485); + break; + case 10: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_6581R4_1986S); + break; + case 11: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_8580R5_3691); + break; + case 12: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_8580R5_3691D); + break; + case 13: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_8580R5_1489); + break; + case 14: + sid_set_engine_model(SID_ENGINE_RESID_FP, SID_MODEL_8580R5_1489D); + break; + case 15: + sid_set_engine_model(SID_ENGINE_HARDSID, SID_MODEL_DEFAULT); + break; + + } + snapshotsManager->UnlockMutex(); +} + +// +void CDebugInterfaceVice::SetViciiBorderMode(int borderMode) +{ + LockMutex(); + c64d_set_vicii_border_mode(borderMode); + UnlockMutex(); +} + +int CDebugInterfaceVice::GetViciiBorderMode() +{ + return c64d_get_vicii_border_mode(); +} + +extern "C" { +void c64d_vicii_get_geometry(int *canvasWidth, int *canvasHeight, int *gfxPosX, int *gfxPosY); +} + +void CDebugInterfaceVice::GetViciiGeometry(int *canvasWidth, int *canvasHeight, int *gfxPosX, int *gfxPosY) +{ + c64d_vicii_get_geometry(canvasWidth, canvasHeight, gfxPosX, gfxPosY); +} + + +// samplingMethod: Fast=0, Interpolating=1, Resampling=2, Fast Resampling=3 +void CDebugInterfaceVice::SetSidSamplingMethod(int samplingMethod) +{ + snapshotsManager->LockMutex(); + c64d_sid_set_sampling_method(samplingMethod); + snapshotsManager->UnlockMutex(); +} + +// emulateFilters: no=0, yes=1 +void CDebugInterfaceVice::SetSidEmulateFilters(int emulateFilters) +{ + snapshotsManager->LockMutex(); + c64d_sid_set_emulate_filters(emulateFilters); + snapshotsManager->UnlockMutex(); +} + +// passband: 0-90 +void CDebugInterfaceVice::SetSidPassBand(int passband) +{ + snapshotsManager->LockMutex(); + c64d_sid_set_passband(passband); + snapshotsManager->UnlockMutex(); +} + +// filterBias: -500 500 +void CDebugInterfaceVice::SetSidFilterBias(int filterBias) +{ + snapshotsManager->LockMutex(); + c64d_sid_set_filter_bias(filterBias); + snapshotsManager->UnlockMutex(); +} + +int CDebugInterfaceVice::GetNumSids() +{ + return this->numSids; +} + +// 0=none, 1=stereo, 2=triple +void CDebugInterfaceVice::SetSidStereo(int stereoMode) +{ + snapshotsManager->LockMutex(); + c64d_sid_set_stereo(stereoMode); + + // stereo: 0=none, 1=stereo, 2=triple + this->numSids = stereoMode + 1; + + snapshotsManager->UnlockMutex(); +} + +void CDebugInterfaceVice::SetSidStereoAddress(uint16 sidAddress) +{ + snapshotsManager->LockMutex(); + c64d_sid_set_stereo_address(sidAddress); + snapshotsManager->UnlockMutex(); +} + +void CDebugInterfaceVice::SetSidTripleAddress(uint16 sidAddress) +{ + snapshotsManager->LockMutex(); + c64d_sid_set_triple_address(sidAddress); + snapshotsManager->UnlockMutex(); +} + + + +///// c64model.c +//#define C64MODEL_C64_PAL 0 +//#define C64MODEL_C64C_PAL 1 +//#define C64MODEL_C64_OLD_PAL 2 +// +//#define C64MODEL_C64_NTSC 3 +//#define C64MODEL_C64C_NTSC 4 +//#define C64MODEL_C64_OLD_NTSC 5 +// +//#define C64MODEL_C64_PAL_N 6 +// +///* SX-64 */ +//#define C64MODEL_C64SX_PAL 7 +//#define C64MODEL_C64SX_NTSC 8 +// +//#define C64MODEL_C64_JAP 9 +//#define C64MODEL_C64_GS 10 +// +//#define C64MODEL_PET64_PAL 11 +//#define C64MODEL_PET64_NTSC 12 +///* max machine */ +//#define C64MODEL_ULTIMAX 13 + +void CDebugInterfaceVice::GetC64ModelTypes(std::vector *modelTypeNames, std::vector *modelTypeIds) +{ + modelTypeNames->push_back(new CSlrString("C64 PAL")); + modelTypeIds->push_back(0); + modelTypeNames->push_back(new CSlrString("C64C PAL")); + modelTypeIds->push_back(1); + modelTypeNames->push_back(new CSlrString("C64 old PAL")); + modelTypeIds->push_back(2); + modelTypeNames->push_back(new CSlrString("C64 NTSC")); + modelTypeIds->push_back(3); + modelTypeNames->push_back(new CSlrString("C64C NTSC")); + modelTypeIds->push_back(4); + modelTypeNames->push_back(new CSlrString("C64 old NTSC")); + modelTypeIds->push_back(5); + // crashes: modelTypeNames->push_back(new CSlrString("C64 PAL N (Drean)")); + // crashes: modelTypeIds->push_back(6); + modelTypeNames->push_back(new CSlrString("C64 SX PAL")); + modelTypeIds->push_back(7); + modelTypeNames->push_back(new CSlrString("C64 SX NTSC")); + modelTypeIds->push_back(8); + // no ROM: modelTypeNames->push_back(new CSlrString("Japanese")); + // no ROM: modelTypeIds->push_back(9); + // no ROM: modelTypeNames->push_back(new CSlrString("C64 GS")); + // no ROM: modelTypeIds->push_back(10); + modelTypeNames->push_back(new CSlrString("PET64 PAL")); + modelTypeIds->push_back(11); + modelTypeNames->push_back(new CSlrString("PET64 NTSC")); + modelTypeIds->push_back(12); + // no ROM: modelTypeNames->push_back(new CSlrString("MAX Machine")); + // no ROM: modelTypeIds->push_back(13); +} + +void CDebugInterfaceVice::GetC64ModelTypes(std::vector *modelTypeNames, std::vector *modelTypeIds) +{ + modelTypeNames->push_back("C64 PAL"); + modelTypeIds->push_back(0); + modelTypeNames->push_back("C64C PAL"); + modelTypeIds->push_back(1); + modelTypeNames->push_back("C64 old PAL"); + modelTypeIds->push_back(2); + modelTypeNames->push_back("C64 NTSC"); + modelTypeIds->push_back(3); + modelTypeNames->push_back("C64C NTSC"); + modelTypeIds->push_back(4); + modelTypeNames->push_back("C64 old NTSC"); + modelTypeIds->push_back(5); + // crashes: modelTypeNames->push_back("C64 PAL N (Drean)"); + // crashes: modelTypeIds->push_back(6); + modelTypeNames->push_back("C64 SX PAL"); + modelTypeIds->push_back(7); + modelTypeNames->push_back("C64 SX NTSC"); + modelTypeIds->push_back(8); + // no ROM: modelTypeNames->push_back("Japanese"); + // no ROM: modelTypeIds->push_back(9); + // no ROM: modelTypeNames->push_back("C64 GS"); + // no ROM: modelTypeIds->push_back(10); + modelTypeNames->push_back("PET64 PAL"); + modelTypeIds->push_back(11); + modelTypeNames->push_back("PET64 NTSC"); + modelTypeIds->push_back(12); + // no ROM: modelTypeNames->push_back("MAX Machine"); + // no ROM: modelTypeIds->push_back(13); +} +int c64_change_model_type; + +static void c64_change_model_trap(WORD addr, void *v) +{ + guiMain->LockMutex(); + debugInterfaceVice->LockRenderScreenMutex(); + + LOGD("c64_change_model_trap: model=%d", c64_change_model_type); + + //c64_change_model_type = 0; + + c64model_set(c64_change_model_type); + + debugInterfaceVice->modelType = c64_change_model_type; + + c64d_update_c64_machine_from_model_type(c64_change_model_type); + c64d_update_c64_screen_height_from_model_type(c64_change_model_type); + + c64d_clear_screen(); + + SYS_Sleep(100); + + c64d_clear_screen(); + + debugInterfaceVice->UnlockRenderScreenMutex(); + + debugInterfaceVice->ResetEmulationFrameCounter(); + + guiMain->UnlockMutex(); +} + +void CDebugInterfaceVice::SetC64ModelType(int modelType) +{ + LOGM("CDebugInterfaceVice::SetC64ModelType: %d", modelType); + + // blank screen when machine type is changed + c64d_clear_screen(); + + c64d_update_c64_machine_from_model_type(c64_change_model_type); + + c64_change_model_type = modelType; + interrupt_maincpu_trigger_trap(c64_change_model_trap, NULL); +} + +uint8 CDebugInterfaceVice::GetC64MachineType() +{ + return machineType; +} + +int CDebugInterfaceVice::GetC64ModelType() +{ + snapshotsManager->LockMutex(); + int model = c64model_get(); + snapshotsManager->UnlockMutex(); + return model; +} + +void CDebugInterfaceVice::SetEmulationMaximumSpeed(int maximumSpeed) +{ + resources_set_int("Speed", maximumSpeed); + + if (maximumSpeed < 20) + { + resources_set_int("Sound", 0); + } + else + { + resources_set_int("Sound", 1); + } +} + +extern "C" { + int set_vsp_bug_enabled(int val, void *param); +} + +void CDebugInterfaceVice::SetVSPBugEmulation(bool isVSPBugEmulation) +{ + if (isVSPBugEmulation) + { + set_vsp_bug_enabled(1, NULL); + } + else + { + set_vsp_bug_enabled(0, NULL); + } +} + + +/// +/// + +extern "C" { + void c64d_mem_write_c64(unsigned int addr, unsigned char value); + void c64d_mem_write_c64_no_mark(unsigned int addr, unsigned char value); + void c64d_mem_ram_write_c64(WORD addr, BYTE value); + void c64d_mem_ram_fill_c64(WORD addr, WORD size, BYTE value); +} + +void CDebugInterfaceVice::SetByteC64(uint16 addr, uint8 val) +{ + c64d_mem_write_c64(addr, val); +} + +void CDebugInterfaceVice::SetByteToRamC64(uint16 addr, uint8 val) +{ + c64d_mem_ram_write_c64(addr, val); +} + +/////// + +extern "C" { + //BYTE mem_bank_peek(int bank, WORD addr, void *context); // can't be used, because reading affects/changes state + BYTE c64d_peek_c64(WORD addr); + BYTE c64d_mem_ram_read_c64(WORD addr); + void c64d_peek_memory_c64(BYTE *buffer, int addrStart, int addrEnd); + void c64d_copy_ram_memory_c64(BYTE *buffer, int addrStart, int addrEnd); + void c64d_copy_whole_mem_ram_c64(BYTE *destBuf); + void c64d_peek_whole_map_c64(BYTE *memoryBuffer); +} + +/***********/ +uint8 CDebugInterfaceVice::GetByteC64(uint16 addr) +{ + return c64d_peek_c64(addr); +} + + +uint8 CDebugInterfaceVice::GetByteFromRamC64(uint16 addr) +{ + return c64d_mem_ram_read_c64(addr); +} + + +/// + +extern "C" { + void mon_jump(MON_ADDR addr); + void c64d_set_c64_pc(uint16 pc); + void c64d_mem_ram_write_drive(int driveNum, uint16 addr, uint8 value); + void c64d_drive_poke(int driveNum, uint16 addr, uint8 value); + void c64d_set_drive_pc(int driveNr, uint16 pc); + +} + +void CDebugInterfaceVice::SetVicRegister(uint8 registerNum, uint8 value) +{ + vicii_store(registerNum, value); + + if (registerNum >= 0x20 && registerNum <= 0x2E) + { + c64d_set_color_register(registerNum, value); + } +} + +u8 CDebugInterfaceVice::GetVicRegister(uint8 registerNum) +{ + BYTE v = vicii_peek(registerNum); + return v; +} + +// +extern "C" { + cia_context_t *c64d_get_cia_context(int ciaId); + BYTE c64d_ciacore_peek(cia_context_t *cia_context, WORD addr); + void ciacore_store(cia_context_t *cia_context, WORD addr, BYTE value); +} + +void CDebugInterfaceVice::SetCiaRegister(uint8 ciaId, uint8 registerNum, uint8 value) +{ + cia_context_t *cia_context = c64d_get_cia_context(ciaId); + ciacore_store(cia_context, registerNum, value); +} + +u8 CDebugInterfaceVice::GetCiaRegister(uint8 ciaId, uint8 registerNum) +{ + cia_context_t *cia_context = c64d_get_cia_context(ciaId); + return c64d_ciacore_peek(cia_context, registerNum); +} + +extern "C" { + BYTE sid_peek_chip(WORD addr, int chipno); + void sid_store_chip(WORD addr, BYTE value, int chipno); +} + +struct SetSidRegisterData { + WORD registerNum; + BYTE value; + int sidId; +}; + +static void c64_set_sid_register_trap(WORD addr, void *v) +{ + guiMain->LockMutex(); + debugInterfaceVice->LockMutex(); + gSoundEngine->LockMutex("CDebugInterfaceVice::c64_set_sid_register_trap"); + + SetSidRegisterData *setSidRegisterData = (SetSidRegisterData *)v; + + sid_store_chip(setSidRegisterData->registerNum, setSidRegisterData->value, setSidRegisterData->sidId); + delete setSidRegisterData; + + gSoundEngine->UnlockMutex("CDebugInterfaceVice::c64_set_sid_register_trap"); + debugInterfaceVice->UnlockMutex(); + guiMain->UnlockMutex(); +} + +void CDebugInterfaceVice::SetSidRegister(uint8 sidId, uint8 registerNum, uint8 value) +{ + snapshotsManager->LockMutex(); + + this->LockMutex(); + + if (this->GetDebugMode() == DEBUGGER_MODE_PAUSED) + { + this->LockIoMutex(); + sid_store_chip(registerNum, value, sidId); + this->UnlockIoMutex(); + } + else + { + SetSidRegisterData *setSidRegisterData = new SetSidRegisterData(); + setSidRegisterData->sidId = sidId; + setSidRegisterData->registerNum = registerNum; + setSidRegisterData->value = value; + interrupt_maincpu_trigger_trap(c64_set_sid_register_trap, setSidRegisterData); + } + + this->UnlockMutex(); + snapshotsManager->UnlockMutex(); +} + +void c64_set_sid_data(void *v) +{ + guiMain->LockMutex(); + debugInterfaceVice->LockMutex(); + gSoundEngine->LockMutex("CDebugInterfaceVice::c64_set_sid_data"); + + CSidData *sidData = (CSidData *)v; + sidData->RestoreSids(); + + gSoundEngine->UnlockMutex("CDebugInterfaceVice::c64_set_sid_data"); + debugInterfaceVice->UnlockMutex(); + guiMain->UnlockMutex(); +} + + +void CDebugInterfaceVice::SetSid(CSidData *sidData) +{ + this->LockMutex(); + snapshotsManager->LockMutex(); + + this->sidDataToRestore = sidData; + + snapshotsManager->UnlockMutex(); + this->UnlockMutex(); +} + +u8 CDebugInterfaceVice::GetSidRegister(uint8 sidId, uint8 registerNum) +{ + return sid_peek_chip(registerNum, sidId); +} + +extern "C" { + void via1d1541_store(drive_context_t *ctxptr, WORD addr, BYTE data); + BYTE c64d_via1d1541_peek(drive_context_t *ctxptr, WORD addr); + void via2d_store(drive_context_t *ctxptr, WORD addr, BYTE data); + BYTE c64d_via2d_peek(drive_context_t *ctxptr, WORD addr); +} +void CDebugInterfaceVice::SetViaRegister(uint8 driveId, uint8 viaId, uint8 registerNum, uint8 value) +{ + drive_context_t *drivectx = drive_context[driveId]; + + if (viaId == 1) + { + via1d1541_store(drivectx, registerNum, value); + } + else + { + via2d_store(drivectx, registerNum, value); + } + +} + +u8 CDebugInterfaceVice::GetViaRegister(uint8 driveId, uint8 viaId, uint8 registerNum) +{ + drive_context_t *drivectx = drive_context[driveId]; + + if (viaId == 1) + { + return c64d_via1d1541_peek(drivectx, registerNum); + } + + return c64d_via2d_peek(drivectx, registerNum); +} + + + +void CDebugInterfaceVice::MakeJmpC64(uint16 addr) +{ + LOGD("CDebugInterfaceVice::MakeJmpC64: %04x", addr); + + if (c64d_debug_mode == DEBUGGER_MODE_PAUSED) + { + c64d_set_c64_pc(addr); + c64d_set_debug_mode(DEBUGGER_MODE_PAUSED); + } + else + { + c64d_set_c64_pc(addr); + } +} + +void CDebugInterfaceVice::MakeJmpNoResetC64(uint16 addr) +{ + LOGTODO("CDebugInterfaceVice::MakeJmpNoResetC64"); + // TODO: + this->MakeJmpC64(addr); +} + +void CDebugInterfaceVice::MakeJsrC64(uint16 addr) +{ + LOGTODO("CDebugInterfaceVice::MakeJsrC64"); + // TODO: + this->MakeJmpC64(addr); +} + +extern "C" { + void c64d_maincpu_make_basic_run(); +}; + +void CDebugInterfaceVice::MakeJMPToBasicRunC64() +{ + LOGD("CDebugInterfaceVice::MakeJMPToBasicRunC64"); + + c64d_maincpu_make_basic_run(); +} + + +extern "C" { + void c64d_set_maincpu_regs(uint8 *a, uint8 *x, uint8 *y, uint8 *p, uint8 *sp); + void c64d_set_maincpu_set_sp(uint8 *sp); + void c64d_set_maincpu_set_a(uint8 *a); + void c64d_set_maincpu_set_x(uint8 *x); + void c64d_set_maincpu_set_y(uint8 *y); + void c64d_set_maincpu_set_p(uint8 *p); + +} + +void CDebugInterfaceVice::SetStackPointerC64(uint8 val) +{ + LOGD("CDebugInterfaceVice::SetStackPointerC64: val=%x", val); + + this->LockMutex(); + + uint8 sp = val; + c64d_set_maincpu_set_sp(&sp); + + this->UnlockMutex(); +} + +void CDebugInterfaceVice::SetRegisterAC64(uint8 val) +{ + LOGD("CDebugInterfaceVice::SetRegisterAC64: val=%x", val); + + this->LockMutex(); + + uint8 a = val; + c64d_set_maincpu_set_a(&a); + + this->UnlockMutex(); +} + +void CDebugInterfaceVice::SetRegisterXC64(uint8 val) +{ + LOGD("CDebugInterfaceVice::SetRegisterXC64: val=%x", val); + + this->LockMutex(); + + uint8 x = val; + c64d_set_maincpu_set_x(&x); + + this->UnlockMutex(); +} + +void CDebugInterfaceVice::SetRegisterYC64(uint8 val) +{ + LOGD("CDebugInterfaceVice::SetRegisterYC64: val=%x", val); + + this->LockMutex(); + + uint8 y = val; + c64d_set_maincpu_set_y(&y); + + this->UnlockMutex(); +} + +void CDebugInterfaceVice::SetRegisterPC64(uint8 val) +{ + LOGD("CDebugInterfaceVice::SetRegisterPC64: val=%x", val); + + this->LockMutex(); + + uint8 p = val; + c64d_set_maincpu_set_p(&p); + + this->UnlockMutex(); +} + +extern "C" { + void c64d_set_drive_register_a(int driveNr, uint8 a); + void c64d_set_drive_register_x(int driveNr, uint8 x); + void c64d_set_drive_register_y(int driveNr, uint8 y); + void c64d_set_drive_register_p(int driveNr, uint8 p); + void c64d_set_drive_register_sp(int driveNr, uint8 sp); +} + +void CDebugInterfaceVice::SetRegisterA1541(uint8 val) +{ + this->LockMutex(); + + c64d_set_drive_register_a(0, val); + + this->UnlockMutex(); +} + +void CDebugInterfaceVice::SetRegisterX1541(uint8 val) +{ + this->LockMutex(); + + c64d_set_drive_register_x(0, val); + + this->UnlockMutex(); +} + +void CDebugInterfaceVice::SetRegisterY1541(uint8 val) +{ + this->LockMutex(); + + c64d_set_drive_register_y(0, val); + + this->UnlockMutex(); +} + +void CDebugInterfaceVice::SetRegisterP1541(uint8 val) +{ + this->LockMutex(); + + c64d_set_drive_register_p(0, val); + + this->UnlockMutex(); +} + +void CDebugInterfaceVice::SetStackPointer1541(uint8 val) +{ + this->LockMutex(); + + c64d_set_drive_register_sp(0, val); + + this->UnlockMutex(); +} + + +void CDebugInterfaceVice::SetByte1541(uint16 addr, uint8 val) +{ + c64d_drive_poke(0, addr, val); +} + +void CDebugInterfaceVice::SetByteToRam1541(uint16 addr, uint8 val) +{ + c64d_mem_ram_write_drive(0, addr, val); +} + +extern "C" { + uint8 c64d_peek_drive(int driveNum, uint16 addr); + uint8 c64d_mem_ram_read_drive(int driveNum, uint16 addr); + void c64d_peek_memory_drive(int driveNum, BYTE *buffer, int addrStart, int addrEnd); + void c64d_copy_ram_memory_drive(int driveNum, BYTE *buffer, int addrStart, int addrEnd); + void c64d_peek_whole_map_drive(int driveNum, uint8 *memoryBuffer); + void c64d_copy_mem_ram_drive(int driveNum, uint8 *memoryBuffer); +} + +uint8 CDebugInterfaceVice::GetByte1541(uint16 addr) +{ + return c64d_peek_drive(0, addr); +} + +uint8 CDebugInterfaceVice::GetByteFromRam1541(uint16 addr) +{ + return c64d_mem_ram_read_drive(0, addr); +} + +void CDebugInterfaceVice::MakeJmp1541(uint16 addr) +{ + if (c64d_debug_mode == DEBUGGER_MODE_PAUSED) + { + c64d_set_drive_pc(0, addr); + //c64d_set_debug_mode(DEBUGGER_MODE_RUN_ONE_INSTRUCTION); + } + else + { + c64d_set_drive_pc(0, addr); + } +} + +void CDebugInterfaceVice::MakeJmpNoReset1541(uint16 addr) +{ + this->MakeJmp1541(addr); +} + + +void CDebugInterfaceVice::GetWholeMemoryMap(uint8 *buffer) +{ + c64d_peek_whole_map_c64(buffer); +} + +void CDebugInterfaceVice::GetWholeMemoryMapFromRam(uint8 *buffer) +{ + c64d_copy_whole_mem_ram_c64(buffer); +} + +void CDebugInterfaceVice::GetWholeMemoryMap1541(uint8 *buffer) +{ + c64d_peek_whole_map_drive(0, buffer); +} + +void CDebugInterfaceVice::GetWholeMemoryMapFromRam1541(uint8 *buffer) +{ + c64d_copy_mem_ram_drive(0, buffer); +} + + +void CDebugInterfaceVice::GetMemoryC64(uint8 *buffer, int addrStart, int addrEnd) +{ + c64d_peek_memory_c64(buffer, addrStart, addrEnd); +} + +void CDebugInterfaceVice::GetMemoryFromRam(uint8 *buffer, int addrStart, int addrEnd) +{ + c64d_copy_ram_memory_c64(buffer, addrStart, addrEnd); +} + +void CDebugInterfaceVice::GetMemoryFromRamC64(uint8 *buffer, int addrStart, int addrEnd) +{ + c64d_copy_ram_memory_c64(buffer, addrStart, addrEnd); +} + +void CDebugInterfaceVice::GetMemoryDrive1541(uint8 *buffer, int addrStart, int addrEnd) +{ + c64d_peek_memory_drive(0, buffer, addrStart, addrEnd); +} + +void CDebugInterfaceVice::GetMemoryFromRamDrive1541(uint8 *buffer, int addrStart, int addrEnd) +{ + c64d_copy_ram_memory_drive(0, buffer, addrStart, addrEnd); +} + +void CDebugInterfaceVice::FillC64Ram(uint16 addr, uint16 size, uint8 value) +{ + c64d_mem_ram_fill_c64(addr, size, value); +} + + +/// + +extern "C" { + void c64d_get_vic_colors(uint8 *cD021, uint8 *cD022, uint8 *cD023, uint8 *cD025, uint8 *cD026, uint8 *cD027, uint8 *cD800); +} + +void CDebugInterfaceVice::GetVICColors(uint8 *cD021, uint8 *cD022, uint8 *cD023, uint8 *cD025, uint8 *cD026, uint8 *cD027, uint8 *cD800) +{ + c64d_get_vic_colors(cD021, cD022, cD023, cD025, cD026, cD027, cD800); +} + + +void CDebugInterfaceVice::GetVICSpriteColors(uint8 *cD021, uint8 *cD025, uint8 *cD026, uint8 *spriteColors) +{ + SYS_FatalExit("CDebugInterfaceVice::GetVICSpriteColors: not implemented"); +} + +void CDebugInterfaceVice::GetCBMColor(uint8 colorNum, uint8 *r, uint8 *g, uint8 *b) +{ + *r = c64d_palette_red[colorNum & 0x0F]; + *g = c64d_palette_green[colorNum & 0x0F]; + *b = c64d_palette_blue[colorNum & 0x0F]; +} + +void CDebugInterfaceVice::GetFloatCBMColor(uint8 colorNum, float *r, float *g, float *b) +{ + *r = c64d_float_palette_red[colorNum & 0x0F]; + *g = c64d_float_palette_green[colorNum & 0x0F]; + *b = c64d_float_palette_blue[colorNum & 0x0F]; +} + + + +void CDebugInterfaceVice::SetDebugMode(uint8 debugMode) +{ + LOGD("CDebugInterfaceVice::SetDebugMode: %d (cycle=%d)", debugMode, GetMainCpuCycleCounter()); + + c64d_set_debug_mode(debugMode); + +} + +uint8 CDebugInterfaceVice::GetDebugMode() +{ + return c64d_debug_mode; +} + +// tape +extern "C" { + int tape_image_attach(unsigned int unit, const char *name); + int tape_image_detach(unsigned int unit); + void datasette_control(int command); +} + +static void tape_attach_trap(WORD addr, void *v) +{ + char *filePath = (char*)v; + tape_image_attach(1, filePath); + + SYS_ReleaseCharBuf(filePath); +} + +static void tape_detach_trap(WORD addr, void *v) +{ + tape_image_detach(1); +} + +void CDebugInterfaceVice::AttachTape(CSlrString *filePath) +{ + char *asciiPath = filePath->GetStdASCII(); + + SYS_FixFileNameSlashes(asciiPath); + + char *buf = SYS_GetCharBuf(); + strcpy(buf, asciiPath); + + interrupt_maincpu_trigger_trap(tape_attach_trap, asciiPath); +} + +void CDebugInterfaceVice::DetachTape() +{ + interrupt_maincpu_trigger_trap(tape_detach_trap, NULL); +} + +void CDebugInterfaceVice::DatasettePlay() +{ + datasette_control(DATASETTE_CONTROL_START); +} + +void CDebugInterfaceVice::DatasetteStop() +{ + datasette_control(DATASETTE_CONTROL_STOP); +} + +void CDebugInterfaceVice::DatasetteForward() +{ + datasette_control(DATASETTE_CONTROL_FORWARD); +} + +void CDebugInterfaceVice::DatasetteRewind() +{ + datasette_control(DATASETTE_CONTROL_REWIND); +} + +void CDebugInterfaceVice::DatasetteRecord() +{ + datasette_control(DATASETTE_CONTROL_RECORD); +} + +void CDebugInterfaceVice::DatasetteReset() +{ + datasette_control(DATASETTE_CONTROL_RESET); +} + +void CDebugInterfaceVice::DatasetteSetSpeedTuning(int speedTuning) +{ + resources_set_int("DatasetteSpeedTuning", speedTuning); +} + +void CDebugInterfaceVice::DatasetteSetZeroGapDelay(int zeroGapDelay) +{ + resources_set_int("DatasetteZeroGapDelay", zeroGapDelay); +} + +void CDebugInterfaceVice::DatasetteSetResetWithCPU(bool resetWithCPU) +{ + resources_set_int("DatasetteResetWithCPU", resetWithCPU ? 1:0); +} + +void CDebugInterfaceVice::DatasetteSetTapeWobble(int tapeWobble) +{ + resources_set_int("DatasetteTapeWobble", tapeWobble); +} + + +// http://www.lemon64.com/?mainurl=http%3A//www.lemon64.com/apps/list.php%3FGenre%3Dcarts + +extern "C" { + int cartridge_attach_image(int type, const char *filename); + void cartridge_detach_image(int type); + void cartridge_trigger_freeze(void); +} + +static void cartridge_attach_trap(WORD addr, void *v) +{ + char *filePath = (char*)v; + cartridge_attach_image(0, filePath); + + SYS_ReleaseCharBuf(filePath); + + debugInterfaceVice->ResetEmulationFrameCounter(); +} + +static void cartridge_detach_trap(WORD addr, void *v) +{ + // -1 means all slots + cartridge_detach_image(-1); + machine_trigger_reset(MACHINE_RESET_MODE_HARD); + debugInterfaceVice->ResetEmulationFrameCounter(); + c64d_maincpu_clk = 6; +} + +void CDebugInterfaceVice::AttachCartridge(CSlrString *filePath) +{ + char *asciiPath = filePath->GetStdASCII(); + + SYS_FixFileNameSlashes(asciiPath); + +// this->SetDebugMode(C64_DEBUG_RUN_ONE_INSTRUCTION); +// SYS_Sleep(5000); + +// gSoundEngine->LockMutex("CDebugInterfaceVice::CartridgeAttach"); +// debugInterfaceVice->LockMutex(); +// guiMain->LockMutex(); + + + cartridge_attach_image(0, asciiPath); + + +// guiMain->UnlockMutex(); +// debugInterfaceVice->UnlockMutex(); +// gSoundEngine->UnlockMutex("CDebugInterfaceVice::CartridgeAttach"); + + +// char *buf = SYS_GetCharBuf(); +// strcpy(buf, filePath); +// interrupt_maincpu_trigger_trap(cartridge_attach_trap, buf); + +// SYS_Sleep(1000); +// this->SetDebugMode(C64_DEBUG_RUNNING); + + debugInterfaceVice->ResetEmulationFrameCounter(); +} + +void CDebugInterfaceVice::DetachCartridge() +{ + interrupt_maincpu_trigger_trap(cartridge_detach_trap, NULL); +} + +void CDebugInterfaceVice::CartridgeFreezeButtonPressed() +{ + keyboard_clear_keymatrix(); + cartridge_trigger_freeze(); +} + +extern "C" { + void c64d_get_exrom_game(BYTE *exrom, BYTE *game); +} + +void CDebugInterfaceVice::GetC64CartridgeState(C64StateCartridge *cartridgeState) +{ + c64d_get_exrom_game(&(cartridgeState->exrom), &(cartridgeState)->game); +} + +static void trap_detach_everything(WORD addr, void *v) +{ + // -1 means all slots + cartridge_detach_image(-1); + machine_trigger_reset(MACHINE_RESET_MODE_HARD); + debugInterfaceVice->ResetEmulationFrameCounter(); + c64d_maincpu_clk = 6; + + tape_image_detach(1); + + file_system_detach_disk(8); + + ((CDataAdapterViceDrive1541DiskContents*)debugInterfaceVice->dataAdapterDrive1541DiskContents)->DiskDetached(); +} + + +void CDebugInterfaceVice::DetachEverything() +{ + interrupt_maincpu_trigger_trap(trap_detach_everything, NULL); +} + + +extern "C" { + void c64d_c64_set_vicii_record_state_mode(uint8 recordMode); +} + +void CDebugInterfaceVice::SetVicRecordStateMode(uint8 recordMode) +{ + c64d_c64_set_vicii_record_state_mode(recordMode); +} + + +void CDebugInterfaceVice::SetSIDMuteChannels(int sidNumber, bool mute1, bool mute2, bool mute3, bool muteExt) +{ + uint8 sidVoiceMask = 0xF0; + + if (mute1 == false) + { + sidVoiceMask |= 0x01; + } + if (mute2 == false) + { + sidVoiceMask |= 0x02; + } + if (mute3 == false) + { + sidVoiceMask |= 0x04; + } + if (muteExt == false) + { + sidVoiceMask |= 0x08; + } + + sid_set_voice_mask(sidNumber, sidVoiceMask); + +} + +void CDebugInterfaceVice::SetSIDReceiveChannelsData(int sidNumber, bool isReceiving) +{ + if (isReceiving) + { + c64d_sid_receive_channels_data(sidNumber, 1); + } + else + { + c64d_sid_receive_channels_data(sidNumber, 0); + } +} + +void c64d_update_c64_model() +{ + int modelType = c64model_get(); + c64d_update_c64_machine_from_model_type(modelType); + c64d_update_c64_screen_height_from_model_type(modelType); + +} + +void c64d_update_c64_machine_from_model_type(int modelType) +{ + switch(c64_change_model_type) + { + default: + case 0: + case 1: + case 2: + case 6: + case 7: + case 11: + // PAL, 312 lines + debugInterfaceVice->machineType = MACHINE_TYPE_PAL; + debugInterfaceVice->numEmulationFPS = 50; + break; + case 3: + case 4: + case 5: + case 8: + case 12: + // NTSC, 275 lines + debugInterfaceVice->machineType = MACHINE_TYPE_NTSC; + debugInterfaceVice->numEmulationFPS = 60; + break; + } +} + +void c64d_update_c64_screen_height_from_model_type(int modelType) +{ + switch(c64_change_model_type) + { + default: + case 0: + case 1: + case 2: + case 6: + case 7: + case 11: + // PAL, 312 lines +// debugInterfaceVice->screenHeight = 272; + break; + case 3: + case 4: + case 5: + case 8: + case 12: + // NTSC, 275 lines +// debugInterfaceVice->screenHeight = 259; + break; + } +} + + +static void load_snapshot_trap(WORD addr, void *v) +{ + LOGD("load_snapshot_trap"); + + guiMain->LockMutex(); + debugInterfaceVice->LockMutex(); + + char *filePath = (char*)v; + //int ret = + + FILE *fp = fopen(filePath, "rb"); + if (!fp) + { + viewC64->ShowMessageError("Snapshot not found"); + debugInterfaceVice->UnlockMutex(); + guiMain->UnlockMutex(); + return; + } + fclose(fp); + + gSoundEngine->LockMutex("load_snapshot_trap"); + + if (c64_snapshot_read(filePath, 0, 1, 1, 1, 1) < 0) + { + viewC64->ShowMessageError("Snapshot loading failed"); + + debugInterfaceVice->machineType = MACHINE_TYPE_UNKNOWN; + debugInterfaceVice->numEmulationFPS = 1; + + c64d_clear_screen(); + } + else + { + // if CPU is in JAM then un-jam and continue + if (c64d_is_cpu_in_jam_state == 1) + { + c64d_is_cpu_in_jam_state = 0; + c64d_set_debug_mode(DEBUGGER_MODE_RUNNING); + } + } + + c64d_update_c64_model(); + + debugInterfaceVice->SetSidTypeAsync(c64SettingsSIDEngineModel); + debugInterfaceVice->SetSidSamplingMethod(c64SettingsRESIDSamplingMethod); + debugInterfaceVice->SetSidEmulateFilters(c64SettingsRESIDEmulateFilters); + debugInterfaceVice->SetSidPassBand(c64SettingsRESIDPassBand); + debugInterfaceVice->SetSidFilterBias(c64SettingsRESIDFilterBias); + + int val; + resources_get_int("SidStereo", &val); + c64SettingsSIDStereo = val; + + resources_get_int("SidStereoAddressStart", &val); + c64SettingsSIDStereoAddress = val; + + resources_get_int("SidTripleAddressStart", &val); + c64SettingsSIDTripleAddress = val; + + gSoundEngine->UnlockMutex("load_snapshot_trap"); + + SYS_ReleaseCharBuf(filePath); + + debugInterfaceVice->ClearHistory(); + ((CDataAdapterViceDrive1541DiskContents*)debugInterfaceVice->dataAdapterDrive1541DiskContents)->DiskAttached(); + + debugInterfaceVice->UnlockMutex(); + guiMain->UnlockMutex(); +} + + +bool CDebugInterfaceVice::LoadFullSnapshot(char *filePath) +{ + char *buf = SYS_GetCharBuf(); + strcpy(buf, filePath); + + this->machineType = MACHINE_TYPE_LOADING_SNAPSHOT; + debugInterfaceVice->numEmulationFPS = 1; + + interrupt_maincpu_trigger_trap(load_snapshot_trap, buf); + + if (c64d_debug_mode == DEBUGGER_MODE_PAUSED) + { + c64d_set_debug_mode(DEBUGGER_MODE_RUN_ONE_INSTRUCTION); + } + + return true; +} + +static void save_snapshot_trap(WORD addr, void *v) +{ + LOGD("save_snapshot_trap"); + + debugInterfaceVice->LockMutex(); + + char *filePath = (char*)v; + + gSoundEngine->LockMutex("save_snapshot_trap"); + + c64_snapshot_write(filePath, 0, 1, 0, 1, 1, 1); + + gSoundEngine->UnlockMutex("save_snapshot_trap"); + + SYS_ReleaseCharBuf(filePath); + + debugInterfaceVice->UnlockMutex(); +} + +void CDebugInterfaceVice::SaveFullSnapshot(char *filePath) +{ + // if (c64d_debug_mode == C64_DEBUG_PAUSED) + // { + // // can we? + // c64_snapshot_write(filePath, 0, 1, 0); + // } + // else + { + char *buf = SYS_GetCharBuf(); + strcpy(buf, filePath); + interrupt_maincpu_trigger_trap(save_snapshot_trap, buf); + } + + if (c64d_debug_mode == DEBUGGER_MODE_PAUSED) + { + c64d_set_debug_mode(DEBUGGER_MODE_RUN_ONE_INSTRUCTION); + } +} + +// snapshots +bool CDebugInterfaceVice::LoadFullSnapshot(CByteBuffer *byteBuffer) +{ + LOGD("LoadFullSnapshot"); + debugInterfaceVice->LockMutex(); + gSoundEngine->LockMutex("LoadFullSnapshot"); + + int ret = c64_snapshot_read_from_memory(1, 1, 1, 1, 1, 1, byteBuffer->data, byteBuffer->length); + if (ret != 0) + { + LOGError("CDebugInterfaceVice::LoadFullSnapshot: failed"); + + gSoundEngine->UnlockMutex("LoadFullSnapshot"); + debugInterfaceVice->UnlockMutex(); + return false; + } + + gSoundEngine->UnlockMutex("LoadFullSnapshot"); + debugInterfaceVice->UnlockMutex(); + return true; +} + +void CDebugInterfaceVice::SaveFullSnapshot(CByteBuffer *snapshotBuffer) +{ + SYS_FatalExit("CDebugInterfaceVice::LoadFullSnapshot: not implemented"); +} + + +// these calls should be synced with CPU IRQ so snapshot store or restore is allowed +bool CDebugInterfaceVice::LoadChipsSnapshotSynced(CByteBuffer *byteBuffer) +{ +// extern int c64_snapshot_read_from_memory(int event_mode, int read_roms, int read_disks, int read_reu_data, +// unsigned char *snapshot_data, int snapshot_size); + + LOGD("LoadChipsSnapshotSynced"); + debugInterfaceVice->LockMutex(); + gSoundEngine->LockMutex("LoadChipsSnapshotSynced"); + + int ret = c64_snapshot_read_from_memory(1, 0, 0, 0, 0, 0, byteBuffer->data, byteBuffer->length); + if (ret != 0) + { + LOGError("CDebugInterfaceVice::LoadFullSnapshotSynced: failed"); + + gSoundEngine->UnlockMutex("LoadChipsSnapshotSynced"); + debugInterfaceVice->UnlockMutex(); + return false; + } + + gSoundEngine->UnlockMutex("LoadChipsSnapshotSynced"); + debugInterfaceVice->UnlockMutex(); + return true; +} + +bool CDebugInterfaceVice::SaveChipsSnapshotSynced(CByteBuffer *byteBuffer) +{ + // TODO: check if data changed and store snapshot with data accordingly + return this->SaveFullSnapshotSynced(byteBuffer, true, false, false, false, false, false, true); +} + +bool CDebugInterfaceVice::LoadDiskDataSnapshotSynced(CByteBuffer *byteBuffer) +{ + // extern int c64_snapshot_read_from_memory(int event_mode, int read_roms, int read_disks, int read_reu_data, + // unsigned char *snapshot_data, int snapshot_size); + + LOGD("LoadDiskDataSnapshotSynced"); + debugInterfaceVice->LockMutex(); + gSoundEngine->LockMutex("LoadDiskDataSnapshotSynced"); + +// int ret = c64_snapshot_read_from_memory(0, 0, 1, 0, 0, byteBuffer->data, byteBuffer->length); + int ret = c64_snapshot_read_from_memory(0, 0, 1, 0, 0, 1, byteBuffer->data, byteBuffer->length); + if (ret != 0) + { + LOGError("CDebugInterfaceVice::LoadFullSnapshotSynced: failed"); + + gSoundEngine->UnlockMutex("LoadDiskDataSnapshotSynced"); + debugInterfaceVice->UnlockMutex(); + return false; + } + + gSoundEngine->UnlockMutex("LoadDiskDataSnapshotSynced"); + debugInterfaceVice->UnlockMutex(); + + debugInterfaceVice->dataAdapterViceDrive1541DiskContents->DiskAttached(); + +// viewC64->viewDrive1541Browser->RefreshInsertedDiskImageAsync(); + return true; +} + +bool CDebugInterfaceVice::SaveDiskDataSnapshotSynced(CByteBuffer *byteBuffer) +{ + // TODO: check if data changed and store snapshot with data accordingly + return this->SaveFullSnapshotSynced(byteBuffer, + true, false, true, false, false, true, false); +} + +bool CDebugInterfaceVice::SaveFullSnapshotSynced(CByteBuffer *byteBuffer, + bool saveChips, bool saveRoms, bool saveDisks, bool eventMode, + bool saveReuData, bool saveCartRoms, bool saveScreen) +{ +// LOGD("SaveFullSnapshotSynced: saveDisks=%d data=%x", saveDisks, byteBuffer->data); + int snapshotSize = 0; + u8 *snapshotData = NULL; + + debugInterfaceVice->LockMutex(); + gSoundEngine->LockMutex("SaveFullSnapshotSynced"); + + // TODO: reuse byteBuffer->data + int ret = c64_snapshot_write_in_memory(saveChips ? 1:0, saveRoms ? 1:0, saveDisks ? 1:0, eventMode ? 1:0, + saveReuData ? 1:0, saveCartRoms ? 1:0, saveScreen ? 1:0, + &snapshotSize, &snapshotData); + +// LOGD("SaveFullSnapshotSynced: saveDisks=%d snapshotData=%x", saveDisks, snapshotData); + + gSoundEngine->UnlockMutex("SaveFullSnapshotSynced"); + debugInterfaceVice->UnlockMutex(); + +// LOGD("CDebugInterfaceVice::SaveFullSnapshotSynced: snapshotData=%x snapshotSize=%d", snapshotData, snapshotSize); + + if (ret == 0) + { + byteBuffer->SetData(snapshotData, snapshotSize); + return true; + } + + if (snapshotData != NULL) + { + lib_free(snapshotData); + } + + LOGError("CDebugInterfaceVice::SaveFullSnapshotSynced: failed"); + return false; +} + +// this sets up drive internals from disk image so it is ready for the c64 basic run +void CDebugInterfaceVice::PrepareDriveForBasicRun() +{ + viewC64->viewDrive1541Browser->UpdateDriveDiskID(); + + +// dataAdapterViceDrive1541->ReadS + + u8 buf[256]; + dataAdapterViceDrive1541DiskContents->ReadSector(D64_BAM_TRACK-1, 0, buf); + + for (int i = 0; i < 256; i++) + { + dataAdapterDrive1541DirectRam->AdapterWriteByte(0x400+i, buf[i]); + dataAdapterDrive1541DirectRam->AdapterWriteByte(0x700+i, buf[i]); + } + +} + +bool CDebugInterfaceVice::IsDriveDirtyForSnapshot() +{ + return c64d_is_drive_dirty_for_snapshot() == 0 ? false : true; +} + +void CDebugInterfaceVice::ClearDriveDirtyForSnapshotFlag() +{ + c64d_clear_drive_dirty_for_snapshot(); +} + +bool CDebugInterfaceVice::IsDriveDirtyForRefresh(int driveNum) +{ + return c64d_is_drive_dirty_and_needs_refresh(driveNum) == 0 ? false : true; +} + +void CDebugInterfaceVice::SetDriveDirtyForRefreshFlag(int driveNum) +{ + c64d_set_drive_dirty_needs_refresh_flag(driveNum); +} + +void CDebugInterfaceVice::ClearDriveDirtyForRefreshFlag(int driveNum) +{ + c64d_clear_drive_dirty_needs_refresh_flag(driveNum); +} + + +// Profiler +extern "C" +{ + extern int c64d_profiler_is_active; + void c64d_profiler_activate(char *fileName, int runForNumCycles, int pauseCpuWhenFinished); + void c64d_profiler_deactivate(); +} + +// if fileName is NULL no file will be created, if runForNumCycles is -1 it will run till ProfilerDeactivate +// TODO: select c64 cpu or disk drive cpu +void CDebugInterfaceVice::ProfilerActivate(char *fileName, int runForNumCycles, bool pauseCpuWhenFinished) +{ + c64d_profiler_activate(fileName, runForNumCycles, pauseCpuWhenFinished ? 1:0); +} + +void CDebugInterfaceVice::ProfilerDeactivate() +{ + c64d_profiler_deactivate(); +} + +bool CDebugInterfaceVice::IsProfilerActive() +{ + return c64d_profiler_is_active == 1 ? true : false; +} + +//void CDebugInterfaceVice::UpdateDriveDiskID(int driveId) +//{ +// if (diskImage[driveId]) +// { +// // set correct disk ID to let 1541 ROM not throw 29, 'disk id mismatch' +// // see $F3F6 in 1541 ROM: http://unusedino.de/ec64/technical/misc/c1541/romlisting.html#FDD3 +// // +// LOGD("...diskId= %02x %02x", diskImage->diskId[2], diskImage[driveId]->diskId[3]); +// +// viewC64->debugInterfaceC64->SetByte1541(0x0012, diskImage[driveId]->diskId[2]); +// viewC64->debugInterfaceC64->SetByte1541(0x0013, diskImage[driveId]->diskId[3]); +// +// viewC64->debugInterfaceC64->SetByte1541(0x0016, diskImage[driveId]->diskId[2]); +// viewC64->debugInterfaceC64->SetByte1541(0x0017, diskImage[driveId]->diskId[3]); +// } +//} + +// code monitor +extern "C" { + void monitor_open(void); + void make_prompt(char *str); + int monitor_process(char *cmd); + void monitor_close(int check); + int mon_buffer_flush(void); +} + +bool CDebugInterfaceVice::IsCodeMonitorSupported() +{ + return true; +} + +CSlrString *CDebugInterfaceVice::GetCodeMonitorPrompt() +{ + if (!isCodeMonitorOpened) + { + monitor_open(); + isCodeMonitorOpened = true; + } + + char *prompt = SYS_GetCharBuf(); + make_prompt(prompt); + + CSlrString *str = new CSlrString(prompt); + + SYS_ReleaseCharBuf(prompt); + + return str; +} + +extern "C" { + char *lib_stralloc(const char *str); +} + +static void execute_monitor_command_trap(WORD addr, void *v) +{ + char *monitorCmdStr = (char*)v; + int exit_mon = monitor_process(monitorCmdStr); + mon_buffer_flush(); + + LOGD("exit_mon=%d", exit_mon); +} + +bool CDebugInterfaceVice::ExecuteCodeMonitorCommand(CSlrString *commandStr) +{ + LOGD("CDebugInterfaceVice::ExecuteCodeMonitorCommand"); + //if (!isCodeMonitorOpened) + { + monitor_open(); + isCodeMonitorOpened = true; + } + + if (commandStr->IsEmpty()) + { + return true; + } + + commandStr->ConvertToLowerCase(); + + char *cmdStr = commandStr->GetStdASCII(); + char *monitorCmdStr = lib_stralloc(cmdStr); + delete [] cmdStr; + +// // we need to move to next instruction on these commands +// if (commandStr->CompareWith("step") || commandStr->CompareWith("next") || commandStr->CompareWith("return")) +// { +// SetDebugMode(DEBUGGER_MODE_RUNNING); +// interrupt_maincpu_trigger_trap(execute_monitor_command_trap, monitorCmdStr); +// } +// else + { + int exit_mon = monitor_process(monitorCmdStr); + mon_buffer_flush(); + LOGD("exit_mon=%d", exit_mon); + } + + return true; +} + +void CDebugInterfaceVice::ScanFolderForRoms(const char *folderPath) +{ + char *buf = SYS_GetCharBuf(); + + bool foundKernal = false; + bool foundBasic = false; + bool foundChargen = false; + bool foundDos1541 = false; + bool foundDos1541ii = false; + + // Filenames moved into constants + + // Define the variables for the strings + const char *KERNAL_ROM_NAME = "kernal"; + const char *BASIC_ROM_NAME = "basic"; + const char *CHARGEN_ROM_NAME = "chargen"; + const char *DOS1541_ROM_NAME = "dos1541"; + const char *DOS1541II_ROM_NAME = "dos1541ii"; + + // kernal + sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, KERNAL_ROM_NAME); + if (SYS_FileExists(buf)) + { + if (c64SettingsPathToRomC64Kernal) + delete c64SettingsPathToRomC64Kernal; + c64SettingsPathToRomC64Kernal = new CSlrString(buf); + foundKernal = true; + } + if (!SYS_FileExists(c64SettingsPathToRomC64Kernal)) + { + delete c64SettingsPathToRomC64Kernal; + c64SettingsPathToRomC64Kernal = NULL; + foundKernal = false; + } + + // basic + sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, BASIC_ROM_NAME); + if (SYS_FileExists(buf)) + { + if (c64SettingsPathToRomC64Basic) + delete c64SettingsPathToRomC64Basic; + c64SettingsPathToRomC64Basic = new CSlrString(buf); + foundBasic = true; + } + if (!SYS_FileExists(c64SettingsPathToRomC64Basic)) + { + delete c64SettingsPathToRomC64Basic; + c64SettingsPathToRomC64Basic = NULL; + foundBasic = false; + } + + // chargen + sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, CHARGEN_ROM_NAME); + if (SYS_FileExists(buf)) + { + if (c64SettingsPathToRomC64Chargen) + delete c64SettingsPathToRomC64Chargen; + c64SettingsPathToRomC64Chargen = new CSlrString(buf); + foundChargen = true; + } + if (!SYS_FileExists(c64SettingsPathToRomC64Chargen)) + { + delete c64SettingsPathToRomC64Chargen; + c64SettingsPathToRomC64Chargen = NULL; + foundChargen = false; + } + + // drive 1541 + sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, DOS1541_ROM_NAME); + if (SYS_FileExists(buf)) + { + if (c64SettingsPathToRomC64Drive1541) + delete c64SettingsPathToRomC64Drive1541; + c64SettingsPathToRomC64Drive1541 = new CSlrString(buf); + foundDos1541 = true; + } + if (!SYS_FileExists(c64SettingsPathToRomC64Drive1541)) + { + delete c64SettingsPathToRomC64Drive1541; + c64SettingsPathToRomC64Drive1541 = NULL; + foundDos1541 = false; + } + + // drive 1541-II + sprintf(buf, "%s%c%s", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR, DOS1541II_ROM_NAME); + if (SYS_FileExists(buf)) + { + if (c64SettingsPathToRomC64Drive1541ii) + delete c64SettingsPathToRomC64Drive1541ii; + c64SettingsPathToRomC64Drive1541ii = new CSlrString(buf); + foundDos1541ii = true; + } + if (!SYS_FileExists(c64SettingsPathToRomC64Drive1541ii)) + { + delete c64SettingsPathToRomC64Drive1541ii; + c64SettingsPathToRomC64Drive1541ii = NULL; + foundDos1541ii = false; + } + + + // Made more user-friendly: show filenames and path + // prepare message box +sprintf(buf, "C64 ROMs Status:\n\n" + "Folder: '%s'\n\n" + "Kernal ROM (File: '%s'): %s\n" + "Basic ROM (File: '%s'): %s\n" + "Chargen ROM (File: '%s'): %s\n" + "Drive 1541 ROM (File: '%s'): %s\n" + "Drive 1541-II ROM (File: '%s'): %s\n\n" + "Please ensure that all required ROM files are in the specified folder.", + folderPath, + KERNAL_ROM_NAME, foundKernal ? "FOUND" : (c64SettingsPathToRomC64Kernal ? "MISSING, using previous version" : "MISSING, no version available"), + BASIC_ROM_NAME, foundBasic ? "FOUND" : (c64SettingsPathToRomC64Basic ? "MISSING, using previous version" : "MISSING, no version available"), + CHARGEN_ROM_NAME, foundChargen ? "FOUND" : (c64SettingsPathToRomC64Chargen ? "MISSING, using previous version" : "MISSING, no version available"), + DOS1541_ROM_NAME, foundDos1541 ? "FOUND" : (c64SettingsPathToRomC64Drive1541 ? "MISSING, using previous version" : "MISSING, no version available"), + DOS1541II_ROM_NAME, foundDos1541ii ? "FOUND" : (c64SettingsPathToRomC64Drive1541ii ? "MISSING, using previous version" : "MISSING, no version available")); + + ShowMessageBox("C64 ROMs folder scan", buf); + + SYS_ReleaseCharBuf(buf); + + UpdateRoms(); + + if (GetDebugMode() == DEBUGGER_MODE_PAUSED + && foundKernal && foundBasic && foundChargen) + { + SetDebugMode(DEBUGGER_MODE_RUNNING); + } +} + +extern "C" { + void c64d_trigger_update_roms(); + + void _c64d_update_roms_trap(WORD addr, void *data) + { + LOGD("_c64d_update_roms_trap"); + debugInterfaceVice->UpdateRomsTrap(); + } + +} + +extern "C" { + int driverom_load_images(void); + extern int rom_loaded; + +} + +void CDebugInterfaceVice::UpdateRomsTrap() +{ + // Note: for some reason resources_set_string("DosName1541", str); or DosName1541ii crashes drive when drive was not initialised before (i.e. in situation that there were no roms at start). Thus we can not set resources_set_string here. As a workaround we are reading roms into embedded space and re-read them as defaults, plus init the drive from scratch + + ReadEmbeddedRoms(); + + this->LockMutex(); + + rom_loaded = 0; + resources_set_defaults(); + drive_init(); + + this->UnlockMutex(); + + HardReset(); + DiskDriveReset(); + SetDebugMode(DEBUGGER_MODE_RUNNING); +} + +void CDebugInterfaceVice::UpdateRoms() +{ + c64d_trigger_update_roms(); +} + +extern "C" { +extern BYTE c64memrom_kernal64_rom[C64_KERNAL_ROM_SIZE]; +extern BYTE c64memrom_basic64_rom[C64_BASIC_ROM_SIZE]; +extern BYTE mem_chargen_rom[C64_CHARGEN_ROM_SIZE]; +extern BYTE drive_rom1541_embedded[DRIVE_ROM1541_SIZE]; +extern BYTE drive_rom1541ii_embedded[DRIVE_ROM1541II_SIZE]; +} + +void CDebugInterfaceVice::DumpRomsToFolder(const char *folderPath) +{ + char *buf = SYS_GetCharBuf(); + + // kernal + sprintf(buf, "%s%ckernal", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR); + CByteBuffer::WriteBufferToFile(buf, c64memrom_kernal64_rom, C64_KERNAL_ROM_SIZE); + + // basic + sprintf(buf, "%s%cbasic", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR); + CByteBuffer::WriteBufferToFile(buf, c64memrom_basic64_rom, C64_BASIC_ROM_SIZE); + + // chargen + sprintf(buf, "%s%cchargen", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR); + CByteBuffer::WriteBufferToFile(buf, mem_chargen_rom, C64_CHARGEN_ROM_SIZE); + + // drive 1541 + sprintf(buf, "%s%cdos1541", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR); + CByteBuffer::WriteBufferToFile(buf, drive_rom1541_embedded, DRIVE_ROM1541_SIZE); + + // drive 1541-II + sprintf(buf, "%s%cdos1541II", folderPath, SYS_FILE_SYSTEM_PATH_SEPARATOR); + CByteBuffer::WriteBufferToFile(buf, drive_rom1541ii_embedded, DRIVE_ROM1541II_SIZE); + + SYS_ReleaseCharBuf(buf); +} + +void CDebugInterfaceVice::ReadEmbeddedRoms() +{ + CByteBuffer::ReadFromFileOrClearBuffer(c64SettingsPathToRomC64Kernal, c64memrom_kernal64_rom, C64_KERNAL_ROM_SIZE); + CByteBuffer::ReadFromFileOrClearBuffer(c64SettingsPathToRomC64Basic, c64memrom_basic64_rom, C64_BASIC_ROM_SIZE); + CByteBuffer::ReadBufferFromFile(c64SettingsPathToRomC64Chargen, mem_chargen_rom, C64_CHARGEN_ROM_SIZE); + CByteBuffer::ReadFromFileOrClearBuffer(c64SettingsPathToRomC64Drive1541, drive_rom1541_embedded, DRIVE_ROM1541_SIZE); + CByteBuffer::ReadFromFileOrClearBuffer(c64SettingsPathToRomC64Drive1541ii, drive_rom1541ii_embedded, DRIVE_ROM1541II_SIZE); +} + +void CDebugInterfaceVice::CheckLoadedRoms() +{ + const char *sep = ""; const char *sep2 = "\n"; + char *buf = SYS_GetCharBuf(); + char *buf2 = SYS_GetCharBuf(); + int n = 0; + + if (!SYS_FileExists(c64SettingsPathToRomC64Kernal)) + { + strcat(buf, "kernal"); sep = sep2; n++; + } + if (!SYS_FileExists(c64SettingsPathToRomC64Basic)) + { + sprintf(buf2, "%sbasic", sep); sep = sep2; n++; + strcat(buf, buf2); + } + if (!SYS_FileExists(c64SettingsPathToRomC64Chargen)) + { + sprintf(buf2, "%schargen", sep); sep = sep2; n++; + strcat(buf, buf2); + } + if (!SYS_FileExists(c64SettingsPathToRomC64Drive1541)) + { + sprintf(buf2, "%sdos1541", sep); sep = sep2; n++; + strcat(buf, buf2); + } + if (!SYS_FileExists(c64SettingsPathToRomC64Drive1541ii)) + { + sprintf(buf2, "%sdos1541II", sep); n++; + strcat(buf, buf2); + } + + if (buf[0] != 0) + { + if (n != 5) + { + sprintf(buf2, "Failed to load C64 ROM files:\n%s", buf); + viewC64->ShowMessageError(buf2); + } + else + { + viewC64->ShowMessageError("C64 ROM files are undefined. Please navigate to Settings and select the appropriate C64 ROMs folder to proceed."); + } + } + + SYS_ReleaseCharBuf(buf); + SYS_ReleaseCharBuf(buf2); + +} + +// +void CDebugInterfaceVice::SupportsBreakpoints(bool *writeBreakpoint, bool *readBreakpoint) +{ + *writeBreakpoint = true; + *readBreakpoint = true; +} + +// SID +CPool CSidData::poolSidData(6000, sizeof(CSidData)); + +CSidData::CSidData() +{ + memset(sidRegs[0], 0x00, C64_NUM_SID_REGISTERS); + memset(sidRegs[1], 0x00, C64_NUM_SID_REGISTERS); + memset(sidRegs[2], 0x00, C64_NUM_SID_REGISTERS); +} + +extern "C" { +void c64d_store_sid_data(BYTE *sidDataStore, int sidNum); +} + +void CSidData::PeekFromSids() +{ + for (int sidNum = 0; sidNum < debugInterfaceVice->numSids; sidNum++) + { + c64d_store_sid_data(sidRegs[sidNum], sidNum); + } +} + +void CSidData::RestoreSids() +{ +// LOGD("CSidData::RestoreSids"); + gSoundEngine->LockMutex("CSidData::RestoreSids"); + c64d_skip_sound_run_sound_in_sound_store = TRUE; + for (int sidNum = 0; sidNum < debugInterfaceVice->numSids; sidNum++) + { + for (int registerNum = 0; registerNum < C64_NUM_SID_REGISTERS; registerNum++) + { + sid_store_chip(registerNum, sidRegs[sidNum][registerNum], sidNum); + } + } + c64d_skip_sound_run_sound_in_sound_store = FALSE; + gSoundEngine->UnlockMutex("CSidData::RestoreSids"); +// LOGD("CSidData::RestoreSids done"); +} + +void CSidData::CopyFrom(CSidData *sidData) +{ + for (int sidNum = 0; sidNum < SOUND_SIDS_MAX; sidNum++) + { + for (int regNum = 0; regNum < C64_NUM_SID_REGISTERS; regNum++) + { + this->sidRegs[sidNum][regNum] = sidData->sidRegs[sidNum][regNum]; + } + } +} + +void CSidData::Serialize(CByteBuffer *byteBuffer) +{ + for (int sidNum = 0; sidNum < SOUND_SIDS_MAX; sidNum++) + { + for (int regNum = 0; regNum < C64_NUM_SID_REGISTERS; regNum++) + { + byteBuffer->PutU8(sidRegs[sidNum][regNum]); + } + } +} + +bool CSidData::Deserialize(CByteBuffer *byteBuffer) +{ + for (int sidNum = 0; sidNum < SOUND_SIDS_MAX; sidNum++) + { + for (int regNum = 0; regNum < C64_NUM_SID_REGISTERS; regNum++) + { + if (byteBuffer->IsEof()) + return false; + + u8 v = byteBuffer->GetU8(); + sidRegs[sidNum][regNum] = v; + } + } + return true; +} + +bool CSidData::SaveRegs(const char *fileName) +{ + FILE *fp = fopen(fileName, "wb"); + if (!fp) + { + return false; + } + + fwrite(sidRegs, 1, SOUND_SIDS_MAX*C64_NUM_SID_REGISTERS, fp); + fclose(fp); + return true; +} + +bool CSidData::LoadRegs(const char *fileName) +{ + FILE *fp = fopen(fileName, "rb"); + if (!fp) + { + return false; + } + fread(sidRegs, 1, SOUND_SIDS_MAX*C64_NUM_SID_REGISTERS, fp); + fclose(fp); + return true; +} + +/// default keymap +void ViceKeyMapInitDefault() +{ + SYS_FatalExit("ViceKeyMapInitDefault"); + + +// C64 keyboard matrix: +// +// Bit 7 6 5 4 3 2 1 0 +// 0 CUD F5 F3 F1 F7 CLR RET DEL +// 1 SHL E S Z 4 A W 3 +// 2 X T F C 6 D R 5 +// 3 V U H B 8 G Y 7 +// 4 N O K M 0 J I 9 +// 5 , @ : . - L P + +// 6 / ^ = SHR HOM ; * £ +// 7 R/S Q C= SPC 2 CTL <- 1 + + // MATRIX (row, column) + + // http://classiccmp.org/dunfield/c64/h/front.jpg + + // keyboard_parse_set_pos_row('a', int row, int col, int shift); + + /* + + keyboard_parse_set_pos_row(MTKEY_F5, 0, 6, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_F6, 0, 6, LEFT_SHIFT); + keyboard_parse_set_pos_row(MTKEY_F3, 0, 5, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_F4, 0, 5, LEFT_SHIFT); + keyboard_parse_set_pos_row(MTKEY_F1, 0, 4, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_F2, 0, 4, LEFT_SHIFT); + keyboard_parse_set_pos_row(MTKEY_F7, 0, 3, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_F8, 0, 3, LEFT_SHIFT); + + keyboard_parse_set_pos_row(MTKEY_ENTER, 0, 1, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_BACKSPACE, 0, 0, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_LSHIFT, 1, 7, NO_SHIFT); + keyboard_parse_set_pos_row('e', 1, 6, NO_SHIFT); + keyboard_parse_set_pos_row('s', 1, 5, NO_SHIFT); + keyboard_parse_set_pos_row('z', 1, 4, NO_SHIFT); + keyboard_parse_set_pos_row('4', 1, 3, NO_SHIFT); + keyboard_parse_set_pos_row('a', 1, 2, NO_SHIFT); + keyboard_parse_set_pos_row('w', 1, 1, NO_SHIFT); + keyboard_parse_set_pos_row('3', 1, 0, NO_SHIFT); + keyboard_parse_set_pos_row('x', 2, 7, NO_SHIFT); + keyboard_parse_set_pos_row('t', 2, 6, NO_SHIFT); + keyboard_parse_set_pos_row('f', 2, 5, NO_SHIFT); + keyboard_parse_set_pos_row('c', 2, 4, NO_SHIFT); + keyboard_parse_set_pos_row('6', 2, 3, NO_SHIFT); + keyboard_parse_set_pos_row('d', 2, 2, NO_SHIFT); + keyboard_parse_set_pos_row('r', 2, 1, NO_SHIFT); + keyboard_parse_set_pos_row('5', 2, 0, NO_SHIFT); + keyboard_parse_set_pos_row('v', 3, 7, NO_SHIFT); + keyboard_parse_set_pos_row('u', 3, 6, NO_SHIFT); + keyboard_parse_set_pos_row('h', 3, 5, NO_SHIFT); + keyboard_parse_set_pos_row('b', 3, 4, NO_SHIFT); + keyboard_parse_set_pos_row('8', 3, 3, NO_SHIFT); + keyboard_parse_set_pos_row('g', 3, 2, NO_SHIFT); + keyboard_parse_set_pos_row('y', 3, 1, NO_SHIFT); + keyboard_parse_set_pos_row('7', 3, 0, NO_SHIFT); + keyboard_parse_set_pos_row('n', 4, 7, NO_SHIFT); + keyboard_parse_set_pos_row('o', 4, 6, NO_SHIFT); + keyboard_parse_set_pos_row('k', 4, 5, NO_SHIFT); + keyboard_parse_set_pos_row('m', 4, 4, NO_SHIFT); + keyboard_parse_set_pos_row('0', 4, 3, NO_SHIFT); + keyboard_parse_set_pos_row('j', 4, 2, NO_SHIFT); + keyboard_parse_set_pos_row('i', 4, 1, NO_SHIFT); + keyboard_parse_set_pos_row('9', 4, 0, NO_SHIFT); + keyboard_parse_set_pos_row(',', 5, 7, NO_SHIFT); + keyboard_parse_set_pos_row('[', 5, 6, NO_SHIFT); + keyboard_parse_set_pos_row(';', 5, 5, NO_SHIFT); + keyboard_parse_set_pos_row('.', 5, 4, NO_SHIFT); + keyboard_parse_set_pos_row('-', 5, 3, NO_SHIFT); + keyboard_parse_set_pos_row('l', 5, 2, NO_SHIFT); + keyboard_parse_set_pos_row('p', 5, 1, NO_SHIFT); + keyboard_parse_set_pos_row('=', 5, 0, NO_SHIFT); + keyboard_parse_set_pos_row('/', 6, 7, NO_SHIFT); + // keyboard_parse_set_pos_row('^', 6, 6, NO_SHIFT); + // keyboard_parse_set_pos_row('@', 6, 5, DESHIFT_SHIFT); + keyboard_parse_set_pos_row(MTKEY_RSHIFT, 6, 4, NO_SHIFT); + // keyboard_parse_set_pos_row('', 6, 3, NO_SHIFT); + keyboard_parse_set_pos_row('\'', 6, 2, NO_SHIFT); + keyboard_parse_set_pos_row(']', 6, 1, NO_SHIFT); + // keyboard_parse_set_pos_row('', 6, 0, NO_SHIFT); + + keyboard_parse_set_pos_row('`', 7, 7, NO_SHIFT); + keyboard_parse_set_pos_row('q', 7, 6, NO_SHIFT); + // keyboard_parse_set_pos_row('', 7, 5, NO_SHIFT); + keyboard_parse_set_pos_row(' ', 7, 4, NO_SHIFT); + keyboard_parse_set_pos_row('2', 7, 3, NO_SHIFT); + keyboard_parse_set_pos_row('@', 7, 3, LEFT_SHIFT); + keyboard_parse_set_pos_row(MTKEY_LCONTROL, 7, 2, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_LALT, 7, 5, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_ESC, 7, 1, NO_SHIFT); + keyboard_parse_set_pos_row('1', 7, 0, NO_SHIFT); + + keyboard_parse_set_pos_row(MTKEY_ARROW_UP, 0, 7, LEFT_SHIFT); + keyboard_parse_set_pos_row(MTKEY_ARROW_DOWN, 0, 7, NO_SHIFT); + keyboard_parse_set_pos_row(MTKEY_ARROW_LEFT, 0, 2, LEFT_SHIFT); + keyboard_parse_set_pos_row(MTKEY_ARROW_RIGHT, 0, 2, NO_SHIFT); + + */ + + +// C64 keyboard matrix: +// +// Bit 7 6 5 4 3 2 1 0 +// 0 CUD F5 F3 F1 F7 CLR RET DEL +// 1 SHL E S Z 4 A W 3 +// 2 X T F C 6 D R 5 +// 3 V U H B 8 G Y 7 +// 4 N O K M 0 J I 9 +// 5 , @ : . - L P + +// 6 / ^ = SHR HOM ; * £ +// 7 R/S Q C= SPC 2 CTL <- 1 + +} + diff --git a/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.h b/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.h index b89cb9f..5a04314 100644 --- a/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.h +++ b/src/Emulators/vice/ViceInterface/CDebugInterfaceVice.h @@ -100,8 +100,8 @@ class CDebugInterfaceVice : public CDebugInterfaceC64 virtual void ClearDebugMarkers(); - virtual void Reset(); - virtual void HardReset(); + virtual void ResetSoft(); + virtual void ResetHard(); virtual void DiskDriveReset(); // this is main emulation cpu cycle counter @@ -124,6 +124,15 @@ class CDebugInterfaceVice : public CDebugInterfaceC64 virtual void JoystickDown(int port, uint32 axis); virtual void JoystickUp(int port, uint32 axis); + virtual void EmulatedMouseUpdateSettings(); + virtual bool EmulatedMouseEnable(bool enable); + virtual void EmulatedMouseSetType(int mouseType); + virtual void EmulatedMouseSetPort(int port); + virtual void EmulatedMouseSetPosition(int x, int y); + virtual void EmulatedMouseButtonLeft(bool isPressed); + virtual void EmulatedMouseButtonMiddle(bool isPressed); + virtual void EmulatedMouseButtonRight(bool isPressed); + // virtual int GetCpuPC(); virtual int GetDrive1541PC(); @@ -356,6 +365,10 @@ class CDebugInterfaceVice : public CDebugInterfaceC64 // virtual void SupportsBreakpoints(bool *writeBreakpoint, bool *readBreakpoint); + // + virtual CDebuggerApi *GetDebuggerApi(); + virtual CDebuggerServerApi *GetDebuggerServerApi(); + // virtual void Shutdown(); }; @@ -372,6 +385,9 @@ class CSidData void CopyFrom(CSidData *sidData); u8 sidRegs[SOUND_SIDS_MAX][C64_NUM_SID_REGISTERS]; + // shall we copy that sid register to SID + bool shouldSetSidReg[SOUND_SIDS_MAX][C64_NUM_SID_REGISTERS]; + void Serialize(CByteBuffer *byteBuffer); bool Deserialize(CByteBuffer *byteBuffer); bool SaveRegs(const char *fileName); diff --git a/src/Emulators/vice/ViceInterface/CDebuggerApiVice.cpp b/src/Emulators/vice/ViceInterface/CDebuggerApiVice.cpp index f8b3307..4d8be8e 100644 --- a/src/Emulators/vice/ViceInterface/CDebuggerApiVice.cpp +++ b/src/Emulators/vice/ViceInterface/CDebuggerApiVice.cpp @@ -1,4 +1,5 @@ #include "CDebuggerApiVice.h" +#include "CDebugInterfaceVice.h" #include "CViewC64.h" #include "CViewMonitorConsole.h" #include "CViewC64VicEditor.h" @@ -20,7 +21,7 @@ #include "CViewDataMap.h" #include "CDebugAsmSource.h" #include "CDebugSymbols.h" -#include "CDebugSymbolsSegment.h" +#include "CDebugSymbolsSegmentC64.h" #include "CViewDataWatch.h" #include "CGuiMain.h" #include "CSlrFont.h" @@ -29,6 +30,7 @@ CDebuggerApiVice::CDebuggerApiVice(CDebugInterface *debugInterface) : CDebuggerApi(debugInterface) { assembleTarget = ASSEMBLE_TARGET_MAIN_CPU; + debugInterfaceVice = (CDebugInterfaceVice *)debugInterface; } void CDebuggerApiVice::SwitchToVicEditor() @@ -188,14 +190,19 @@ long CDebuggerApiVice::GetCurrentTimeInMilliseconds() return SYS_GetCurrentTimeInMillis(); } -void CDebuggerApiVice::ResetMachine() +void CDebuggerApiVice::MakeJmp(int addr) { - viewC64->debugInterfaceC64->HardReset(); + debugInterfaceVice->MakeJmpC64(addr); } -void CDebuggerApiVice::MakeJmp(int addr) +CDataAdapter *CDebuggerApiVice::GetDataAdapterDrive1541MemoryWithIO() +{ + return debugInterfaceVice->dataAdapterDrive1541; +} + +CDataAdapter *CDebuggerApiVice::GetDataAdapterDrive1541MemoryDirectRAM() { - viewC64->debugInterfaceC64->MakeJmpC64(addr); + return debugInterfaceVice->dataAdapterDrive1541DirectRam; } void CDebuggerApiVice::SetByte(int addr, u8 v) @@ -205,18 +212,18 @@ void CDebuggerApiVice::SetByte(int addr, u8 v) void CDebuggerApiVice::SetByteWithIo(int addr, u8 v) { - viewC64->debugInterfaceC64->SetByteC64(addr, v); + debugInterfaceVice->SetByteC64(addr, v); } void CDebuggerApiVice::SetByteToRam(int addr, u8 v) { // LOGD("CDebuggerApiVice::SetByteToRam: %04x %02x", addr, v); - viewC64->debugInterfaceC64->SetByteToRamC64(addr, v); + debugInterfaceVice->SetByteToRamC64(addr, v); } u8 CDebuggerApiVice::GetByteWithIo(int addr) { - return viewC64->debugInterfaceC64->GetByteC64(addr); + return debugInterfaceVice->GetByteC64(addr); } u8 CDebuggerApiVice::GetByteFromRam(int addr) @@ -226,12 +233,12 @@ u8 CDebuggerApiVice::GetByteFromRam(int addr) void CDebuggerApiVice::SetByteToRamC64(int addr, u8 v) { - viewC64->debugInterfaceC64->SetByteToRamC64(addr, v); + debugInterfaceVice->SetByteToRamC64(addr, v); } u8 CDebuggerApiVice::GetByteFromRamC64(int addr) { - return viewC64->debugInterfaceC64->GetByteFromRamC64(addr); + return debugInterfaceVice->GetByteFromRamC64(addr); } void CDebuggerApiVice::DetachEverything() @@ -287,65 +294,6 @@ int CDebuggerApiVice::Assemble(int addr, char *assembleText) return -1; } -void CDebuggerApiVice::AddWatch(CSlrString *segmentName, int address, CSlrString *watchName, uint8 representation, int numberOfValues) -{ - if (debugInterface->symbols) - { - CDebugSymbolsSegment *segment = debugInterface->symbols->FindSegment(segmentName); - if (segment == NULL) - { - segmentName->DebugPrint("segment="); - LOGError("CDebuggerApiVice::AddWatch: segment not found"); - return; - } - - // TODO: convert watch name in symbols to CSlrString - char *cWatchName = watchName->GetStdASCII(); - segment->AddWatch(address, cWatchName, representation, numberOfValues); - delete [] cWatchName; - } - else - { - LOGError("CDebuggerApiVice::AddWatch: no symbols"); - } -} - -void CDebuggerApiVice::AddWatch(int address, char *watchName, uint8 representation, int numberOfValues) -{ - // TODO: Generalize me - CDebugInterface *debugInterface = NULL; - if (viewC64->debugInterfaceC64) - { - debugInterface = viewC64->debugInterfaceC64; - } - else if (viewC64->debugInterfaceAtari) - { - debugInterface = viewC64->debugInterfaceAtari; - } - - - if (debugInterface->symbols) - { - CDebugSymbolsSegment *segment = debugInterface->symbols->currentSegment; - if (segment == NULL) - { - LOGError("CDebuggerApiVice::AddWatch: default segment not found"); - return; - } - - segment->AddWatch(address, watchName, representation, numberOfValues); - } - else - { - LOGError("CDebuggerApiVice::AddWatch: no symbols"); - } -} - -void CDebuggerApiVice::AddWatch(int address, char *watchName) -{ - this->AddWatch(address, watchName, WATCH_REPRESENTATION_HEX_8, 1); -} - bool CDebuggerApiVice::LoadPRG(const char *filePath) { u16 fromAddr, toAddr; @@ -359,7 +307,7 @@ bool CDebuggerApiVice::LoadPRG(const char *filePath, u16 *fromAddr, u16 *toAddr) { CByteBuffer *byteBuffer = new CByteBuffer(file, false); - viewC64->viewC64MainMenu->LoadPRG(byteBuffer, fromAddr, toAddr); + viewC64->mainMenuHelper->LoadPRG(byteBuffer, fromAddr, toAddr); delete byteBuffer; delete file; @@ -372,13 +320,13 @@ bool CDebuggerApiVice::LoadPRG(const char *filePath, u16 *fromAddr, u16 *toAddr) bool CDebuggerApiVice::LoadPRG(CByteBuffer *byteBuffer, u16 *fromAddr, u16 *toAddr) { - viewC64->viewC64MainMenu->LoadPRG(byteBuffer, fromAddr, toAddr); + viewC64->mainMenuHelper->LoadPRG(byteBuffer, fromAddr, toAddr); return true; } bool CDebuggerApiVice::LoadPRG(CByteBuffer *byteBuffer, bool autoStart, bool forceFastReset) { - return viewC64->viewC64MainMenu->LoadPRG(byteBuffer, autoStart, false, forceFastReset); + return viewC64->mainMenuHelper->LoadPRG(byteBuffer, autoStart, false, forceFastReset); } bool CDebuggerApiVice::LoadCRT(CByteBuffer *byteBuffer) @@ -392,7 +340,7 @@ bool CDebuggerApiVice::LoadCRT(CByteBuffer *byteBuffer) filePath->DebugPrint(); - bool ret = viewC64->viewC64MainMenu->InsertCartridge(filePath, false); + bool ret = viewC64->mainMenuHelper->InsertCartridge(filePath, false); delete filePath; @@ -402,7 +350,7 @@ bool CDebuggerApiVice::LoadCRT(CByteBuffer *byteBuffer) bool CDebuggerApiVice::LoadCRT(const char *filePath) { CSlrString *path = new CSlrString(filePath); - bool ret = viewC64->viewC64MainMenu->InsertCartridge(path, false); + bool ret = viewC64->mainMenuHelper->InsertCartridge(path, false); delete path; return ret; } @@ -433,10 +381,10 @@ bool CDebuggerApiVice::LoadKLA(const char *filePath, u16 bitmapAddress, u16 scre return ret; } -void CDebuggerApiVice::SaveExomizerPRG(u16 fromAddr, u16 toAddr, u16 jmpAddr, const char *filePath) +bool CDebuggerApiVice::SaveExomizerPRG(u16 fromAddr, u16 toAddr, u16 jmpAddr, const char *filePath) { LOGM("SaveExomizerPRG: fromAddr=%04x toAddr=%04x jmpAddr=%04x filePath='%s'", fromAddr, toAddr, jmpAddr, filePath); - C64SaveMemoryExomizerPRG(fromAddr, toAddr, jmpAddr, filePath); + return C64SaveMemoryExomizerPRG(fromAddr, toAddr, jmpAddr, filePath); } u8 *CDebuggerApiVice::ExomizerMemoryRaw(u16 fromAddr, u16 toAddr, int *compressedSize) @@ -444,22 +392,10 @@ u8 *CDebuggerApiVice::ExomizerMemoryRaw(u16 fromAddr, u16 toAddr, int *compresse return C64ExomizeMemoryRaw(fromAddr, toAddr, compressedSize); } - - -void CDebuggerApiVice::SavePRG(u16 fromAddr, u16 toAddr, const char *filePath) +bool CDebuggerApiVice::SavePRG(u16 fromAddr, u16 toAddr, const char *filePath) { LOGM("SavePRG: fromAddr=%04x toAddr=%04x filePath='%s'", fromAddr, toAddr, filePath); - C64SaveMemory(fromAddr, toAddr, true, viewC64->debugInterfaceC64->dataAdapterC64DirectRam, filePath); -} - -void CDebuggerApiVice::SaveBinary(u16 fromAddr, u16 toAddr, const char *filePath) -{ - C64SaveMemory(fromAddr, toAddr, false, viewC64->debugInterfaceC64->dataAdapterC64DirectRam, filePath); -} - -int CDebuggerApiVice::LoadBinary(u16 fromAddr, const char *filePath) -{ - return C64LoadMemory(fromAddr, viewC64->debugInterfaceC64->dataAdapterC64DirectRam, filePath); + return C64SaveMemory(fromAddr, toAddr, true, debugInterfaceVice->dataAdapterC64DirectRam, filePath); } void CDebuggerApiVice::BasicUpStart(u16 jmpAddr) @@ -468,19 +404,19 @@ void CDebuggerApiVice::BasicUpStart(u16 jmpAddr) char buf[16]; sprintf(buf, "%d", jmpAddr); - viewC64->debugInterfaceC64->SetByteToRamC64(0x0801, 0x0D); - viewC64->debugInterfaceC64->SetByteToRamC64(0x0802, 0x08); - viewC64->debugInterfaceC64->SetByteToRamC64(0x0803, (u8) (lineNumber & 0xff)); - viewC64->debugInterfaceC64->SetByteToRamC64(0x0804, (u8) (lineNumber >> 8)); - viewC64->debugInterfaceC64->SetByteToRamC64(0x0805, 0x9E); - viewC64->debugInterfaceC64->SetByteToRamC64(0x0806, 0x20); + debugInterfaceVice->SetByteToRamC64(0x0801, 0x0D); + debugInterfaceVice->SetByteToRamC64(0x0802, 0x08); + debugInterfaceVice->SetByteToRamC64(0x0803, (u8) (lineNumber & 0xff)); + debugInterfaceVice->SetByteToRamC64(0x0804, (u8) (lineNumber >> 8)); + debugInterfaceVice->SetByteToRamC64(0x0805, 0x9E); + debugInterfaceVice->SetByteToRamC64(0x0806, 0x20); int a = 0x0807; for (int i = 0; i < strlen(buf); i++) { - viewC64->debugInterfaceC64->SetByteToRamC64(a++, buf[i]); + debugInterfaceVice->SetByteToRamC64(a++, buf[i]); } - viewC64->debugInterfaceC64->SetByteToRamC64(a++, 0x00); + debugInterfaceVice->SetByteToRamC64(a++, 0x00); } void CDebuggerApiVice::AddCrtEntryPoint(u8 *cartImage, u16 coldStartAddr, u16 warmStartAddr) @@ -574,13 +510,39 @@ CByteBuffer *CDebuggerApiVice::MakeCrt(const char *cartName, int cartSize, int b void CDebuggerApiVice::SetCiaRegister(u8 ciaId, u8 registerNum, u8 value) { - viewC64->debugInterfaceC64->SetCiaRegister(ciaId, registerNum, value); + debugInterfaceVice->SetCiaRegister(ciaId, registerNum, value); +} + +u8 CDebuggerApiVice::GetCiaRegister(u8 ciaId, u8 registerNum) +{ + return debugInterfaceVice->GetCiaRegister(ciaId, registerNum); +} + +void CDebuggerApiVice::SetSid(CSidData *sidData) +{ + debugInterfaceVice->SetSid(sidData); +} + +void CDebuggerApiVice::SetSidRegister(uint8 sidId, uint8 registerNum, uint8 value) +{ + debugInterfaceVice->SetSidRegister(sidId, registerNum, value); +} + +u8 CDebuggerApiVice::GetSidRegister(uint8 sidId, uint8 registerNum) +{ + return debugInterfaceVice->GetSidRegister(sidId, registerNum); } void CDebuggerApiVice::SetVicRegister(u16 registerNum, u8 value) { u8 reg = registerNum & 0x00FF; - viewC64->debugInterfaceC64->SetVicRegister(reg, value); + debugInterfaceVice->SetVicRegister(reg, value); +} + +u8 CDebuggerApiVice::GetVicRegister(u16 registerNum) +{ + u8 reg = registerNum & 0x00FF; + return debugInterfaceVice->GetVicRegister(reg); } void CDebuggerApiVice::SetScreenAndCharsetAddress(u16 screenAddr, u16 charsetAddr) @@ -614,7 +576,35 @@ void CDebuggerApiVice::SetScreenAndCharsetAddress(u16 screenAddr, u16 charsetAdd void CDebuggerApiVice::GetCBMColor(u8 colorNum, u8 *r, u8 *g, u8 *b) { - return viewC64->debugInterfaceC64->GetCBMColor(colorNum, r, g, b); + return debugInterfaceVice->GetCBMColor(colorNum, r, g, b); +} + +void CDebuggerApiVice::SetDrive1541ViaRegister(u8 driveId, u8 viaId, u8 registerNum, u8 value) +{ + debugInterfaceVice->SetViaRegister(driveId, viaId, registerNum, value); +} + +u8 CDebuggerApiVice::GetDrive1541ViaRegister(u8 driveId, u8 viaId, u8 registerNum) +{ + return debugInterfaceVice->GetViaRegister(driveId, viaId, registerNum); +} + +u64 CDebuggerApiVice::AddBreakpointRasterLine(int rasterLine) +{ + debugInterfaceVice->LockMutex(); + CDebugSymbolsSegmentC64 *segment = (CDebugSymbolsSegmentC64*)debugInterfaceVice->symbols->currentSegment; + CDebugBreakpointRasterLine *breakpoint = segment->AddBreakpointRaster(rasterLine); + debugInterfaceVice->UnlockMutex(); + return breakpoint->breakpointId; +} + +u64 CDebuggerApiVice::RemoveBreakpointRasterLine(int rasterLine) +{ + debugInterfaceVice->LockMutex(); + CDebugSymbolsSegmentC64 *segment = (CDebugSymbolsSegmentC64*)debugInterfaceVice->symbols->currentSegment; + u64 breakpointId = segment->RemoveBreakpointRaster(rasterLine); + debugInterfaceVice->UnlockMutex(); + return breakpointId; } void CDebuggerApiVice::ShowMessage(const char *text) @@ -636,3 +626,22 @@ void CDebuggerApiVice::AddView(CGuiView *view) guiMain->UnlockMutex(); } +nlohmann::json CDebuggerApiVice::GetCpuStatusJson() +{ + nlohmann::json cpuStatus; + cpuStatus["pc"] = viewC64->viciiStateToShow.pc; + cpuStatus["a"] = viewC64->viciiStateToShow.a; + cpuStatus["x"] = viewC64->viciiStateToShow.x; + cpuStatus["y"] = viewC64->viciiStateToShow.y; + cpuStatus["sp"] = viewC64->viciiStateToShow.sp; + cpuStatus["p"] = viewC64->viciiStateToShow.processorFlags; + cpuStatus["memory0001"] = viewC64->viciiStateToShow.memory0001; + cpuStatus["instructionCycle"] = viewC64->viciiStateToShow.instructionCycle; + cpuStatus["rasterCycle"] = viewC64->viciiStateToShow.raster_cycle; + cpuStatus["rasterX"] = viewC64->c64RasterPosToShowX; + cpuStatus["rasterY"] = viewC64->c64RasterPosToShowY; + cpuStatus["exrom"] = viewC64->viciiStateToShow.exrom; + cpuStatus["game"] = viewC64->viciiStateToShow.game; + return cpuStatus; +} + diff --git a/src/Emulators/vice/ViceInterface/CDebuggerApiVice.h b/src/Emulators/vice/ViceInterface/CDebuggerApiVice.h index 66b8080..de38fb6 100644 --- a/src/Emulators/vice/ViceInterface/CDebuggerApiVice.h +++ b/src/Emulators/vice/ViceInterface/CDebuggerApiVice.h @@ -18,6 +18,7 @@ enum { class CGuiView; class CDebugInterface; class CDebugInterfaceVice; +class CSidData; class CDebuggerApiVice : public CDebuggerApi { @@ -25,18 +26,16 @@ class CDebuggerApiVice : public CDebuggerApi CDebuggerApiVice(CDebugInterface *debugInterface); CDebugInterfaceVice *debugInterfaceVice; - void ResetMachine(); - void SwitchToVicEditor(); void CreateNewPicture(u8 mode, u8 backgroundColor); - + // rgb reference image in vic editor void ClearReferenceImage(); void LoadReferenceImage(char *filePath); void LoadReferenceImage(CImageData *imageData); void SetReferenceImageLayerVisible(bool isVisible); CImageData *GetReferenceImage(); - + // vic editor dialogs -> to be moved void SetTopBarVisible(bool isVisible); void SetViewPaletteVisible(bool isVisible); @@ -63,7 +62,7 @@ class CDebuggerApiVice : public CDebuggerApi // always returns 320x200 for C64: CImageData *GetScreenImageWithoutBorders(); - + // u8 FindC64Color(u8 r, u8 g, u8 b); u8 PaintPixel(int x, int y, u8 color); @@ -73,6 +72,10 @@ class CDebuggerApiVice : public CDebuggerApi // void GetCBMColor(u8 colorNum, u8 *r, u8 *g, u8 *b); + // + CDataAdapter *GetDataAdapterDrive1541MemoryWithIO(); + CDataAdapter *GetDataAdapterDrive1541MemoryDirectRAM(); + // void SetByte(int addr, u8 v); /// NOTE: this needs change void SetByteWithIo(int addr, u8 v); @@ -82,13 +85,31 @@ class CDebuggerApiVice : public CDebuggerApi virtual u8 GetByteWithIo(int addr); virtual u8 GetByteFromRam(int addr); - + void MakeJmp(int addr); - - // + + // CIA void SetCiaRegister(u8 ciaId, u8 registerNum, u8 value); + u8 GetCiaRegister(u8 ciaId, u8 registerNum); + + // SIDs + // write multiple registers to SIDs at once. Note, the CSidData is _not_deleted_ after use + void SetSid(CSidData *sidData); + + // note SetSidRegister writes only _one_ register in next emulation cycle via trap, previous not-executed writes will be skipped (overwritten). + // if you need to write to multiple registers then use CSidData instead. + // TODO: we can add a mechanism to collect SidRegister writes here and use CSidData instead, TBD + void SetSidRegister(uint8 sidId, uint8 registerNum, uint8 value); + u8 GetSidRegister(uint8 sidId, uint8 registerNum); + + // VIC void SetVicRegister(u16 registerNum, u8 value); + u8 GetVicRegister(u16 registerNum); + // Drive1541 VIA + void SetDrive1541ViaRegister(u8 driveId, u8 viaId, u8 registerNum, u8 value); + u8 GetDrive1541ViaRegister(u8 driveId, u8 viaId, u8 registerNum); + // void DetachEverything(); void ClearRam(int startAddr, int endAddr, u8 value); @@ -97,11 +118,6 @@ class CDebuggerApiVice : public CDebuggerApi u8 assembleTarget; void SetAssembleTarget(u8 target); int Assemble(int addr, char *assembleText); - - // - void AddWatch(CSlrString *segmentName, int address, CSlrString *watchName, uint8 representation, int numberOfValues); - void AddWatch(int address, char *watchName, uint8 representation, int numberOfValues); - void AddWatch(int address, char *watchName); // void BasicUpStart(u16 jmpAddr); @@ -113,21 +129,23 @@ class CDebuggerApiVice : public CDebuggerApi bool LoadCRT(const char *filePath); bool LoadSID(const char *filePath, u16 *fromAddr, u16 *toAddr, u16 *initAddr, u16 *playAddr); bool LoadSID(const char *filePath, u16 *fromAddr, u16 *toAddr, u16 *initAddr, u16 *playAddr, u8 **buffer); -// bool LoadAndRelocateSID(char *filePath, u16 fromAddr, u16 *toAddr, u16 *initAddr, u16 *playAddr); + // bool LoadAndRelocateSID(char *filePath, u16 fromAddr, u16 *toAddr, u16 *initAddr, u16 *playAddr); bool LoadKLA(const char *filePath); bool LoadKLA(const char *filePath, u16 bitmapAddress, u16 screenAddress, u16 colorRamAddress, u8 *colorD020, u8 *colorD021); - void SaveExomizerPRG(u16 fromAddr, u16 toAddr, u16 jmpAddr, const char *fileName); - void SavePRG(u16 fromAddr, u16 toAddr, const char *fileName); + bool SaveExomizerPRG(u16 fromAddr, u16 toAddr, u16 jmpAddr, const char *fileName); + bool SavePRG(u16 fromAddr, u16 toAddr, const char *fileName); void AddCrtEntryPoint(u8 *cartImage, u16 coldStartAddr, u16 warmStartAddr); CByteBuffer *MakeCrt(const char *cartName, int cartSize, int bankSize, u8 *cartImage); - void SaveBinary(u16 fromAddr, u16 toAddr, const char *fileName); - int LoadBinary(u16 fromAddr, const char *filePath); - + u8 *ExomizerMemoryRaw(u16 fromAddr, u16 toAddr, int *compressedSize); // void SetScreenAndCharsetAddress(u16 screenAddr, u16 charsetAddr); + // breakpoints + u64 AddBreakpointRasterLine(int rasterLine); + u64 RemoveBreakpointRasterLine(int rasterLine); + // void ShowMessage(const char *text); void BlitText(const char *text, float posX, float posY, float fontSize); @@ -136,6 +154,10 @@ class CDebuggerApiVice : public CDebuggerApi // void AddView(CGuiView *view); + + // + virtual nlohmann::json GetCpuStatusJson(); + }; #endif diff --git a/src/Emulators/vice/ViceInterface/CDebuggerServerApiVice.cpp b/src/Emulators/vice/ViceInterface/CDebuggerServerApiVice.cpp new file mode 100644 index 0000000..52fecc0 --- /dev/null +++ b/src/Emulators/vice/ViceInterface/CDebuggerServerApiVice.cpp @@ -0,0 +1,551 @@ +#include "CDebuggerServerApiVice.h" +#include "CDebugInterfaceVice.h" +#include "CDebuggerApiVice.h" +#include "CDebuggerServer.h" + +using namespace std; +using namespace nlohmann; + +CDebuggerServerApiVice::CDebuggerServerApiVice(CDebugInterface *debugInterface) +: CDebuggerServerApi(debugInterface) +{ + this->debugInterfaceVice = (CDebugInterfaceVice *)debugInterface; + this->debuggerApiVice = (CDebuggerApiVice *)debugInterface->GetDebuggerApi(); + this->sidData = new CSidData(); +} + +void CDebuggerServerApiVice::RegisterEndpoints(CDebuggerServer *server) +{ + CDebuggerServerApi::RegisterEndpoints(server); + + char *buf = SYS_GetCharBuf(); + + // save PRG + sprintf(buf, "%s/savePrg", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + + string fileName = params.at("path").get(); + u16 fromAddr = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("fromAddr")); + u16 toAddr = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("toAddr")); + bool exomize = false; + if (params.contains("exomize")) + { + exomize = params.at("exomize").get(); + } + + bool ret; + if (exomize) + { + u16 jmpAddr = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("jmpAddr")); + ret = debuggerApiVice->SaveExomizerPRG(fromAddr, toAddr, jmpAddr, fileName.c_str()); + } + else + { + ret = debuggerApiVice->SavePRG(fromAddr, toAddr, fileName.c_str()); + } + + debugInterfaceVice->UnlockMutex(); + if (ret) + { + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + } + return server->PrepareResult(HTTP_FORBIDDEN, token, json(), NULL, 0); + }); + + // VIC + sprintf(buf, "%s/vic/write", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + for (auto& [key, value] : params["registers"].items()) + { + u64 registerNum = FUN_DecOrHexStrWithPrefixToU64(key.c_str()); + if (registerNum >= 0xD000 && registerNum < 0xD040) + { + registerNum -= 0xD000; + } + if (registerNum > 0x3F) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + u64 registerValue = FUN_JsonValueDecOrHexStrWithPrefixToU64(value); + debuggerApiVice->SetVicRegister(registerNum, registerValue); + } + debugInterfaceVice->UnlockMutex(); + + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/vic/read", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + + std::unordered_map registers; + for (const auto& reg : params["registers"]) + { + u64 registerNum = FUN_JsonValueDecOrHexStrWithPrefixToU64(reg); + if (registerNum >= 0xD000 && registerNum < 0xD040) + { + registerNum -= 0xD000; + } + if (registerNum > 0x3F) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + + u8 registerValue = debugInterfaceVice->GetVicRegister(registerNum); + registers[registerNum] = registerValue; + } + + json j; + j["registers"] = registers; + + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + }); + + sprintf(buf, "%s/vic/breakpoint/add", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + u64 rasterLine = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("rasterLine")); + json j; + + u64 breakpointId = debuggerApiVice->AddBreakpointRasterLine((int)rasterLine); + if (breakpointId != UNKNOWN_BREAKPOINT_ID) + { + j["breakpointId"] = breakpointId; + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + } + + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, j, NULL, 0); + }); + + sprintf(buf, "%s/vic/breakpoint/remove", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + u64 rasterLine = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("rasterLine")); + json j; + + u64 breakpointId = debuggerApiVice->RemoveBreakpointRasterLine((int)rasterLine); + if (breakpointId != UNKNOWN_BREAKPOINT_ID) + { + j["breakpointId"] = breakpointId; + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + } + + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, j, NULL, 0); + }); + + // CIA + sprintf(buf, "%s/cia/write", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + + int selectedCiaNum = 0; + if (params.contains("num")) + { + selectedCiaNum = params.at("num").get(); + if (selectedCiaNum < 0 || selectedCiaNum > 1) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + } + + for (auto& [key, value] : params["registers"].items()) + { + int ciaNum = selectedCiaNum; + u64 registerNum = FUN_DecOrHexStrWithPrefixToU64(key.c_str()); + if (registerNum >= 0xDC00 && registerNum < 0xDC10) + { + registerNum -= 0xDC00; + ciaNum = 0; + } + if (registerNum >= 0xDD00 && registerNum < 0xDD10) + { + registerNum -= 0xDD00; + ciaNum = 1; + } + if (registerNum > 0x0F) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + u64 registerValue = FUN_JsonValueDecOrHexStrWithPrefixToU64(value); + debuggerApiVice->SetCiaRegister(ciaNum, registerNum, registerValue); + } + debugInterfaceVice->UnlockMutex(); + + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/cia/read", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + + int selectedCiaNum = 0; + if (params.contains("num")) + { + selectedCiaNum = params.at("num").get(); + if (selectedCiaNum < 0 || selectedCiaNum > 1) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + } + + std::unordered_map registers; + for (const auto& reg : params["registers"]) + { + int ciaNum = selectedCiaNum; + u64 registerNum = FUN_JsonValueDecOrHexStrWithPrefixToU64(reg); + if (registerNum >= 0xDC00 && registerNum < 0xDC10) + { + registerNum -= 0xDC00; + ciaNum = 0; + } + if (registerNum >= 0xDD00 && registerNum < 0xDD10) + { + registerNum -= 0xDD00; + ciaNum = 1; + } + if (registerNum > 0x0F) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + + u8 registerValue = debuggerApiVice->GetCiaRegister(ciaNum, registerNum); + registers[registerNum] = registerValue; + } + + json j; + j["registers"] = registers; + + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + }); + + // SID + sprintf(buf, "%s/sid/write", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + + // Note: we need to burst-write to SID registers at once to avoid side-effects + // make all regs to not set SID + for (int sidNum = 0; sidNum < SOUND_SIDS_MAX; sidNum++) + { + for (int reg = 0; reg < C64_NUM_SID_REGISTERS; reg++) + { + sidData->shouldSetSidReg[sidNum][reg] = false; + } + } + + for (auto& [key, jsonSidData] : params["sids"].items()) + { + int sidNum = jsonSidData.at("num").get(); + if (sidNum < 0 || sidNum > SOUND_SIDS_MAX) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + + for (auto& [key, value] : jsonSidData["registers"].items()) + { + u64 registerNum = FUN_DecOrHexStrWithPrefixToU64(key.c_str()); + // TODO: subtract selected sid# address --> debugInterfaceVice->GetSidStereoAddress(sidNum) +// if (registerNum >= 0xD400 && registerNum < 0xDFFF) +// { +// registerNum -= 0xD400; +// } + + u64 registerValue = FUN_JsonValueDecOrHexStrWithPrefixToU64(value); + sidData->sidRegs[sidNum][registerNum] = registerValue; + sidData->shouldSetSidReg[sidNum][registerNum] = true; + } + } + + // write to SIDs at once (i.e. now when paused, or in next cycle when running) + debuggerApiVice->SetSid(sidData); + + debugInterfaceVice->UnlockMutex(); + + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/sid/read", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + + int sidNum = 0; + if (params.contains("num")) + { + sidNum = params.at("num").get(); + if (sidNum < 0 || sidNum > SOUND_SIDS_MAX) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + } + + std::unordered_map registers; + for (const auto& reg : params["registers"]) + { + u64 registerNum = FUN_JsonValueDecOrHexStrWithPrefixToU64(reg); + // TODO: subtract selected sid# address --> debugInterfaceVice->GetSidStereoAddress(sidNum) +// if (registerNum >= 0xD400 && registerNum < 0xDFFF) +// { +// registerNum -= 0xD400; +// } +// if (registerNum > 0x0F) +// { +// return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); +// } + + u8 registerValue = debuggerApiVice->GetSidRegister(sidNum, registerNum); + registers[registerNum] = registerValue; + } + + json j; + j["registers"] = registers; + + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + }); + + // + sprintf(buf, "%s/drive1541/cpu/memory/writeBlock", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); +// LOGD("cpu/memory/writeBlock: address=%d size=%d", address, binaryDataSize); +// LOG_PrintHexArray(binaryData, binaryDataSize); + + CDataAdapter *dataAdapter = debuggerApiVice->GetDataAdapterDrive1541MemoryWithIO(); + if (address + binaryDataSize > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + for (int i = 0; i < binaryDataSize; i++) + { + dataAdapter->AdapterWriteByte(address++, binaryData[i]); + } + + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/drive1541/cpu/memory/readBlock", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); + int size = params.at("size").get(); +// LOGD("cpu/memory/readBlock: address=%d size=%d", address, size); + + CDataAdapter *dataAdapter = debuggerApiVice->GetDataAdapterDrive1541MemoryWithIO(); + if (address + size > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + u8 *resultBinaryData = new u8[size]; + + for (int i = 0; i < size; i++) + { + dataAdapter->AdapterReadByte(address++, &resultBinaryData[i]); + } + return server->PrepareResult(HTTP_OK, token, json(), resultBinaryData, size); + }); + + sprintf(buf, "%s/drive1541/ram/clear", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); + int size = params.at("size").get(); + int value = 0; + if (params.contains("value")) + { + value = params.at("value").get(); + } + + CDataAdapter *dataAdapter = debuggerApiVice->GetDataAdapterDrive1541MemoryDirectRAM(); + if (address + size > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + for (int i = 0; i < size; i++) + { + dataAdapter->AdapterWriteByte(address++, value); + } + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/drive1541/ram/writeBlock", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); +// LOGD("%s/ram/writeBlock: address=%d size=%d", debugInterface->GetPlatformNameEndpointString(), address, binaryDataSize); +// LOG_PrintHexArray(binaryData, binaryDataSize); + + CDataAdapter *dataAdapter = debuggerApiVice->GetDataAdapterDrive1541MemoryDirectRAM(); + if (address + binaryDataSize > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + for (int i = 0; i < binaryDataSize; i++) + { + dataAdapter->AdapterWriteByte(address++, binaryData[i]); + } + + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/drive1541/ram/readBlock", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); + int size = params.at("size").get(); +// LOGD("readBlock: address=%d size=%d", address, size); + + CDataAdapter *dataAdapter = debuggerApiVice->GetDataAdapterDrive1541MemoryDirectRAM(); + if (address + size > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + u8 *resultBinaryData = new u8[size]; + + for (int i = 0; i < size; i++) + { + dataAdapter->AdapterReadByte(address++, &resultBinaryData[i]); + } + return server->PrepareResult(HTTP_OK, token, json(), resultBinaryData, size); + }); + + // Drive1541 VIA + sprintf(buf, "%s/drive1541/via/write", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + + int selectedViaNum = 0; + if (params.contains("num")) + { + selectedViaNum = params.at("num").get(); + if (selectedViaNum < 0 || selectedViaNum > 1) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + } + + int selectedDriveNum = 0; + if (params.contains("drive")) + { + selectedDriveNum = params.at("drive").get(); + if (selectedDriveNum < 0 || selectedDriveNum > MAX_DRIVE_NUM) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + } + + for (auto& [key, value] : params["registers"].items()) + { + int viaNum = selectedViaNum; + u64 registerNum = FUN_DecOrHexStrWithPrefixToU64(key.c_str()); + if (registerNum >= 0x1800 && registerNum < 0x1810) + { + registerNum -= 0x1800; + viaNum = 0; + } + if (registerNum >= 0x1C00 && registerNum < 0x1C10) + { + registerNum -= 0x1C00; + viaNum = 1; + } + if (registerNum > 0x0F) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + u64 registerValue = FUN_JsonValueDecOrHexStrWithPrefixToU64(value); + debuggerApiVice->SetDrive1541ViaRegister(selectedDriveNum, viaNum, registerNum, registerValue); + } + debugInterfaceVice->UnlockMutex(); + + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/drive1541/via/read", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debugInterfaceVice->LockMutex(); + + int selectedViaNum = 0; + if (params.contains("num")) + { + selectedViaNum = params.at("num").get(); + if (selectedViaNum < 0 || selectedViaNum > 1) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + } + + int selectedDriveNum = 0; + if (params.contains("drive")) + { + selectedDriveNum = params.at("drive").get(); + if (selectedDriveNum < 0 || selectedDriveNum > MAX_DRIVE_NUM) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + } + + std::unordered_map registers; + for (const auto& reg : params["registers"]) + { + int viaNum = selectedViaNum; + u64 registerNum = FUN_JsonValueDecOrHexStrWithPrefixToU64(reg); + if (registerNum >= 0x1800 && registerNum < 0x1810) + { + registerNum -= 0x1800; + viaNum = 0; + } + if (registerNum >= 0x1C00 && registerNum < 0x1C10) + { + registerNum -= 0x1C00; + viaNum = 1; + } + if (registerNum > 0x0F) + { + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + } + + u8 registerValue = debuggerApiVice->GetDrive1541ViaRegister(selectedDriveNum, viaNum, registerNum); + registers[registerNum] = registerValue; + } + + json j; + j["registers"] = registers; + + debugInterfaceVice->UnlockMutex(); + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + }); + + SYS_ReleaseCharBuf(buf); +} diff --git a/src/Emulators/vice/ViceInterface/CDebuggerServerApiVice.h b/src/Emulators/vice/ViceInterface/CDebuggerServerApiVice.h new file mode 100644 index 0000000..18b3ea3 --- /dev/null +++ b/src/Emulators/vice/ViceInterface/CDebuggerServerApiVice.h @@ -0,0 +1,26 @@ +#ifndef _CDebuggerServerApiVice_h_ +#define _CDebuggerServerApiVice_h_ + +#include "CDebuggerServerApi.h" +#include "drive.h" + +class CDebugInterfaceVice; +class CDebuggerApiVice; +class CSidData; + +const int MAX_DRIVE_NUM = DRIVE_NUM - 1; + +class CDebuggerServerApiVice : public CDebuggerServerApi +{ +public: + CDebuggerServerApiVice(CDebugInterface *debugInterface); + CDebugInterfaceVice *debugInterfaceVice; + CDebuggerApiVice *debuggerApiVice; + + virtual void RegisterEndpoints(CDebuggerServer *server); + + // + CSidData *sidData; +}; + +#endif diff --git a/src/Emulators/vice/ViceInterface/ViceWrapper.cpp b/src/Emulators/vice/ViceInterface/ViceWrapper.cpp index 1760456..0e05abf 100644 --- a/src/Emulators/vice/ViceInterface/ViceWrapper.cpp +++ b/src/Emulators/vice/ViceInterface/ViceWrapper.cpp @@ -155,7 +155,7 @@ void c64d_mark_c64_cell_read(uint16 addr) if (segment) { u8 value = c64d_peek_c64(addr); - CBreakpointMemory *breakpoint = segment->breakpointsMemory->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_READ); + CDebugBreakpointData *breakpoint = segment->breakpointsData->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_READ); if (breakpoint != NULL) { debugInterfaceVice->SetDebugMode(DEBUGGER_MODE_PAUSED); @@ -179,7 +179,7 @@ void c64d_mark_c64_cell_write(uint16 addr, uint8 value) CDebugSymbolsSegment *segment = debugInterfaceVice->symbols->currentSegment; if (segment) { - CBreakpointMemory *breakpoint = segment->breakpointsMemory->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_WRITE); + CDebugBreakpointData *breakpoint = segment->breakpointsData->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_WRITE); if (breakpoint != NULL) { debugInterfaceVice->SetDebugMode(DEBUGGER_MODE_PAUSED); @@ -215,7 +215,7 @@ void c64d_mark_drive1541_cell_read(uint16 addr) u8 value = c64d_peek_drive(segment->driveNum, addr); - CBreakpointMemory *breakpoint = segment->breakpointsMemory->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_READ); + CDebugBreakpointData *breakpoint = segment->breakpointsData->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_READ); if (breakpoint) { debugInterfaceVice->SetDebugMode(DEBUGGER_MODE_PAUSED); @@ -241,7 +241,7 @@ void c64d_mark_drive1541_cell_write(uint16 addr, uint8 value) { debugInterfaceVice->LockMutex(); - CBreakpointMemory *breakpoint = segment->breakpointsMemory->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_WRITE); + CDebugBreakpointData *breakpoint = segment->breakpointsData->EvaluateBreakpoint(addr, value, MEMORY_BREAKPOINT_ACCESS_WRITE); if (breakpoint) { debugInterfaceVice->SetDebugMode(DEBUGGER_MODE_PAUSED); @@ -693,7 +693,7 @@ void c64d_c64_check_pc_breakpoint(uint16 pc) { debugInterfaceVice->LockMutex(); - CBreakpointAddr *addrBreakpoint = segment->breakpointsPC->EvaluateBreakpoint(pc); + CDebugBreakpointAddr *addrBreakpoint = segment->breakpointsPC->EvaluateBreakpoint(pc); if (addrBreakpoint != NULL) { if (IS_SET(addrBreakpoint->actions, ADDR_BREAKPOINT_ACTION_SET_BACKGROUND)) @@ -756,7 +756,7 @@ void c64d_drive1541_check_pc_breakpoint(uint16 pc) else if (segment->breakOnPC) { debugInterfaceVice->LockMutex(); - CBreakpointAddr *addrBreakpoint = segment->breakpointsPC->EvaluateBreakpoint(pc); + CDebugBreakpointAddr *addrBreakpoint = segment->breakpointsPC->EvaluateBreakpoint(pc); if (addrBreakpoint != NULL) { if (IS_SET(addrBreakpoint->actions, ADDR_BREAKPOINT_ACTION_STOP)) @@ -1142,7 +1142,7 @@ void c64d_c64_check_raster_breakpoint(uint16 rasterLine) debugInterfaceVice->LockMutex(); if (segment && segment->breakOnRaster) { - CBreakpointAddr *breakpoint = segment->breakpointsRasterLine->EvaluateBreakpoint(rasterLine); + CDebugBreakpointAddr *breakpoint = segment->breakpointsRasterLine->EvaluateBreakpoint(rasterLine); if (breakpoint != NULL) { debugInterfaceVice->SetDebugMode(DEBUGGER_MODE_PAUSED); diff --git a/src/Emulators/vice/arch/mousedrv.c b/src/Emulators/vice/arch/mousedrv.c index 8acb823..070e5d9 100644 --- a/src/Emulators/vice/arch/mousedrv.c +++ b/src/Emulators/vice/arch/mousedrv.c @@ -114,6 +114,15 @@ void mouse_move(int x, int y) mouse_timestamp = vsyncarch_gettime(); } +void c64d_mouse_set_position(int x, int y) +{ + mouse_x = x; + mouse_y = y; + mouse_timestamp = vsyncarch_gettime(); +} + +//void c64d_set_mouse_pos(int x, int y); + unsigned long mousedrv_get_timestamp(void) { return mouse_timestamp; @@ -133,3 +142,13 @@ void mousedrv_button_middle(int pressed) { mouse_funcs.mbm(pressed); } + +void mousedrv_button_up(int pressed) +{ + mouse_funcs.mbu(pressed); +} + +void mousedrv_button_down(int pressed) +{ + mouse_funcs.mbd(pressed); +} diff --git a/src/Emulators/vice/joyport/joyport.c b/src/Emulators/vice/joyport/joyport.c index 0f11695..8956c02 100644 --- a/src/Emulators/vice/joyport/joyport.c +++ b/src/Emulators/vice/joyport/joyport.c @@ -74,7 +74,7 @@ void set_joyport_pot_mask(int mask) pot_port_mask = mask; } -static int joyport_set_device(int port, int id) +int joyport_set_device(int port, int id) { int i; diff --git a/src/Emulators/vice/joyport/mouse.c b/src/Emulators/vice/joyport/mouse.c index 025ecd5..f94affa 100644 --- a/src/Emulators/vice/joyport/mouse.c +++ b/src/Emulators/vice/joyport/mouse.c @@ -628,7 +628,7 @@ static int mt_to_id(int mt) return -1; } -static int joyport_mouse_enable(int port, int val) +int joyport_mouse_enable(int port, int val) { int mt; @@ -669,6 +669,25 @@ static int joyport_mouse_enable(int port, int val) return 0; } +void c64d_mouse_set_type(int mt) +{ + if (mt != MOUSE_TYPE_SMART) + { + if (ds1202) { + ds1202_1302_destroy(ds1202, ds1202_rtc_save); + ds1202 = NULL; + } + mouse_type = -1; + } + + mouse_type = mt; +} + +int c64d_mouse_type_to_joyportid(int mouseType) +{ + return mt_to_id(mouseType); +} + static BYTE joyport_mouse_value(int port) { return _mouse_enabled ? (BYTE)~mouse_digital_val : 0xff; @@ -944,7 +963,7 @@ static int mouse_joyport_register(void) /* --------------------------------------------------------- */ /* Resources & cmdline */ -static int set_mouse_enabled(int val, void *param) +int set_mouse_enabled(int val, void *param) { if (_mouse_enabled == val) { return 0; diff --git a/src/Plugins/C64D_InitPlugins.cpp b/src/Plugins/C64D_InitPlugins.cpp index 28dc19e..14e4909 100644 --- a/src/Plugins/C64D_InitPlugins.cpp +++ b/src/Plugins/C64D_InitPlugins.cpp @@ -30,7 +30,6 @@ void C64D_InitPlugins() // viewC64->RegisterEmulatorPlugin(plugin); // C64DebuggerPluginCommando *plugin = new C64DebuggerPluginCommando(300, 30, 0, 500, 400); -// viewC64->RegisterEmulatorPlugin(plugin); - +// viewC64->RegisterEmulatorPlugin(plugin); } diff --git a/src/Plugins/CrtMaker/CViewC64CrtMaker.cpp b/src/Plugins/CrtMaker/CViewC64CrtMaker.cpp index 1508182..a7b6729 100644 --- a/src/Plugins/CrtMaker/CViewC64CrtMaker.cpp +++ b/src/Plugins/CrtMaker/CViewC64CrtMaker.cpp @@ -496,7 +496,7 @@ void CViewC64CrtMaker::Run() } // run the cart - api->debugInterface->HardReset(); + api->debugInterface->ResetHard(); api->debugInterface->SetDebugMode(DEBUGGER_MODE_RUNNING); SYS_Sleep(300); diff --git a/src/Plugins/Slideshow/C64DebuggerPluginSlideshow.cpp b/src/Plugins/Slideshow/C64DebuggerPluginSlideshow.cpp index 0087ba4..9eb0eac 100644 --- a/src/Plugins/Slideshow/C64DebuggerPluginSlideshow.cpp +++ b/src/Plugins/Slideshow/C64DebuggerPluginSlideshow.cpp @@ -191,7 +191,7 @@ void C64DebuggerPluginSlideshow::ThreadRun(void *data) crtMaker->MakeCartridge(); // run the cart - api->debugInterface->HardReset(); + api->debugInterface->ResetHard(); api->debugInterface->SetDebugMode(DEBUGGER_MODE_RUNNING); SYS_Sleep(300); @@ -391,7 +391,7 @@ void C64DebuggerPluginSlideshow::ThreadRun(void *data) // recreate CRT crtMaker->ProcessFiles(); crtMaker->MakeCartridge(); - viewC64->viewC64MainMenu->InsertCartridge(new CSlrString(crtMaker->cartOutPath), false); + viewC64->mainMenuHelper->InsertCartridge(new CSlrString(crtMaker->cartOutPath), false); //api->MakeJmp(entryPoint); api->UnPauseEmulation(); diff --git a/src/Remote/CDebuggerServer.cpp b/src/Remote/CDebuggerServer.cpp new file mode 100644 index 0000000..121e324 --- /dev/null +++ b/src/Remote/CDebuggerServer.cpp @@ -0,0 +1,42 @@ +#include "CDebuggerServer.h" + +CDebuggerServer::CDebuggerServer() +{ +} + +void CDebuggerServer::Start() +{ +} + +void CDebuggerServer::Stop() +{ +} + +void CDebuggerServer::AddEndpointFunction(const std::string& endpointName, std::function *(const std::string, const nlohmann::json, u8 *, int)> func) +{ + +} + +std::vector *CDebuggerServer::RunEndpointFunction(const std::string& endpointName, const std::string token, nlohmann::json params, u8 *binaryData, int binaryDataSize) +{ + return NULL; +} + +std::vector *CDebuggerServer::PrepareResult(int status, const std::string token, nlohmann::json resultJson, u8 *binaryData, int binaryDataSize) +{ + return NULL; +} + +void CDebuggerServer::ThreadRun(void *passData) +{ +} + +void CDebuggerServer::BroadcastEvent(const char *eventName, nlohmann::json j) +{ + +} + +bool CDebuggerServer::AreClientsConnected() +{ + return false; +} diff --git a/src/Remote/CDebuggerServer.h b/src/Remote/CDebuggerServer.h new file mode 100644 index 0000000..6c85c2d --- /dev/null +++ b/src/Remote/CDebuggerServer.h @@ -0,0 +1,99 @@ +#ifndef _CDebuggerServer_h_ +#define _CDebuggerServer_h_ + +#include "SYS_Defs.h" +#include "SYS_Threading.h" +#include "json.hpp" + +class CDebuggerServer : public CSlrThread +{ +public: + CDebuggerServer(); + + virtual void Start(); + virtual void Stop(); + + virtual void AddEndpointFunction(const std::string& endpointName, std::function *(const std::string, const nlohmann::json, u8 *, int)> func); + virtual std::vector *RunEndpointFunction(const std::string& endpointName, const std::string token, nlohmann::json params, u8 *binaryData, int binaryDataSize); + virtual std::vector *PrepareResult(int status, const std::string token, nlohmann::json resultJson, u8 *binaryData, int binaryDataSize); + + virtual void ThreadRun(void *passData); + + virtual void BroadcastEvent(const char *eventName, nlohmann::json j); + + virtual bool AreClientsConnected(); +}; + +// 1xx: Informational +#define HTTP_CONTINUE 100 +#define HTTP_SWITCHING_PROTOCOLS 101 +#define HTTP_PROCESSING 102 + +// 2xx: Success +#define HTTP_OK 200 +#define HTTP_CREATED 201 +#define HTTP_ACCEPTED 202 +#define HTTP_NON_AUTHORITATIVE_INFORMATION 203 +#define HTTP_NO_CONTENT 204 +#define HTTP_RESET_CONTENT 205 +#define HTTP_PARTIAL_CONTENT 206 +#define HTTP_MULTI_STATUS 207 +#define HTTP_ALREADY_REPORTED 208 +#define HTTP_IM_USED 226 + +// 3xx: Redirection +#define HTTP_MULTIPLE_CHOICES 300 +#define HTTP_MOVED_PERMANENTLY 301 +#define HTTP_FOUND 302 +#define HTTP_SEE_OTHER 303 +#define HTTP_NOT_MODIFIED 304 +#define HTTP_USE_PROXY 305 +#define HTTP_TEMPORARY_REDIRECT 307 +#define HTTP_PERMANENT_REDIRECT 308 + +// 4xx: Client Errors +#define HTTP_BAD_REQUEST 400 +#define HTTP_UNAUTHORIZED 401 +#define HTTP_PAYMENT_REQUIRED 402 +#define HTTP_FORBIDDEN 403 +#define HTTP_NOT_FOUND 404 +#define HTTP_METHOD_NOT_ALLOWED 405 +#define HTTP_NOT_ACCEPTABLE 406 +#define HTTP_PROXY_AUTHENTICATION_REQUIRED 407 +#define HTTP_REQUEST_TIMEOUT 408 +#define HTTP_CONFLICT 409 +#define HTTP_GONE 410 +#define HTTP_LENGTH_REQUIRED 411 +#define HTTP_PRECONDITION_FAILED 412 +#define HTTP_PAYLOAD_TOO_LARGE 413 +#define HTTP_URI_TOO_LONG 414 +#define HTTP_UNSUPPORTED_MEDIA_TYPE 415 +#define HTTP_RANGE_NOT_SATISFIABLE 416 +#define HTTP_EXPECTATION_FAILED 417 +#define HTTP_I_AM_A_TEAPOT 418 +#define HTTP_SESSION_EXPIRED 419 +#define HTTP_MISDIRECTED_REQUEST 421 +#define HTTP_UNPROCESSABLE_ENTITY 422 +#define HTTP_LOCKED 423 +#define HTTP_FAILED_DEPENDENCY 424 +#define HTTP_TOO_EARLY 425 +#define HTTP_UPGRADE_REQUIRED 426 +#define HTTP_PRECONDITION_REQUIRED 428 +#define HTTP_TOO_MANY_REQUESTS 429 +#define HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE 431 +#define HTTP_UNAVAILABLE_FOR_LEGAL_REASONS 451 + +// 5xx: Server Errors +#define HTTP_INTERNAL_SERVER_ERROR 500 +#define HTTP_NOT_IMPLEMENTED 501 +#define HTTP_BAD_GATEWAY 502 +#define HTTP_SERVICE_UNAVAILABLE 503 +#define HTTP_GATEWAY_TIMEOUT 504 +#define HTTP_HTTP_VERSION_NOT_SUPPORTED 505 +#define HTTP_VARIANT_ALSO_NEGOTIATES 506 +#define HTTP_INSUFFICIENT_STORAGE 507 +#define HTTP_LOOP_DETECTED 508 +#define HTTP_NOT_EXTENDED 510 +#define HTTP_NETWORK_AUTHENTICATION_REQUIRED 511 + +#endif diff --git a/src/Remote/CDebuggerServerApi.cpp b/src/Remote/CDebuggerServerApi.cpp new file mode 100644 index 0000000..60c3217 --- /dev/null +++ b/src/Remote/CDebuggerServerApi.cpp @@ -0,0 +1,406 @@ +#include "SYS_Main.h" +#include "CDebuggerServerApi.h" +#include "CDebuggerServer.h" +#include "CDebugInterface.h" +#include "CDebuggerApi.h" +#include "CDebugSymbolsSegment.h" + +using namespace std; +using namespace nlohmann; + +CDebuggerServerApi::CDebuggerServerApi(CDebugInterface *debugInterface) +: debugInterface(debugInterface) +{ + debuggerApi = debugInterface->GetDebuggerApi(); +} + +void CDebuggerServerApi::RegisterEndpoints(CDebuggerServer *server) +{ + LOGD("CDebuggerServerApi::RegisterEndpoints: /%s", debugInterface->GetPlatformNameEndpointString()); + char *buf = SYS_GetCharBuf(); + + sprintf(buf, "%s/reset/hard", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debuggerApi->ResetMachine(true); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/reset/soft", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debuggerApi->ResetMachine(false); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/detachEverything", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debuggerApi->DetachEverything(); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/warp/set", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + bool warp = params.at("warp").get(); + debuggerApi->SetWarpSpeed(warp); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/pause", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debuggerApi->PauseEmulation(); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/continue", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debuggerApi->UnPauseEmulation(); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/step/cycle", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debuggerApi->StepOneCycle(); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/step/instruction", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debuggerApi->StepOverInstruction(); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/step/subroutine", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + debuggerApi->StepOverSubroutine(); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/cpu/status", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + json cpuStatus = debuggerApi->GetCpuStatusJson(); + return server->PrepareResult(HTTP_OK, token, cpuStatus, NULL, 0); + }); + + sprintf(buf, "%s/cpu/makejmp", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); + debuggerApi->MakeJmp(address); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/cpu/counters/read", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char *binaryData, int binaryDataSize) -> vector* + { + json counters; + counters["cycle"] = debuggerApi->GetMainCpuCycleCounter(); + counters["instruction"] = debuggerApi->GetMainCpuInstructionCycleCounter(); + counters["frame"] = debuggerApi->GetEmulationFrameNumber(); + return server->PrepareResult(HTTP_OK, token, counters, NULL, 0); + }); + + sprintf(buf, "%s/cpu/memory/writeBlock", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); +// LOGD("cpu/memory/writeBlock: address=%d size=%d", address, binaryDataSize); +// LOG_PrintHexArray(binaryData, binaryDataSize); + + CDataAdapter *dataAdapter = debuggerApi->GetDataAdapterMemoryWithIO(); + if (address + binaryDataSize > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + for (int i = 0; i < binaryDataSize; i++) + { + dataAdapter->AdapterWriteByte(address++, binaryData[i]); + } + + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/cpu/memory/readBlock", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); + int size = params.at("size").get(); +// LOGD("cpu/memory/readBlock: address=%d size=%d", address, size); + + CDataAdapter *dataAdapter = debuggerApi->GetDataAdapterMemoryWithIO(); + if (address + size > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + u8 *resultBinaryData = new u8[size]; + + for (int i = 0; i < size; i++) + { + dataAdapter->AdapterReadByte(address++, &resultBinaryData[i]); + } + return server->PrepareResult(HTTP_OK, token, json(), resultBinaryData, size); + }); + + sprintf(buf, "%s/ram/clear", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); + int size = params.at("size").get(); + int value = 0; + if (params.contains("value")) + { + value = params.at("value").get(); + } + + CDataAdapter *dataAdapter = debuggerApi->GetDataAdapterMemoryDirectRAM(); + if (address + size > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + for (int i = 0; i < size; i++) + { + dataAdapter->AdapterWriteByte(address++, value); + } + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/ram/writeBlock", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); +// LOGD("%s/ram/writeBlock: address=%d size=%d", debugInterface->GetPlatformNameEndpointString(), address, binaryDataSize); +// LOG_PrintHexArray(binaryData, binaryDataSize); + + CDataAdapter *dataAdapter = debuggerApi->GetDataAdapterMemoryDirectRAM(); + if (address + binaryDataSize > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + for (int i = 0; i < binaryDataSize; i++) + { + dataAdapter->AdapterWriteByte(address++, binaryData[i]); + } + + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/ram/readBlock", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int address = params.at("address").get(); + int size = params.at("size").get(); +// LOGD("readBlock: address=%d size=%d", address, size); + + CDataAdapter *dataAdapter = debuggerApi->GetDataAdapterMemoryDirectRAM(); + if (address + size > dataAdapter->AdapterGetDataLength()) + { + return server->PrepareResult(HTTP_PAYLOAD_TOO_LARGE, token, json(), NULL, 0); + } + + u8 *resultBinaryData = new u8[size]; + + for (int i = 0; i < size; i++) + { + dataAdapter->AdapterReadByte(address++, &resultBinaryData[i]); + } + return server->PrepareResult(HTTP_OK, token, json(), resultBinaryData, size); + }); + + sprintf(buf, "%s/input/key/down", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int mtKeyCode = params.at("keyCode").get(); + bool res = debuggerApi->KeyboardDown(mtKeyCode); + return server->PrepareResult(res ? HTTP_OK : HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/input/key/up", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + int mtKeyCode = params.at("keyCode").get(); + bool res = debuggerApi->KeyboardUp(mtKeyCode); + return server->PrepareResult(res ? HTTP_OK : HTTP_NOT_ACCEPTABLE, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/input/joystick/down", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + u32 axis = CDebuggerApi::JoypadAxisNameToAxisCode(params.at("axis")); + int port = params.at("port"); + debuggerApi->JoystickDown(port, axis); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + sprintf(buf, "%s/input/joystick/up", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + u32 axis = CDebuggerApi::JoypadAxisNameToAxisCode(params.at("axis")); + int port = params.at("port"); + debuggerApi->JoystickUp(port, axis); + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + // breakpoints + sprintf(buf, "%s/cpu/breakpoint/add", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + u64 addr = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("addr")); + json j; + + u64 breakpointId = debuggerApi->AddBreakpointPC((int)addr); + if (breakpointId != UNKNOWN_BREAKPOINT_ID) + { + j["breakpointId"] = breakpointId; + char *strSegment = debugInterface->symbols->currentSegment->name->GetStdASCII(); + j["segment"] = strSegment; + delete [] strSegment; + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + } + + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, j, NULL, 0); + }); + + sprintf(buf, "%s/cpu/breakpoint/remove", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + u64 addr = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("addr")); + json j; + + u64 breakpointId = debuggerApi->RemoveBreakpointPC((int)addr); + if (breakpointId != UNKNOWN_BREAKPOINT_ID) + { + j["breakpointId"] = breakpointId; + char *strSegment = debugInterface->symbols->currentSegment->name->GetStdASCII(); + j["segment"] = strSegment; + delete [] strSegment; + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + } + + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, j, NULL, 0); + }); + + sprintf(buf, "%s/cpu/memory/breakpoint/add", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + u64 addr = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("addr")); + u64 value = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("value")); + + json j; + + u32 memoryAccess = MEMORY_BREAKPOINT_ACCESS_WRITE; + if (params.contains("access")) + { + if (params.at("access") == "read") + { + memoryAccess = MEMORY_BREAKPOINT_ACCESS_READ; + } + else if (params.at("access") == "write") + { + memoryAccess = MEMORY_BREAKPOINT_ACCESS_WRITE; + } + else server->PrepareResult(HTTP_BAD_REQUEST, token, j, NULL, 0); + } + + DataBreakpointComparison comparison = DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL; + if (params.contains("comparison")) + { + string comparisonStr = params.at("comparison"); + comparison = CDebugBreakpointsData::StrToDataBreakpointComparison(comparisonStr.c_str()); + } + + u64 breakpointId = debuggerApi->AddBreakpointMemory((int)addr, memoryAccess, comparison, (int)value); + if (breakpointId != UNKNOWN_BREAKPOINT_ID) + { + j["breakpointId"] = breakpointId; + char *strSegment = debugInterface->symbols->currentSegment->name->GetStdASCII(); + j["segment"] = strSegment; + delete [] strSegment; + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + } + + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, j, NULL, 0); + }); + + sprintf(buf, "%s/cpu/memory/breakpoint/remove", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + u64 addr = FUN_JsonValueDecOrHexStrWithPrefixToU64(params.at("addr")); + json j; + + u64 breakpointId = debuggerApi->RemoveBreakpointMemory((int)addr); + if (breakpointId != UNKNOWN_BREAKPOINT_ID) + { + j["breakpointId"] = breakpointId; + char *strSegment = debugInterface->symbols->currentSegment->name->GetStdASCII(); + j["segment"] = strSegment; + delete [] strSegment; + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + } + + return server->PrepareResult(HTTP_NOT_ACCEPTABLE, token, j, NULL, 0); + }); + + // set/get segment + sprintf(buf, "%s/segment/read", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + json j; + CSlrString *segmentNameStr = debuggerApi->GetCurrentSegmentName(); + if (segmentNameStr == NULL) + { + j["segment"] = ""; + } + else + { + const char *name = segmentNameStr->GetStdASCII(); + j["segment"] = name; + delete [] name; + } + + return server->PrepareResult(HTTP_OK, token, j, NULL, 0); + }); + + sprintf(buf, "%s/segment/write", debugInterface->GetPlatformNameEndpointString()); + server->AddEndpointFunction(buf, [this, server](const string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + string segmentName = params["segment"]; + CSlrString *segmentNameStr = new CSlrString(segmentName.c_str()); + bool ret = debuggerApi->SetCurrentSegment(segmentNameStr); + delete segmentNameStr; + + if (ret) + { + return server->PrepareResult(HTTP_OK, token, json(), NULL, 0); + } + else + { + return server->PrepareResult(HTTP_NOT_FOUND, token, json(), NULL, 0); + } + + }); + + + // TODO: store/restore snapshot (binary blob) + + // Symbols: + // DONE? add breakpoint + breakpoint callback + // TODO: Breakpoint VSync callback + // void CDebugInterface::DoFrame() -- is raster line ok? (no, because it's only for c64) + + // TODO: add watch + // TODO: get current source file path / line / column + + SYS_ReleaseCharBuf(buf); +} diff --git a/src/Remote/CDebuggerServerApi.h b/src/Remote/CDebuggerServerApi.h new file mode 100644 index 0000000..7358559 --- /dev/null +++ b/src/Remote/CDebuggerServerApi.h @@ -0,0 +1,19 @@ +#ifndef _CDebuggerServerApi_h_ +#define _CDebuggerServerApi_h_ + +// generic server api +class CDebugInterface; +class CDebuggerApi; +class CDebuggerServer; + +class CDebuggerServerApi +{ +public: + CDebuggerServerApi(CDebugInterface *debugInterface); + CDebugInterface *debugInterface; + CDebuggerApi *debuggerApi; + + virtual void RegisterEndpoints(CDebuggerServer *server); +}; + +#endif diff --git a/src/Remote/Pipe/CPipeProtocolDebuggerCallback.cpp b/src/Remote/Pipe/CPipeProtocolDebuggerCallback.cpp new file mode 100644 index 0000000..eb070fe --- /dev/null +++ b/src/Remote/Pipe/CPipeProtocolDebuggerCallback.cpp @@ -0,0 +1,176 @@ +#include "CPipeProtocolDebuggerCallback.h" +#include "SYS_PIPE.h" +#include "CViewC64.h" +#include "CMainMenuHelper.h" +#include "CViewDisassembly.h" + +bool CPipeProtocolDebuggerCallback::PipeProtocolCallbackInterpretPacket(CByteBuffer *inByteBuffer) +{ + LOGD("CPipeProtocolDebuggerCallback"); + + u16 packetId = inByteBuffer->GetU16(); + u32 sequenceNumber = inByteBuffer->GetU32(); + + LOGD("... packetId=%02x sequenceNumber=%d", packetId, sequenceNumber); + + // simple parser for now + switch(packetId) + { + case C64D_PACKET_STATUS: + // skip + break; + + case C64D_PACKET_LOAD_FILE: + { + bool autoStart = inByteBuffer->GetBool(); + bool showLoadingAddr = inByteBuffer->GetBool(); + bool forceReset = inByteBuffer->GetBool(); + CSlrString *path = inByteBuffer->GetSlrString(); + bool ret = viewC64->mainMenuHelper->LoadPRG(path, autoStart, true, showLoadingAddr, forceReset); + SendBinaryPacketStatus(sequenceNumber, ret ? C64D_PACKET_STATUS_OK : C64D_PACKET_STATUS_ERROR_NOT_FOUND); + } break; + + case C64D_PACKET_PAUSE_RUN: + { + viewC64->StepOverInstruction(); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } break; + + case C64D_PACKET_CONTINUE_RUN: + { + viewC64->RunContinueEmulation(); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } break; + + case C64D_PACKET_STEP_ONE_CYCLE: + { + viewC64->StepOneCycle(); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } break; + + case C64D_PACKET_STEP_ONE_INSTRUCTION: + { + viewC64->StepOverInstruction(); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } break; + + case C64D_PACKET_STEP_OVER_JSR: + { + CViewDisassembly *viewDisassembly = viewC64->GetActiveDisassemblyView(); + if (viewDisassembly) + { + viewDisassembly->StepOverJsr(); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } + else + { + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_ERROR_NOT_FOUND); + } + } break; + + case C64D_PACKET_RESET_SOFT: + viewC64->ResetSoft(); + break; + + case C64D_PACKET_RESET_HARD: + viewC64->ResetHard(); + break; + + case C64D_PACKET_JMP_TO_ADDRESS_AT_CURSOR: + { + CViewDisassembly *viewDisassembly = viewC64->GetActiveDisassemblyView(); + if (viewDisassembly) + { + viewDisassembly->MakeJMPToCursor(); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } + else + { + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_ERROR_NOT_FOUND); + } + } break; + + case C64D_PACKET_MOVE_CURSOR_TO_ADDRESS: + { + u16 address = inByteBuffer->GetU16(); + + CViewDisassembly *viewDisassembly = viewC64->GetActiveDisassemblyView(); + if (viewDisassembly) + { + viewDisassembly->ScrollToAddress(address); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } + else + { + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_ERROR_NOT_FOUND); + } + } break; + + case C64D_PACKET_MAKE_JMP_TO_ADDRESS: + { + u16 address = inByteBuffer->GetU16(); + + CViewDisassembly *viewDisassembly = viewC64->GetActiveDisassemblyView(); + if (viewDisassembly) + { + viewDisassembly->MakeJMPToAddress(address); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } + else + { + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_ERROR_NOT_FOUND); + } + } break; + + case C64D_PACKET_GET_CPU_STATUS: + LOGError("C64D_PACKET_GET_CPU_STATUS not implemented"); + break; + + case C64D_PACKET_SET_BREAKPOINT_PC: + { + u16 address = inByteBuffer->GetU16(); + bool setOn = inByteBuffer->GetBool(); + + CViewDisassembly *viewDisassembly = viewC64->GetActiveDisassemblyView(); + if (viewDisassembly) + { + viewDisassembly->SetBreakpointPC(address, setOn); + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_OK); + } + else + { + SendBinaryPacketStatus(sequenceNumber, C64D_PACKET_STATUS_ERROR_NOT_FOUND); + } + } break; + + default: + LOGError("PipeProtocolCallbackInterpretPacket: Unknown packet id=%02x", packetId); + return false; + } + + + LOGD("PipeProtocolCallbackInterpretPacket: done"); + return true; +} + +void CPipeProtocolDebuggerCallback::SendBinaryPacketStatus(u32 sequenceNumber, u8 errorNum) +{ + CByteBuffer *byteBuffer = new CByteBuffer(); + byteBuffer->putU16(C64D_PACKET_STATUS); + byteBuffer->PutU32(sequenceNumber); + byteBuffer->PutU8(errorNum); + + // TODO: sync mutex + PIPE_SendByteBuffer(byteBuffer); +} + +void CPipeProtocolDebuggerCallback::SendBinaryPacket(u16 packetId, u32 sequenceNumber, CByteBuffer *data) +{ + LOGD("CPipeProtocolDebuggerCallback::SendBinaryPacket: packetId=%02x sequenceNumber=%d", packetId, sequenceNumber); + + // TODO: do we really need sequence number and packetId? + PIPE_SendByteBuffer(data); + + LOGD("CPipeProtocolDebuggerCallback::SendBinaryPacket: done"); +} + diff --git a/src/Remote/Pipe/CPipeProtocolDebuggerCallback.h b/src/Remote/Pipe/CPipeProtocolDebuggerCallback.h new file mode 100644 index 0000000..8d7d997 --- /dev/null +++ b/src/Remote/Pipe/CPipeProtocolDebuggerCallback.h @@ -0,0 +1,43 @@ +#ifndef _CPipeProtocolRetroDebuggerCallback_H_ +#define _CPipeProtocolRetroDebuggerCallback_H_ + +// TODO: this is deprecated and will be removed + +#include "CByteBuffer.h" +#include "SYS_PIPE.h" + +class CPipeProtocolDebuggerCallback : public CPipeProtocolCallback +{ +public: + virtual bool PipeProtocolCallbackInterpretPacket(CByteBuffer *inByteBuffer); + void SendBinaryPacketStatus(u32 sequenceNumber, u8 errorNum); + void SendBinaryPacket(u16 packetId, u32 sequenceNumber, CByteBuffer *data); +}; + + +typedef enum c64d_packet_e { + C64D_PACKET_STATUS = 0, + C64D_PACKET_LOAD_FILE, + C64D_PACKET_PAUSE_RUN, + C64D_PACKET_CONTINUE_RUN, + C64D_PACKET_STEP_ONE_CYCLE, + C64D_PACKET_STEP_ONE_INSTRUCTION, + C64D_PACKET_STEP_OVER_JSR, + C64D_PACKET_RESET_SOFT, + C64D_PACKET_RESET_HARD, + C64D_PACKET_JMP_TO_ADDRESS_AT_CURSOR, + C64D_PACKET_MOVE_CURSOR_TO_ADDRESS, + C64D_PACKET_MAKE_JMP_TO_ADDRESS, + C64D_PACKET_GET_CPU_STATUS, + C64D_PACKET_SET_BREAKPOINT_PC, + C64D_PACKET_LAST +} c64d_packet_t; + +typedef enum c64d_packet_status_e { + C64D_PACKET_STATUS_OK = 0, + C64D_PACKET_STATUS_ERROR_NOT_FOUND +} c64d_packet_status_t; + + + +#endif diff --git a/src/Remote/WebSockets/CDebuggerServerWebSockets.cpp b/src/Remote/WebSockets/CDebuggerServerWebSockets.cpp new file mode 100644 index 0000000..dd16943 --- /dev/null +++ b/src/Remote/WebSockets/CDebuggerServerWebSockets.cpp @@ -0,0 +1,280 @@ +#ifdef WIN32 +#include +#endif + +#include "DBG_Log.h" +#include "CDebuggerServerWebSockets.h" +#include "CViewC64.h" +#include "CDebugInterface.h" +#include "CDebuggerServerApi.h" +#include "json.hpp" + +using namespace std; +using namespace nlohmann; + +CDebuggerServer *REMOTE_CreateDebuggerServerWebSockets(int port) +{ + return new CDebuggerServerWebSockets(port); +} + +void REMOTE_DebuggerServerWebSocketsSetPort(CDebuggerServer *debuggerServer, int port) +{ + ((CDebuggerServerWebSockets*)debuggerServer)->SetPort(port); +} + +CDebuggerServerWebSockets::CDebuggerServerWebSockets(int port) +: port(port) +{ + app = NULL; + serverStarted = false; + numConnectedClients = 0; +} + +void CDebuggerServerWebSockets::SetPort(int port) +{ + this->port = port; +} + +void CDebuggerServerWebSockets::Start() +{ + if (serverStarted) + { + LOGError("CDebuggerServerWebSockets: server already started"); + return; + } + + SYS_StartThread(this); +} + +// Note, Stop will not shutdown server immediately, appLoop will still run if clients are connected +// TODO: force disconnect clients in CDebuggerServerWebSockets +void CDebuggerServerWebSockets::Stop() +{ + if (!serverStarted) + { + LOGError("CDebuggerServerWebSockets: server is not running"); + return; + } + + if (!listenSocket) + { + LOGError("CDebuggerServerWebSockets: listenSocket is NULL"); + serverStarted = false; + return; + } + + appLoop->defer([this]() + { + us_listen_socket_close(0, listenSocket); + listenSocket = nullptr; + numConnectedClients = 0; + }); +} + +bool CDebuggerServerWebSockets::AreClientsConnected() +{ + if (serverStarted && numConnectedClients > 0) + return true; + return false; +} + +void CDebuggerServerWebSockets::ThreadRun(void *passData) +{ + ThreadSetName("WSDebugServer"); + + numConnectedClients = 0; + + app = new uWS::App(); + app->listen(this->port, [this](auto *token) + { + if (token) + { + this->listenSocket = token; + LOGM("WebSockets debugger server listening on port %d", port); + } + else + { + LOGError("WebSockets debugger server failed to listen on port %d", port); + return; + } + }); + + appLoop = app->getLoop(); + + // + AddEndpointFunction("load", [this](string token, json params, unsigned char* binaryData, int binaryDataSize) -> vector* + { + string fileName = params.at("path").get(); + CSlrString *str = new CSlrString(StringToUtf16(string(fileName))); + viewC64->mainMenuHelper->LoadFile(str); + delete str; + return PrepareResult(HTTP_OK, token, json(), NULL, 0); + }); + + // register endpoints for all emulators + for (auto it = viewC64->debugInterfaces.begin(); it != viewC64->debugInterfaces.end(); it++) + { + CDebugInterface *debugInterface = *it; + CDebuggerServerApi *webSocketsApi = debugInterface->GetDebuggerServerApi(); + webSocketsApi->RegisterEndpoints(this); + } + + app->ws("/stream", { + .open = [this](auto* ws) + { + numConnectedClients++; + LOGD("WebSocket connection opened (numConnectedClients=%d)", numConnectedClients); + ws->subscribe("broadcast"); + }, + .message = [this](auto* ws, string_view message, uWS::OpCode opCode) + { + string jsonStr; + + try + { + auto endPos = message.find('\0'); + bool hasBinary = false; + int binaryDataSize = 0; + + if (endPos != string_view::npos) + { + jsonStr = message.substr(0, endPos); + binaryDataSize = (int)message.size() - (int)endPos - 1; + + if (binaryDataSize > 0) + hasBinary = true; + } + else + { + jsonStr = message; + } + +// LOGD("/stream JSON:") +// cout << message << endl; + + json j = json::parse(jsonStr); + + string fn = j["fn"].get(); + string token; + + if (j.contains("token")) + { + token = j["token"].get(); + } + + vector *result; + if (hasBinary == false) + { + result = RunEndpointFunction(fn, token, j["params"], nullptr, 0); + } + else + { + unsigned char* binaryData = nullptr; + + if (binaryDataSize > 0 && message.size() > endPos + 1) + { + binaryData = new unsigned char[binaryDataSize]; + memcpy(binaryData, message.data() + endPos + 1, binaryDataSize); + } + result = RunEndpointFunction(fn, token, j["params"], binaryData, binaryDataSize); + delete[] binaryData; + } + + string_view resultStr(result->data(), result->size()); + +// cout << "Result: " << resultStr << endl; + + if (!resultStr.empty()) + { + ws->send(resultStr, uWS::BINARY, (resultStr.length() > 512)); + } + + delete result; + } + catch (const exception &e) + { + LOGError("CDebuggerServerWebSockets: invalid JSON format %s", e.what()); + LOGError("CDebuggerServerWebSockets: json=%s", jsonStr.c_str()); + json j; + j["status"] = HTTP_BAD_REQUEST; + j["error"] = e.what(); + ws->send(j.dump(), uWS::TEXT); + } + }, + .close = [this](auto* ws, int code, string_view message) + { + numConnectedClients--; + LOGD("WebSocket connection closed (numConnectedClients=%d)", numConnectedClients); + } + }); + + LOGD("CDebuggerServerWebSockets: run"); + serverStarted = true; + app->run(); + + LOGM("WebSockets debugger server shutdown"); + delete app; + app = NULL; + serverStarted = false; +} + +void CDebuggerServerWebSockets::AddEndpointFunction(const string& functionName, function*(const string, const json, u8 *, int)> func) +{ + endpointFunctions[functionName] = func; +} + +vector *CDebuggerServerWebSockets::RunEndpointFunction(const string& functionName, const string token, json params, u8 *binaryData, int binaryDataSize) +{ + auto it = endpointFunctions.find(functionName); + if (it != endpointFunctions.end()) + { + // Execute the lambda associated with the endpoint + return it->second(token, params, binaryData, binaryDataSize); + } + else + { + LOGError("CDebuggerServerWebSockets::RunEndpoint: endpoint %s not found", functionName.c_str()); + return new vector(); + } +} + +vector *CDebuggerServerWebSockets::PrepareResult(int status, const string token, json resultJson, u8 *binaryData, int binaryDataSize) +{ + LOGD("CDebuggerServerWebSockets::PrepareResult"); + json sendJson; + sendJson["status"] = status; + if (!token.empty()) + { + sendJson["token"] = token; + } + if (!resultJson.empty()) + { + sendJson["result"] = resultJson; + } + + string sendJsonStr = sendJson.dump(); + + vector *outBuffer = new vector(); + outBuffer->reserve(sendJsonStr.length() + binaryDataSize + 2); + + outBuffer->insert(outBuffer->end(), sendJsonStr.begin(), sendJsonStr.end()); + + if (binaryData) + { + outBuffer->push_back(0); + outBuffer->insert(outBuffer->end(), binaryData, binaryData + binaryDataSize); + } + + return outBuffer; +} + +void CDebuggerServerWebSockets::BroadcastEvent(const char *eventName, nlohmann::json j) +{ + LOGD("WebSocketsDebuggerServer::BroadcastEvent"); + + j["event"] = eventName; + appLoop->defer([this, j]() + { + app->publish("broadcast", j.dump(), uWS::OpCode::TEXT); + }); +} diff --git a/src/Remote/WebSockets/CDebuggerServerWebSockets.h b/src/Remote/WebSockets/CDebuggerServerWebSockets.h new file mode 100644 index 0000000..099b024 --- /dev/null +++ b/src/Remote/WebSockets/CDebuggerServerWebSockets.h @@ -0,0 +1,44 @@ +#ifndef _CDebuggerServerWebSockets_h_ +#define _CDebuggerServerWebSockets_h_ + +#include "CDebuggerServer.h" +#include "App.h" + +class CDebugBreakpoint; + +CDebuggerServer *REMOTE_CreateDebuggerServerWebSockets(int port); + +class CDebuggerServerWebSockets : public CDebuggerServer +{ +public: + CDebuggerServerWebSockets(int port); + + virtual void Start(); + virtual void Stop(); + + bool serverStarted; + int numConnectedClients; + + virtual void AddEndpointFunction(const std::string& endpointName, std::function *(const std::string, const nlohmann::json, u8 *, int)> func); + virtual std::vector *RunEndpointFunction(const std::string& endpointName, const std::string token, nlohmann::json params, u8 *binaryData, int binaryDataSize); + virtual std::vector *PrepareResult(int status, const std::string token, nlohmann::json resultJson, u8 *binaryData, int binaryDataSize); + + virtual void ThreadRun(void *passData); + + virtual void BroadcastEvent(const char *eventName, nlohmann::json j); + + virtual bool AreClientsConnected(); + + virtual void SetPort(int port); + +private: + int port; + uWS::App *app; + uWS::Loop *appLoop; + us_listen_socket_t *listenSocket = nullptr; + std::unordered_map *(const std::string token, const nlohmann::json, u8 *, int)>> endpointFunctions; +}; + +struct SocketData {}; + +#endif diff --git a/src/Screens/CMainMenuHelper.cpp b/src/Screens/CMainMenuHelper.cpp new file mode 100644 index 0000000..61a1591 --- /dev/null +++ b/src/Screens/CMainMenuHelper.cpp @@ -0,0 +1,2335 @@ +// +// NOTE: +// This view will be removed. It is being refactored and moved to main menu bar instead +// + +#include "RES_ResourceManager.h" +#include "CSlrFileZlib.h" + +#include "CViewC64.h" +#include "CColorsTheme.h" +#include "CMainMenuHelper.h" +#include "VID_Main.h" +#include "CGuiMain.h" +#include "CSlrString.h" +#include "C64Tools.h" +#include "SYS_KeyCodes.h" +#include "CSlrKeyboardShortcuts.h" +#include "CSlrFileFromOS.h" +#include "C64D_Version.h" +#include "CDebugSymbols.h" +#include "CDebugMemory.h" +#include "C64KeyboardShortcuts.h" +#include "CViewSnapshots.h" +#include "CViewTimeline.h" +#include "CViewAbout.h" +#include "CViewDataMap.h" +#include "CViewDrive1541Browser.h" +#include "CViewKeyboardShortcuts.h" +#include "CSnapshotsManager.h" +#include "AtariAsap.h" +#include "EmulatorsConfig.h" +#include "CViewC64VicEditor.h" + +#include "CMainMenuBar.h" + +#include "CDebugInterfaceC64.h" +#include "CDebugSymbolsDrive1541.h" +#include "CDebugInterfaceAtari.h" +#include "CDebugInterfaceNes.h" + +#include "C64SettingsStorage.h" + +#include "CGuiMain.h" + +#define VIEWC64SETTINGS_OPEN_NONE 0 +#define VIEWC64SETTINGS_OPEN_FILE 1 +#define VIEWC64SETTINGS_OPEN_D64 2 +#define VIEWC64SETTINGS_OPEN_CRT 3 +#define VIEWC64SETTINGS_OPEN_PRG 4 +#define VIEWC64SETTINGS_OPEN_JUKEBOX 5 +#define VIEWC64SETTINGS_OPEN_TAPE 6 +#define VIEWC64SETTINGS_OPEN_REU 7 +#define VIEWC64SETTINGS_SAVE_REU 8 +#define VIEWC64SETTINGS_OPEN_ATR 10 +#define VIEWC64SETTINGS_OPEN_ROM 11 + +CMainMenuHelper::CMainMenuHelper(float posX, float posY, float posZ, float sizeX, float sizeY) +: CGuiView(posX, posY, posZ, sizeX, sizeY) +{ + this->name = "CViewMainMenu"; + + font = viewC64->fontCBMShifted; + fontScale = 3; + fontHeight = font->GetCharHeight('@', fontScale) + 2; + + // TODO: make generic + if (viewC64->debugInterfaceC64) + { + diskExtensions.push_back(new CSlrString("d64")); + diskExtensions.push_back(new CSlrString("x64")); + diskExtensions.push_back(new CSlrString("g64")); + diskExtensions.push_back(new CSlrString("p64")); + + cDiskExtensions.push_back("d64"); cDiskExtensions.push_back("D64"); + cDiskExtensions.push_back("x64"); cDiskExtensions.push_back("X64"); + cDiskExtensions.push_back("g64"); cDiskExtensions.push_back("G64"); + cDiskExtensions.push_back("p64"); cDiskExtensions.push_back("P64"); + + tapeExtensions.push_back(new CSlrString("tap")); + tapeExtensions.push_back(new CSlrString("t64")); + + crtExtensions.push_back(new CSlrString("crt")); + crtExtensions.push_back(new CSlrString("reu")); + + reuExtensions.push_back(new CSlrString("reu")); + reuExtensions.push_back(new CSlrString("bin")); + + // Open dialog + openFileExtensions.push_back(new CSlrString("prg")); + openFileExtensions.push_back(new CSlrString("d64")); + openFileExtensions.push_back(new CSlrString("x64")); + openFileExtensions.push_back(new CSlrString("g64")); + openFileExtensions.push_back(new CSlrString("p64")); + openFileExtensions.push_back(new CSlrString("tap")); + openFileExtensions.push_back(new CSlrString("t64")); + openFileExtensions.push_back(new CSlrString("crt")); + openFileExtensions.push_back(new CSlrString("sid")); + openFileExtensions.push_back(new CSlrString("reu")); + } + + if (viewC64->debugInterfaceAtari) + { + diskExtensions.push_back(new CSlrString("atr")); + + crtExtensions.push_back(new CSlrString("car")); + + openFileExtensions.push_back(new CSlrString("xex")); + openFileExtensions.push_back(new CSlrString("obx")); + openFileExtensions.push_back(new CSlrString("atr")); + openFileExtensions.push_back(new CSlrString("a8s")); + openFileExtensions.push_back(new CSlrString("cas")); + openFileExtensions.push_back(new CSlrString("car")); + openFileExtensions.push_back(new CSlrString("snap")); + +// ASAP supports the following file formats: SAP, CMC, CM3, CMR, CMS, DMC, DLT, FC, MPT, MPD, RMT, TMC/TM8, TM2, STIL + openFileExtensions.push_back(new CSlrString("sap")); + openFileExtensions.push_back(new CSlrString("cmc")); + openFileExtensions.push_back(new CSlrString("cm3")); + openFileExtensions.push_back(new CSlrString("cmr")); + openFileExtensions.push_back(new CSlrString("cms")); + openFileExtensions.push_back(new CSlrString("dmc")); + openFileExtensions.push_back(new CSlrString("dlt")); + openFileExtensions.push_back(new CSlrString("fc")); + openFileExtensions.push_back(new CSlrString("mpt")); + openFileExtensions.push_back(new CSlrString("mpd")); + openFileExtensions.push_back(new CSlrString("rmt")); + openFileExtensions.push_back(new CSlrString("tmc")); + openFileExtensions.push_back(new CSlrString("tm8")); + openFileExtensions.push_back(new CSlrString("tm2")); + openFileExtensions.push_back(new CSlrString("stil")); + } + + if (viewC64->debugInterfaceNes) + { + openFileExtensions.push_back(new CSlrString("nes")); + } + + openFileExtensions.push_back(new CSlrString("c64jukebox")); + openFileExtensions.push_back(new CSlrString("json")); + openFileExtensions.push_back(new CSlrString("snap")); + openFileExtensions.push_back(new CSlrString("vsf")); + openFileExtensions.push_back(new CSlrString("rtdl")); + openFileExtensions.push_back(new CSlrString("rdtl")); + + // jukebox + jukeboxExtensions.push_back(new CSlrString("c64jukebox")); + jukeboxExtensions.push_back(new CSlrString("json")); + + // roms + romsFileExtensions.push_back(new CSlrString("rom")); + romsFileExtensions.push_back(new CSlrString("bin")); + + + /// colors + tr = viewC64->colorsTheme->colorTextR; + tg = viewC64->colorsTheme->colorTextG; + tb = viewC64->colorsTheme->colorTextB; + +} + +CMainMenuHelper::~CMainMenuHelper() +{ +} + + +void CMainMenuHelper::OpenDialogInsertD64() +{ + LOGM("OpenDialogInsertD64"); + openDialogFunction = VIEWC64SETTINGS_OPEN_D64; + + CSlrString *windowTitle = new CSlrString("Open D64 disk image"); + windowTitle->DebugPrint("windowTitle="); + viewC64->ShowDialogOpenFile(this, &diskExtensions, c64SettingsDefaultD64Folder, windowTitle); + delete windowTitle; +} + +void CMainMenuHelper::OpenDialogInsertATR() +{ + LOGM("OpenDialogInsertATR"); + openDialogFunction = VIEWC64SETTINGS_OPEN_ATR; + + CSlrString *windowTitle = new CSlrString("Open ATR disk image"); + windowTitle->DebugPrint("windowTitle="); + viewC64->ShowDialogOpenFile(this, &diskExtensions, c64SettingsDefaultATRFolder, windowTitle); + delete windowTitle; +} + +void CMainMenuHelper::OpenDialogInsertCartridge() +{ + LOGM("OpenDialogInsertCartridge"); + openDialogFunction = VIEWC64SETTINGS_OPEN_CRT; + + CSlrString *windowTitle = new CSlrString("Open CRT cartridge image"); + viewC64->ShowDialogOpenFile(this, &crtExtensions, c64SettingsDefaultCartridgeFolder, windowTitle); + delete windowTitle; +} + +void CMainMenuHelper::OpenDialogInsertAtariCartridge() +{ + LOGM("OpenDialogInsertCartridge"); + openDialogFunction = VIEWC64SETTINGS_OPEN_ROM; + + CSlrString *windowTitle = new CSlrString("Open CAR cartridge image"); + viewC64->ShowDialogOpenFile(this, &crtExtensions, c64SettingsDefaultCartridgeFolder, windowTitle); + delete windowTitle; +} + +void CMainMenuHelper::OpenDialogInsertTape() +{ + LOGM("OpenDialogInsertTape"); + openDialogFunction = VIEWC64SETTINGS_OPEN_TAPE; + + CSlrString *windowTitle = new CSlrString("Open tape image"); + windowTitle->DebugPrint("windowTitle="); + viewC64->ShowDialogOpenFile(this, &tapeExtensions, c64SettingsDefaultTAPFolder, windowTitle); + delete windowTitle; +} + +void CMainMenuHelper::OpenDialogAttachReu() +{ + LOGM("OpenDialogAttachReu"); + openDialogFunction = VIEWC64SETTINGS_OPEN_REU; + + CSlrString *windowTitle = new CSlrString("Open REU image"); + windowTitle->DebugPrint("windowTitle="); + viewC64->ShowDialogOpenFile(this, &reuExtensions, c64SettingsDefaultReuFolder, windowTitle); + delete windowTitle; +} + +void CMainMenuHelper::OpenDialogSaveReu() +{ + LOGM("OpenDialogSaveReu"); + openDialogFunction = VIEWC64SETTINGS_OPEN_REU; + + CSlrString *windowTitle = new CSlrString("Save REU image"); + windowTitle->DebugPrint("windowTitle="); + CSlrString *defaultFileName = new CSlrString("image"); + viewC64->ShowDialogSaveFile(this, &reuExtensions, defaultFileName, c64SettingsDefaultReuFolder, windowTitle); + delete windowTitle; +} + +void CMainMenuHelper::OpenDialogOpenFile() +{ + LOGM("OpenDialogOpenFile"); + openDialogFunction = VIEWC64SETTINGS_OPEN_FILE; + + CSlrString *defaultFolder = viewC64->recentlyOpenedFiles->GetCurrentOpenedFolder(); + CSlrString *windowTitle = new CSlrString("Open file"); + viewC64->ShowDialogOpenFile(this, &openFileExtensions, defaultFolder, windowTitle); + delete defaultFolder; + delete windowTitle; +} + +void CMainMenuHelper::OpenDialogStartJukeboxPlaylist() +{ + LOGM("OpenDialogStartJukeboxPlaylist"); + openDialogFunction = VIEWC64SETTINGS_OPEN_JUKEBOX; + + CSlrString *windowTitle = new CSlrString("Start JukeBox playlist"); + windowTitle->DebugPrint("windowTitle="); + viewC64->ShowDialogOpenFile(this, &jukeboxExtensions, c64SettingsDefaultD64Folder, windowTitle); + delete windowTitle; +} + +void CMainMenuHelper::SystemDialogFileOpenSelected(CSlrString *path) +{ + LOGM("CViewMainMenu::SystemDialogFileOpenSelected, path=%x", path); + path->DebugPrint("path="); + + if (openDialogFunction == VIEWC64SETTINGS_OPEN_D64) + { + InsertD64(path, true, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + C64DebuggerStoreSettings(); + } + else if (openDialogFunction == VIEWC64SETTINGS_OPEN_TAPE) + { + LoadTape(path, false, true, true); + C64DebuggerStoreSettings(); + } + else if (openDialogFunction == VIEWC64SETTINGS_OPEN_CRT) + { + InsertCartridge(path, true); + C64DebuggerStoreSettings(); + } + else if (openDialogFunction == VIEWC64SETTINGS_OPEN_PRG) + { + LoadPRG(path, true, true, true, false); + C64DebuggerStoreSettings(); + } + else if (openDialogFunction == VIEWC64SETTINGS_OPEN_REU) + { + AttachReu(path, true, true); + C64DebuggerStoreSettings(); + } + else if (openDialogFunction == VIEWC64SETTINGS_OPEN_JUKEBOX) + { + viewC64->InitJukebox(path); + //C64DebuggerStoreSettings(); + } + + if (openDialogFunction == VIEWC64SETTINGS_OPEN_ATR) + { + InsertATR(path, true, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + C64DebuggerStoreSettings(); + } + else + { + /// + + LoadFile(path); + C64DebuggerStoreSettings(); + } + + openDialogFunction = VIEWC64SETTINGS_OPEN_NONE; +} + +void CMainMenuHelper::SystemDialogFileSaveSelected(CSlrString *path) +{ + LOGM("CViewMainMenu::SystemDialogFileSaveSelected, path=%x", path); + path->DebugPrint("path="); + + if (openDialogFunction == VIEWC64SETTINGS_SAVE_REU) + { + SaveReu(path, true, true); + C64DebuggerStoreSettings(); + } + + openDialogFunction = VIEWC64SETTINGS_OPEN_NONE; +} + +void CMainMenuHelper::SystemDialogFileSaveCancelled() +{ +} + +// TODO: refactor and move me to.... / in progress make a generic file opener +void CMainMenuHelper::LoadFile(CSlrString *path) +{ + LOGM("CViewMainMenu::LoadFile:"); + path->DebugPrint(); + + bool loaded = false; + + viewC64->recentlyOpenedFiles->Add(path); + + CSlrString *ext = path->GetFileExtensionComponentFromPath(); + ext->ConvertToLowerCase(); + + LOGD("ext="); + ext->DebugPrint(); + + // c64 file formats + if (ext->CompareWith("prg")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceC64); + loaded = LoadPRG(path, true, true, true, false); + } + else if (ext->CompareWith("d64") || + ext->CompareWith("x64") || + ext->CompareWith("g64") || + ext->CompareWith("p64")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceC64); + loaded = InsertD64(path, true, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + } + else if (ext->CompareWith("crt")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceC64); + loaded = InsertCartridge(path, true); + } + else if (ext->CompareWith("reu")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceC64); + bool val = true; + C64DebuggerSetSetting("ReuEnabled", &val); + loaded = AttachReu(path, true, true); + } + else if (ext->CompareWith("sid")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceC64); + loaded = LoadSID(path); + } + else if (ext->CompareWith("snap") || + ext->CompareWith("vsf")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceC64); + viewC64->viewC64Snapshots->LoadSnapshot(path, true, viewC64->debugInterfaceC64); + loaded = true; + } + else if (ext->CompareWith("tap") || + ext->CompareWith("t64")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceC64); + loaded = LoadTape(path, true, true, true); + } + + // Atari formats + else if (ext->CompareWith("xex") + || ext->CompareWith("obx")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceAtari); + loaded = LoadXEX(path, true, true, true); + } + else if (ext->CompareWith("atr")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceAtari); + loaded = InsertATR(path, true, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + } + else if (ext->CompareWith("a8s")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceAtari); + viewC64->viewAtariSnapshots->LoadSnapshot(path, true, viewC64->debugInterfaceAtari); + loaded = true; + } + // ASAP supports the following file formats: SAP, CMC, CM3, CMR, CMS, DMC, DLT, FC, MPT, MPD, RMT, TMC/TM8, TM2, STIL + // TODO: we *really* need to have a generic file opener class to parse such things out of here + else if (ext->CompareWith("sap") + || ext->CompareWith("cmc") + || ext->CompareWith("cm3") + || ext->CompareWith("cmr") + || ext->CompareWith("cms") + || ext->CompareWith("dmc") + || ext->CompareWith("dlt") + || ext->CompareWith("fc") + || ext->CompareWith("mpt") + || ext->CompareWith("mpd") + || ext->CompareWith("rmt") + || ext->CompareWith("tmc") + || ext->CompareWith("tm8") + || ext->CompareWith("tm2") + || ext->CompareWith("stil")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceAtari); + loaded = LoadASAP(path); + } + + // NES file formats + else if (ext->CompareWith("nes")) + { + viewC64->StartEmulationThread(viewC64->debugInterfaceNes); + loaded = LoadNES(path, true); + } + + // other formats + else if (ext->CompareWith("c64jukebox") || + ext->CompareWith("json")) + + { + viewC64->InitJukebox(path); + loaded = true; + } + else if (ext->CompareWith("rtdl") || ext->CompareWith("rdtl")) + { + CViewTimeline::LoadTimeline(path); + loaded = true; + } + + if (loaded == false) + { + viewC64->viewVicEditor->ImportImage(path); + } + + viewC64->ShowMainScreen(); + + delete ext; + + viewC64->DefaultSymbolsRestore(); +} + +bool CMainMenuHelper::InsertD64(CSlrString *path, bool updatePathToD64, bool autoRun, int autoRunEntryNum, bool showLoadAddressInfo) +{ + LOGD("CViewMainMenu::InsertD64: path=%x autoRun=%s autoRunEntryNum=%d", path, STRBOOL(autoRun), autoRunEntryNum); + path->DebugPrint("CViewMainMenu::InsertD64: path="); + + guiMain->LockMutex(); + if (SYS_FileExists(path) == false) + { + if (c64SettingsPathToD64 != NULL) + delete c64SettingsPathToD64; + + c64SettingsPathToD64 = NULL; + LOGError("InsertD64: file not found, skipping"); + + if (showLoadAddressInfo) + { + guiMain->ShowMessageBox("Error", "Unable to open the D64 file. Please check its location, permissions, and ensure it's a valid format."); + } + guiMain->UnlockMutex(); + return false; + } + + if (c64SettingsPathToD64 != path) + { + if (c64SettingsPathToD64 != NULL) + delete c64SettingsPathToD64; + c64SettingsPathToD64 = new CSlrString(path); + } + + if (updatePathToD64) + { + LOGD("...updatePathToD64"); + if (c64SettingsDefaultD64Folder != NULL) + delete c64SettingsDefaultD64Folder; + c64SettingsDefaultD64Folder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultD64Folder->DebugPrint("c64SettingsDefaultD64Folder="); + } + C64DebuggerStoreSettings(); + + // insert D64 + viewC64->debugInterfaceC64->InsertD64(path); + + + // TODO: support UTF paths + char *asciiPath = path->GetStdASCII(); + + // display file name in menu + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + viewC64->ShowMessage("Inserted %s", fname); + +// if (menuItemInsertD64->str2 != NULL) +// delete menuItemInsertD64->str2; +// menuItemInsertD64->str2 = new CSlrString(fname); +// delete [] fname; + + LOGM("Inserted new d64: %s", asciiPath); + delete [] asciiPath; + + viewC64->viewDrive1541Browser->StartSelectedDiskImageBrowsing(); + + if (autoRun) + { + viewC64->viewDrive1541Browser->StartDiskPRGEntry(autoRunEntryNum, showLoadAddressInfo); + } + + guiMain->UnlockMutex(); + + return true; +} + +// insert next D64 from the same folder +void CMainMenuHelper::InsertNextD64() +{ + LOGM("CViewMainMenu::InsertNextD64"); + if (SYS_FileExists(c64SettingsPathToD64) == false) + { + if (c64SettingsPathToD64 != NULL) + delete c64SettingsPathToD64; + + c64SettingsPathToD64 = NULL; + LOGError("InsertNextD64: file not found, skipping"); + return; + } + + char *asciiPath = c64SettingsPathToD64->GetStdASCII(); + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + char *fpath = SYS_GetPathFromFullPath(asciiPath); + LOGD("..fname=%s fpath=%s", fname, fpath); + + std::vector *filesInFolder = SYS_GetFilesInFolder(fpath, &cDiskExtensions); + + // find current file, and then insert next + for (std::vector::iterator it = filesInFolder->begin(); it != filesInFolder->end(); it++) + { + CFileItem *file = *it; + + LOGD("...%s", file->name); + if (!strcmp(file->name, fname)) + { + LOGD("FOUND!"); + + it++; + if (it == filesInFolder->end()) + { + it = filesInFolder->begin(); + } + + CFileItem *nextFile = *it; + CSlrString *nextFilePath = new CSlrString(); + nextFilePath->Concatenate(fpath); + nextFilePath->Concatenate(nextFile->name); + + nextFilePath->DebugPrint("nextFilePath="); + + InsertD64(nextFilePath, false, false, -1, false); + + char *buf = SYS_GetCharBuf(); + sprintf(buf, "Inserted %s", nextFile->name); + viewC64->ShowMessage(buf); + + delete nextFilePath; + break; + } + } + + while(!filesInFolder->empty()) + { + CFileItem *f = filesInFolder->back(); + filesInFolder->pop_back(); + delete f; + } + delete filesInFolder; + + LOGD("CViewMainMenu::InsertNextD64: done"); +} + +bool CMainMenuHelper::AttachReu(CSlrString *path, bool updatePathToReu, bool showDetails) +{ + LOGD("CViewMainMenu::AttachReu: path=%x"); + + if (SYS_FileExists(path) == false) + { + if (c64SettingsPathToReu != NULL) + delete c64SettingsPathToReu; + + c64SettingsPathToReu = NULL; + LOGError("AttachReu: file not found, skipping"); + return false; + } + + if (c64SettingsPathToReu != path) + { + if (c64SettingsPathToReu != NULL) + delete c64SettingsPathToReu; + c64SettingsPathToReu = new CSlrString(path); + } + + if (updatePathToReu) + { + LOGD("...updatePathToReu"); + if (c64SettingsDefaultReuFolder != NULL) + delete c64SettingsDefaultReuFolder; + c64SettingsDefaultReuFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultReuFolder->DebugPrint("c64SettingsDefaultReuFolder="); + } + C64DebuggerStoreSettings(); + + // insert REU + char *asciiPath = c64SettingsPathToReu->GetStdASCII(); + + bool ret = viewC64->debugInterfaceC64->LoadReu(asciiPath); + + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + + LOGM("%s REU: %s", (ret ? "Attached" : "Failed to attach"), asciiPath); + delete [] asciiPath; + + if (showDetails) + { + char *buf = SYS_GetCharBuf(); + sprintf(buf, "%s REU: %s", (ret ? "Attached" : "Failed to attach"), fname); + viewC64->ShowMessage(buf); + SYS_ReleaseCharBuf(buf); + } + + delete [] fname; + + return ret; +} + +bool CMainMenuHelper::SaveReu(CSlrString *path, bool updatePathToReu, bool showDetails) +{ + LOGD("CViewMainMenu::SaveReu: path=%x"); + + if (updatePathToReu) + { + LOGD("...updatePathToReu"); + if (c64SettingsPathToReu != path) + { + if (c64SettingsPathToReu != NULL) + delete c64SettingsPathToReu; + c64SettingsPathToReu = new CSlrString(path); + } + + if (c64SettingsDefaultReuFolder != NULL) + delete c64SettingsDefaultReuFolder; + c64SettingsDefaultReuFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultReuFolder->DebugPrint("c64SettingsDefaultReuFolder="); + C64DebuggerStoreSettings(); + } + + // save REU + char *asciiPath = c64SettingsPathToReu->GetStdASCII(); + + bool ret = viewC64->debugInterfaceC64->SaveReu(asciiPath); + + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + + LOGM("%s REU: %s", (ret ? "Saved" : "Failed to save"), asciiPath); + delete [] asciiPath; + + if (showDetails) + { + char *buf = SYS_GetCharBuf(); + sprintf(buf, "%s REU: %s", (ret ? "Saved" : "Failed to save"), fname); + viewC64->ShowMessage(buf); + SYS_ReleaseCharBuf(buf); + } + + delete [] fname; + + return true; +} + +bool CMainMenuHelper::InsertCartridge(CSlrString *path, bool updatePathToCRT) +{ + path->DebugPrint("CViewMainMenu::InsertCartridge, path="); + + guiMain->LockMutex(); + debugInterfaceVice->LockIoMutex(); + + if (SYS_FileExists(path) == false) + { + if (c64SettingsPathToCartridge != NULL) + delete c64SettingsPathToCartridge; + + c64SettingsPathToCartridge = NULL; + LOGError("CViewMainMenu::InsertCartridge: file not found, skipping"); + + debugInterfaceVice->UnlockIoMutex(); + guiMain->UnlockMutex(); + return false; + } + + if (c64SettingsPathToCartridge != path) + { + if (c64SettingsPathToCartridge != NULL) + delete c64SettingsPathToCartridge; + c64SettingsPathToCartridge = new CSlrString(path); + } + + if (updatePathToCRT) + { + LOGD("...updatePathToCRT"); + if (c64SettingsDefaultCartridgeFolder != NULL) + delete c64SettingsDefaultCartridgeFolder; + c64SettingsDefaultCartridgeFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultCartridgeFolder->DebugPrint("strDefaultCartridgeFolder="); + } + C64DebuggerStoreSettings(); + + // insert CRT + viewC64->debugInterfaceC64->AttachCartridge(path); + + LoadLabelsAndWatches(path, viewC64->debugInterfaceC64); + + // TODO: support UTF paths + char *asciiPath = c64SettingsPathToCartridge->GetStdASCII(); + + // display file name in menu + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + + +// if (menuItemInsertCartridge->str2 != NULL) +// delete menuItemInsertCartridge->str2; +// menuItemInsertCartridge->str2 = new CSlrString(fname); +// delete [] fname; + + LOGM("Attached new cartridge: %s", asciiPath); + delete [] asciiPath; + + C64DebuggerStoreSettings(); + + debugInterfaceVice->UnlockIoMutex(); + guiMain->UnlockMutex(); + return true; +} + +bool CMainMenuHelper::LoadPRG(CSlrString *path, bool autoStart, bool updatePRGFolderPath, bool showAddressInfo, bool forceFastReset) +{ + path->DebugPrint("CViewMainMenu::LoadPRG: path="); + + guiMain->LockMutex(); + debugInterfaceVice->LockIoMutex(); + + viewC64->DefaultSymbolsStore(); + + LOGD(" >>> LoadPRG, autostart=%d forceFastReset=%d", autoStart, forceFastReset); + + // TODO: p00 http://vice-emu.sourceforge.net/vice_15.html#SEC299 + + if (c64SettingsPathToPRG != path) + { + if (c64SettingsPathToPRG != NULL) + delete c64SettingsPathToPRG; + c64SettingsPathToPRG = new CSlrString(path); + } + + if (updatePRGFolderPath) + { + LOGD("...updatePRGFolderPath"); + if (c64SettingsDefaultPRGFolder != NULL) + delete c64SettingsDefaultPRGFolder; + c64SettingsDefaultPRGFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultPRGFolder->DebugPrint("c64SettingsDefaultPRGFolder="); + } + C64DebuggerStoreSettings(); + + LOGD("... LoadPRG (2)"); + + c64SettingsPathToPRG->DebugPrint("c64SettingsPathToPRG="); + + // TODO: make CSlrFileFromOS support UTF paths + char *asciiPath = c64SettingsPathToPRG->GetStdASCII(); + + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading PRG file, no such file path:\n%s", asciiPath); + debugInterfaceVice->UnlockIoMutex(); + guiMain->UnlockMutex(); + return false; + } + + // display file name in menu + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + +// guiMain->LockMutex(); + +// if (menuItemOpenFile->str2 != NULL) +// delete menuItemOpenFile->str2; +// menuItemOpenFile->str2 = new CSlrString(fname); +// delete [] fname; + + viewC64->debugInterfaceC64->LockMutex(); + LoadLabelsAndWatches(path, viewC64->debugInterfaceC64); + viewC64->debugInterfaceC64->UnlockMutex(); + + viewC64->DefaultSymbolsRestore(); + +// guiMain->UnlockMutex(); + + // + CByteBuffer *byteBuffer = new CByteBuffer(file, false); + LoadPRG(byteBuffer, autoStart, showAddressInfo, forceFastReset); + + delete [] asciiPath; + delete file; + + delete byteBuffer; + + C64DebuggerStoreSettings(); + + debugInterfaceVice->UnlockIoMutex(); + guiMain->UnlockMutex(); + + return true; +} + +bool CMainMenuHelper::LoadSID(CSlrString *filePath) +{ + if (viewC64->debugInterfaceC64 == NULL) + return false; + + filePath->DebugPrint("CViewMainMenu::LoadSID: path="); + + viewC64->DefaultSymbolsStore(); + + // TODO: make CSlrFileFromOS support UTF paths + char *asciiPath = filePath->GetStdASCII(); + + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading SID file, no such file path:\n%s", asciiPath); + return false; + } + + if (c64SettingsC64SidImportMode == SID_IMPORT_MODE_PSID64) + { + CByteBuffer *byteBufferSID = new CByteBuffer(file, false); + CByteBuffer *byteBufferPRG = ConvertSIDtoPRG(byteBufferSID); + + if (byteBufferPRG != NULL) + { + LoadPRG(byteBufferPRG, true, false, true); + delete byteBufferPRG; + } + else + { + viewC64->ShowMessageError("Failed to import SID"); + } + + delete byteBufferSID; + } + else if (c64SettingsC64SidImportMode == SID_IMPORT_MODE_DIRECT_COPY) + { + u16 fromAddr; + u16 toAddr; + u16 initAddr; + u16 playAddr; + C64LoadSIDToRam(asciiPath, &fromAddr, &toAddr, &initAddr, &playAddr); + + char *buf = SYS_GetCharBuf(); + sprintf(buf, "SID from $%04X to $%04X. Init $%04X Play $%04X.", fromAddr, toAddr, initAddr, playAddr); + viewC64->ShowMessage(buf); + SYS_ReleaseCharBuf(buf); + } + + delete asciiPath; + delete file; + + viewC64->DefaultSymbolsRestore(); + + return true; + +} + + +extern "C" { + int tape_image_attach(unsigned int unit, const char *name); + int tape_image_detach(unsigned int unit); +} + + +bool CMainMenuHelper::LoadTape(CSlrString *path, bool autoStart, bool updateTAPFolderPath, bool showAddressInfo) +{ + path->DebugPrint("CViewMainMenu::LoadTape: path="); + + guiMain->LockMutex(); + debugInterfaceVice->LockIoMutex(); + + if (SYS_FileExists(path) == false) + { + if (c64SettingsPathToTAP != NULL) + delete c64SettingsPathToTAP; + + c64SettingsPathToTAP = NULL; + LOGError("CViewMainMenu::LoadTape: file not found, skipping"); + + debugInterfaceVice->UnlockIoMutex(); + guiMain->UnlockMutex(); + return false; + } + + LOGD(" >>> LoadTape, autostart=%d", autoStart); +// guiMain->LockMutex(); + + viewC64->DefaultSymbolsStore(); + + if (c64SettingsPathToTAP != path) + { + if (c64SettingsPathToTAP != NULL) + delete c64SettingsPathToTAP; + c64SettingsPathToTAP = new CSlrString(path); + } + + if (updateTAPFolderPath) + { + LOGD("...updateTAPFolderPath"); + if (c64SettingsDefaultTAPFolder != NULL) + delete c64SettingsDefaultTAPFolder; + c64SettingsDefaultTAPFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultTAPFolder->DebugPrint("c64SettingsDefaultTAPFolder="); + } + C64DebuggerStoreSettings(); + + LOGD("... LoadTAP (2)"); + + c64SettingsPathToTAP->DebugPrint("c64SettingsPathToTAP="); + + // TODO: make CSlrFileFromOS support UTF paths + char *asciiPath = c64SettingsPathToTAP->GetStdASCII(); + + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading TAP file"); +// guiMain->UnlockMutex(); + + debugInterfaceVice->UnlockIoMutex(); + guiMain->UnlockMutex(); + return false; + } + + // + viewC64->debugInterfaceC64->AttachTape(c64SettingsPathToTAP); + + delete [] asciiPath; + delete file; + + char *buf = SYS_GetCharBuf(); + CSlrString *fname = c64SettingsPathToTAP->GetFileNameComponentFromPath(); + char *cName = fname->GetStdASCII(); + sprintf(buf, "Tape %s attached", cName); + viewC64->ShowMessage(buf); + delete [] cName; + SYS_ReleaseCharBuf(buf); + + // + viewC64->DefaultSymbolsRestore(); + +// guiMain->UnlockMutex(); + + debugInterfaceVice->UnlockIoMutex(); + guiMain->UnlockMutex(); + + return true; +} + +bool CMainMenuHelper::LoadXEX(CSlrString *path, bool autoStart, bool updateXEXFolderPath, bool showAddressInfo) +{ + path->DebugPrint("CViewMainMenu::LoadXEX: path="); + + LOGD(" >>> LoadXEX, autostart=%d", autoStart); + + viewC64->DefaultSymbolsStore(); + + if (c64SettingsPathToXEX != path) + { + if (c64SettingsPathToXEX != NULL) + delete c64SettingsPathToXEX; + c64SettingsPathToXEX = new CSlrString(path); + } + + if (updateXEXFolderPath) + { + LOGD("...updateXEXFolderPath"); + if (c64SettingsDefaultXEXFolder != NULL) + delete c64SettingsDefaultXEXFolder; + c64SettingsDefaultXEXFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultXEXFolder->DebugPrint("c64SettingsDefaultXEXFolder="); + } + C64DebuggerStoreSettings(); + + LOGD("... LoadXEX (2)"); + + c64SettingsPathToXEX->DebugPrint("c64SettingsPathToXEX="); + + // TODO: make CSlrFileFromOS support UTF paths + char *asciiPath = c64SettingsPathToXEX->GetStdASCII(); + + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading XEX file"); + if (c64SettingsPathToXEX != NULL) + delete c64SettingsPathToXEX; + c64SettingsPathToXEX = NULL; + C64DebuggerStoreSettings(); + return false; + } + + // display file name in menu +// char *fname = SYS_GetFileNameFromFullPath(asciiPath); + + LOGTODO("XEX: update menu item"); + + guiMain->LockMutex(); + + /* + if (menuItemLoadPRG->str2 != NULL) + delete menuItemLoadPRG->str2; + + menuItemLoadPRG->str2 = new CSlrString(fname); + delete [] fname; + */ + + LoadLabelsAndWatches(path, viewC64->debugInterfaceAtari); + guiMain->UnlockMutex(); + + + // + debugInterfaceAtari->LockMutex(); + + if (c64SettingsResetCountersOnAutoRun) + { + debugInterfaceAtari->ResetMainCpuDebugCycleCounter(); + debugInterfaceAtari->ResetEmulationFrameCounter(); + } + debugInterfaceAtari->ClearHistory(); + + debugInterfaceAtari->LoadExecutable(asciiPath); + + + debugInterfaceAtari->UnlockMutex(); + + // + viewC64->DefaultSymbolsRestore(); + + delete asciiPath; + delete file; + + return true; +} + +bool CMainMenuHelper::LoadCAS(CSlrString *path, bool autoStart, bool updateCASFolderPath, bool showAddressInfo) +{ + path->DebugPrint("CViewMainMenu::LoadCAS: path="); + + viewC64->DefaultSymbolsStore(); + + LOGD(" >>> LoadCAS, autostart=%d", autoStart); + + if (c64SettingsPathToCAS != path) + { + if (c64SettingsPathToCAS != NULL) + delete c64SettingsPathToCAS; + c64SettingsPathToCAS = new CSlrString(path); + } + + if (updateCASFolderPath) + { + LOGD("...updateCASFolderPath"); + if (c64SettingsDefaultCASFolder != NULL) + delete c64SettingsDefaultCASFolder; + c64SettingsDefaultCASFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultCASFolder->DebugPrint("c64SettingsDefaultCASFolder="); + } + C64DebuggerStoreSettings(); + + LOGD("... LoadCAS (2)"); + + c64SettingsPathToCAS->DebugPrint("c64SettingsPathToCAS="); + + // TODO: make CSlrFileFromOS support UTF paths + char *asciiPath = c64SettingsPathToCAS->GetStdASCII(); + + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading CAS file"); + return false; + } + + // display file name in menu +// char *fname = SYS_GetFileNameFromFullPath(asciiPath); + LOGTODO("CAS: load labels/symbols/watches & update menu item"); + + /* + guiMain->LockMutex(); + if (menuItemLoadPRG->str2 != NULL) + delete menuItemLoadPRG->str2; + + menuItemLoadPRG->str2 = new CSlrString(fname); + delete [] fname; + + LoadLabelsAndWatches(path); + guiMain->UnlockMutex(); + + */ + + // + debugInterfaceAtari->LockMutex(); + viewC64->debugInterfaceAtari->AttachTape(asciiPath, false); + debugInterfaceAtari->UnlockMutex(); + + delete asciiPath; + delete file; + + viewC64->DefaultSymbolsRestore(); + + return true; +} + +bool CMainMenuHelper::InsertAtariCartridge(CSlrString *path, bool autoStart, bool updateAtariCartridgeFolderPath, bool showAddressInfo) +{ + path->DebugPrint("CViewMainMenu::LoadAtariCartridge: path="); + + viewC64->DefaultSymbolsStore(); + + LOGD(" >>> LoadAtariCartridge, autostart=%d", autoStart); + + if (c64SettingsPathToAtariCartridge != path) + { + if (c64SettingsPathToAtariCartridge != NULL) + delete c64SettingsPathToAtariCartridge; + c64SettingsPathToAtariCartridge = new CSlrString(path); + } + + if (updateAtariCartridgeFolderPath) + { + LOGD("...updateAtariCartridgeFolderPath"); + if (c64SettingsDefaultAtariCartridgeFolder != NULL) + delete c64SettingsDefaultAtariCartridgeFolder; + c64SettingsDefaultAtariCartridgeFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultAtariCartridgeFolder->DebugPrint("c64SettingsDefaultAtariCartridgeFolder="); + } + C64DebuggerStoreSettings(); + + LOGD("... LoadAtariCartridge (2)"); + + c64SettingsPathToAtariCartridge->DebugPrint("c64SettingsPathToAtariCartridge="); + + // TODO: make CSlrFileFromOS support UTF paths + char *asciiPath = c64SettingsPathToAtariCartridge->GetStdASCII(); + + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading AtariCartridge file"); + return false; + } + + // display file name in menu + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + + guiMain->LockMutex(); + +// if (menuItemInsertAtariCartridge->str2 != NULL) +// delete menuItemInsertAtariCartridge->str2; +// menuItemInsertAtariCartridge->str2 = new CSlrString(fname); +// delete [] fname; + + LoadLabelsAndWatches(path, viewC64->debugInterfaceAtari); + guiMain->UnlockMutex(); + + // + debugInterfaceAtari->LockMutex(); + viewC64->debugInterfaceAtari->InsertCartridge(asciiPath, false); + debugInterfaceAtari->UnlockMutex(); + + delete asciiPath; + delete file; + + viewC64->DefaultSymbolsRestore(); + + return true; +} + +// +bool CMainMenuHelper::InsertATR(CSlrString *path, bool updatePathToATR, bool autoRun, int autoRunEntryNum, bool showLoadAddressInfo) +{ + LOGD("CViewMainMenu::InsertATR: path=%x autoRun=%s autoRunEntryNum=%d", path, STRBOOL(autoRun), autoRunEntryNum); + + viewC64->DefaultSymbolsStore(); + + if (SYS_FileExists(path) == false) + { + if (c64SettingsPathToATR != NULL) + delete c64SettingsPathToATR; + + c64SettingsPathToATR = NULL; + LOGError("InsertATR: file not found, skipping"); + return false; + } + + if (c64SettingsPathToATR != path) + { + if (c64SettingsPathToATR != NULL) + delete c64SettingsPathToATR; + c64SettingsPathToATR = new CSlrString(path); + } + + if (updatePathToATR) + { + LOGD("...updatePathToATR"); + if (c64SettingsDefaultATRFolder != NULL) + delete c64SettingsDefaultATRFolder; + c64SettingsDefaultATRFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultATRFolder->DebugPrint("c64SettingsDefaultATRFolder="); + } + C64DebuggerStoreSettings(); + + char *asciiPath = c64SettingsPathToATR->GetStdASCII(); + + debugInterfaceAtari->LockMutex(); + + // insert ATR + viewC64->debugInterfaceAtari->MountDisk(asciiPath, 0, false); + + debugInterfaceAtari->UnlockMutex(); + + // display file name in menu + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + + guiMain->LockMutex(); + +// if (menuItemInsertATR->str2 != NULL) +// delete menuItemInsertATR->str2; +// menuItemInsertATR->str2 = new CSlrString(fname); +// delete [] fname; + + guiMain->UnlockMutex(); + + LOGM("Inserted new ATR: %s", asciiPath); + delete asciiPath; + +// if (guiMain->currentView == viewC64->viewFileD64) +// viewC64->viewFileD64->StartSelectedDiskImageBrowsing(); +// +// if (autoRun) +// { +// viewC64->viewFileD64->StartDiskPRGEntry(autoRunEntryNum, showLoadAddressInfo); +// } + + viewC64->DefaultSymbolsRestore(); + return true; +} + +bool CMainMenuHelper::LoadASAP(CSlrString *filePath) +{ +// bool LoadXEX(CSlrString *path, bool autoStart, bool updatePRGFolderPath, bool showAddressInfo); + + if (viewC64->debugInterfaceAtari == NULL) + return false; + + filePath->DebugPrint("CViewMainMenu::LoadASAP: path="); + + viewC64->DefaultSymbolsStore(); + + // TODO: make CSlrFileFromOS support UTF paths + char *asciiPath = filePath->GetStdASCII(); + + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading ASAP file, no such file path:\n%s", asciiPath); + return false; + } + + LOGD("... LoadASAP: converting to XEX"); + + CByteBuffer *asapBuffer = new CByteBuffer(file); + delete file; + + bool isStereo; + CByteBuffer *xexBuffer = ConvertASAPtoXEX(asciiPath, asapBuffer, &isStereo); + delete asapBuffer; + STRFREE(asciiPath); + + if (xexBuffer == NULL) + { + viewC64->ShowMessageError("Error loading ASAP file, conversion to XEX failed"); + return false; + } + + // TODO: Does Atari800 support loading XEX file directly from memory buffer? Can't find that... we need a temp file for now + char *xexTempFilePath = SYS_GetCharBuf(); + sprintf(xexTempFilePath, "%s%casap-temp.xex", gPathToTemp, SYS_FILE_SYSTEM_PATH_SEPARATOR); + LOGD("CViewMainMenu::LoadASAP: xexTempFilePath=%s", xexTempFilePath); + xexBuffer->storeToFile(xexTempFilePath); + delete xexBuffer; + + // set stereo + debugInterfaceAtari->SetPokeyStereo(isStereo); + + // load xex + debugInterfaceAtari->LockMutex(); + + if (c64SettingsResetCountersOnAutoRun) + { + debugInterfaceAtari->ResetMainCpuDebugCycleCounter(); + debugInterfaceAtari->ResetEmulationFrameCounter(); + } + debugInterfaceAtari->ClearHistory(); + + debugInterfaceAtari->LoadExecutable(xexTempFilePath); + + debugInterfaceAtari->UnlockMutex(); + + // + viewC64->DefaultSymbolsRestore(); + + SYS_ReleaseCharBuf(xexTempFilePath); + return true; +} + +bool CMainMenuHelper::LoadNES(CSlrString *path, bool updateNESFolderPath) +{ + if (path == NULL) + return false; + + path->DebugPrint("CViewMainMenu::LoadNES: path="); + + viewC64->DefaultSymbolsStore(); + + LOGD(" >>> LoadNES"); + + if (c64SettingsPathToNES != path) + { + if (c64SettingsPathToNES != NULL) + delete c64SettingsPathToNES; + c64SettingsPathToNES = new CSlrString(path); + } + + if (updateNESFolderPath) + { + LOGD("...updateNESFolderPath"); + if (c64SettingsDefaultNESFolder != NULL) + delete c64SettingsDefaultNESFolder; + c64SettingsDefaultNESFolder = path->GetFilePathWithoutFileNameComponentFromPath(); + + c64SettingsDefaultNESFolder->DebugPrint("c64SettingsDefaultNESFolder="); + } + C64DebuggerStoreSettings(); + + LOGD("... LoadNES (2)"); + + c64SettingsPathToNES->DebugPrint("c64SettingsPathToNES="); + + // TODO: make CSlrFileFromOS support UTF paths + char *asciiPath = c64SettingsPathToNES->GetStdASCII(); + + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading NES file"); + return false; + } + + // display file name in menu + char *fname = SYS_GetFileNameWithExtensionFromFullPath(asciiPath); + + guiMain->LockMutex(); + +// if (menuItemOpenFile->str2 != NULL) +// delete menuItemOpenFile->str2; +// menuItemOpenFile->str2 = new CSlrString(fname); +// delete [] fname; + + LOGTODO("NES: load labels/symbols/watches"); +// LoadLabelsAndWatches(path); + + guiMain->UnlockMutex(); + + // + debugInterfaceNes->LockMutex(); + viewC64->debugInterfaceNes->InsertCartridge(asciiPath); + + if (c64SettingsResetCountersOnAutoRun) + { + viewC64->debugInterfaceNes->ResetEmulationFrameCounter(); + viewC64->debugInterfaceNes->ResetMainCpuDebugCycleCounter(); + } + + debugInterfaceNes->UnlockMutex(); + + delete asciiPath; + delete file; + + viewC64->DefaultSymbolsRestore(); + + return true; +} + + + +void CMainMenuHelper::LoadLabelsAndWatches(CSlrString *path, CDebugInterface *debugInterface) +{ + LOGM("CViewMainMenu::LoadLabelsAndWatches, emulator type=%d", debugInterface->GetEmulatorType()); + path->DebugPrint("path="); + + CSlrString *fPath = path->GetFilePathWithoutExtension(); + char *noExtPath = fPath->GetStdASCII(); + char *buf = SYS_GetCharBuf(); + + // check for labels + if (c64SettingsLoadViceLabels) + { + char *buf = SYS_GetCharBuf(); + sprintf(buf, "%s.labels", noExtPath); + + LOGD("...searching for labels: %s", buf); + + CSlrFileFromOS *file = new CSlrFileFromOS(buf); + if (file->Exists() == false) + { + delete file; + + sprintf(buf, "%s.vs", noExtPath); + + LOGD("...searching for labels: %s", buf); + + file = new CSlrFileFromOS(buf); + } + + if (file->Exists()) + { + debugInterface->symbols->DeleteAllSymbols(); + debugInterface->symbols->ParseSymbols(file); + } + + delete file; + } + + // check for watches + if (c64SettingsLoadWatches) + { + sprintf(buf, "%s.watch", noExtPath); + + LOGD("...searching for watches: %s", buf); + + CSlrFileFromOS *file = new CSlrFileFromOS(buf); + if (file->Exists()) + { + debugInterface->symbols->DeleteAllWatches(); + debugInterface->symbols->ParseWatches(file); + } + + delete file; + } + + // check for debug info + if (c64SettingsLoadDebugInfo) + { + sprintf(buf, "%s.dbg", noExtPath); + + LOGD("...searching for debug info: %s", buf); + + CSlrFileFromOS *file = new CSlrFileFromOS(buf); + if (file->Exists()) + { + debugInterface->symbols->DeleteAllSymbols(); + debugInterface->symbols->ParseSourceDebugInfo(file); + } + else + { + LOGError("dbg file does not exist, parsed path=%s", buf); + path->DebugPrint("error: dbg at origin path does not exist, path="); + } + + delete file; + } + + + SYS_ReleaseCharBuf(buf); + delete [] noExtPath; + delete fPath; +} + +bool CMainMenuHelper::LoadPRG(CByteBuffer *byteBuffer, bool autoStart, bool showAddressInfo, bool forceFastReset) +{ + if (viewC64->debugInterfaceC64 == NULL) + return false; + + LOGM("CViewMainMenu::LoadPRG: autoStart=%d showAddressInfo=%d c64SettingsAutoJmpDoReset=%d forceFastReset=%d", autoStart, showAddressInfo, c64SettingsAutoJmpDoReset, forceFastReset); + CByteBuffer *loadPrgByteBuffer = new CByteBuffer(byteBuffer); + this->loadPrgAutoStart = autoStart; + this->loadPrgShowAddressInfo = showAddressInfo; + this->loadPrgForceFastReset = forceFastReset; + + viewC64->debugInterfaceC64->symbols->memory->ClearDebugMarkers(); + viewC64->debugInterfaceC64->symbolsDrive1541->memory->ClearDebugMarkers(); + + if (!this->isRunning) + { + SYS_StartThread(this, (void*)loadPrgByteBuffer); + } + return true; +} + +// TODO: move LoadPRG logic to C64 Tools +void CMainMenuHelper::ThreadRun(void *data) +{ + ThreadSetName("CViewMainMenu::LoadPRG"); + + LOGD("CViewMainMenu::ThreadRun"); + + CByteBuffer *loadPrgByteBuffer = (CByteBuffer *)data; + + if (loadPrgForceFastReset) + { + // force fast reset + viewC64->debugInterfaceC64->SetDebugMode(DEBUGGER_MODE_RUNNING); + viewC64->debugInterfaceC64->SetPatchKernalFastBoot(true); + + viewC64->debugInterfaceC64->ResetHard(); + SYS_Sleep(350); + + debugInterfaceVice->PrepareDriveForBasicRun(); + + viewC64->debugInterfaceC64->SetPatchKernalFastBoot(c64SettingsFastBootKernalPatch); + + } + else + { + // do regular check, depends on user's setting + if (loadPrgAutoStart) + { + if (c64SettingsAutoJmpDoReset == MACHINE_LOADPRG_RESET_MODE_SOFT + || c64SettingsAutoJmpDoReset == MACHINE_LOADPRG_RESET_MODE_HARD) + { + viewC64->debugInterfaceC64->SetDebugMode(DEBUGGER_MODE_RUNNING); + viewC64->debugInterfaceC64->SetPatchKernalFastBoot(true); + + if (c64SettingsAutoJmpDoReset == MACHINE_LOADPRG_RESET_MODE_SOFT) + { + viewC64->debugInterfaceC64->ResetSoft(); + } + else if (c64SettingsAutoJmpDoReset == MACHINE_LOADPRG_RESET_MODE_HARD) + { + viewC64->debugInterfaceC64->ResetHard(); + } + + SYS_Sleep(c64SettingsAutoJmpWaitAfterReset); + + viewC64->viewDrive1541Browser->UpdateDriveDiskID(); + viewC64->debugInterfaceC64->SetPatchKernalFastBoot(c64SettingsFastBootKernalPatch); + } + else if (c64SettingsAutoJmpDoReset == MACHINE_LOADPRG_RESET_MODE_LOAD_SNAPSHOT_BASIC) + { + LOGD("c64SettingsAutoJmpDoReset is MACHINE_LOAD_SNAPSHOT_BASIC"); + + if (viewC64->debugInterfaceC64->GetC64ModelType() != 0) + { + viewC64->debugInterfaceC64->ForceRunAndUnJamCpu(); + int modelId = 0; + C64DebuggerSetSetting("C64Model", &modelId); + SYS_Sleep(200); + } + + viewC64->debugInterfaceC64->PauseEmulationBlockedWait(); + + guiMain->LockMutex(); + + CSlrFileZlib *fileZlib = RES_GetFileZlib("/template/reset_basic_snapshot", DEPLOY_FILE_TYPE_DATA); + u32 fileSize = fileZlib->GetFileSize(); + u8 *snapshotData = new u8[fileSize]; + fileZlib->Read(snapshotData, fileSize); + CByteBuffer *byteBuffer = new CByteBuffer(snapshotData, fileSize); + viewC64->debugInterfaceC64->LoadFullSnapshot(byteBuffer); + delete byteBuffer; + delete fileZlib; + + // be sure that snapshot is loaded, run one instruction + viewC64->debugInterfaceC64->PauseEmulationBlockedWait(); + + // and then switch to RUNNING + viewC64->debugInterfaceC64->SetDebugMode(DEBUGGER_MODE_RUNNING); + + SetupC64Defaults(); + + // and insert disk + if (c64SettingsPathToD64) + { + debugInterfaceVice->InsertD64(c64SettingsPathToD64); + } + // inserting is synched, does not need sleep here +// SYS_Sleep(50); + + viewC64->debugInterfaceC64->PauseEmulationBlockedWait(); + viewC64->debugInterfaceC64->SetDebugMode(DEBUGGER_MODE_RUNNING); + + // prepare drive RAM, set vectors etc + debugInterfaceVice->PrepareDriveForBasicRun(); + + guiMain->UnlockMutex(); + } + } + } + + LoadPRGNotThreaded(loadPrgByteBuffer, loadPrgAutoStart, loadPrgShowAddressInfo); + delete loadPrgByteBuffer; + + LOGD("CViewMainMenu::finished"); +} + +void CMainMenuHelper::SetupC64Defaults() +{ + // TODO: c64 MODEL + + // set defaults + viewC64->debugInterfaceC64->SetSidType(c64SettingsSIDEngineModel); + viewC64->debugInterfaceC64->SetSidSamplingMethod(c64SettingsRESIDSamplingMethod); + viewC64->debugInterfaceC64->SetSidEmulateFilters(c64SettingsRESIDEmulateFilters); + viewC64->debugInterfaceC64->SetSidPassBand(c64SettingsRESIDPassBand); + viewC64->debugInterfaceC64->SetSidFilterBias(c64SettingsRESIDFilterBias); + viewC64->debugInterfaceC64->SetSidStereo(c64SettingsSIDStereo); + viewC64->debugInterfaceC64->SetSidStereoAddress(c64SettingsSIDStereoAddress); + viewC64->debugInterfaceC64->SetSidTripleAddress(c64SettingsSIDTripleAddress); + viewC64->debugInterfaceC64->SetReuEnabled(c64SettingsReuEnabled); + viewC64->debugInterfaceC64->SetReuSize(c64SettingsReuSize); + viewC64->debugInterfaceC64->SetVSPBugEmulation(c64SettingsEmulateVSPBug); + + if (c64SettingsEmulatedMouseC64Enabled) + { + viewC64->debugInterfaceC64->EmulatedMouseEnable(c64SettingsEmulatedMouseC64Enabled); + } +} + +void CMainMenuHelper::SetBasicVectors(int endAddr) +{ + LOGD("CViewMainMenu::SetBasicEndAddr: %x", endAddr); + // some decrunchers need correct basic pointers + + // set beginning of BASIC area + viewC64->debugInterfaceC64->SetByteC64(0x002B, 0x01); + viewC64->debugInterfaceC64->SetByteC64(0x002C, 0x08); + + // set beginning of variable/arrays area + viewC64->debugInterfaceC64->SetByteC64(0x002D, endAddr & 0x00FF); + viewC64->debugInterfaceC64->SetByteC64(0x002F, endAddr & 0x00FF); + viewC64->debugInterfaceC64->SetByteC64(0x0031, endAddr & 0x00FF); + viewC64->debugInterfaceC64->SetByteC64(0x00AE, endAddr & 0x00FF); + + viewC64->debugInterfaceC64->SetByteC64(0x002E, (endAddr >> 8) & 0x00FF); + viewC64->debugInterfaceC64->SetByteC64(0x0030, (endAddr >> 8) & 0x00FF); + viewC64->debugInterfaceC64->SetByteC64(0x0032, (endAddr >> 8) & 0x00FF); + viewC64->debugInterfaceC64->SetByteC64(0x00AF, (endAddr >> 8) & 0x00FF); + + // set end of BASIC area + viewC64->debugInterfaceC64->SetByteC64(0x0033, 0x00); + viewC64->debugInterfaceC64->SetByteC64(0x0037, 0x00); + + viewC64->debugInterfaceC64->SetByteC64(0x0034, 0xA0); + viewC64->debugInterfaceC64->SetByteC64(0x0038, 0xA0); + + // stop cursor flash + viewC64->debugInterfaceC64->SetByteC64(0x00CC, 0x01); + + // setup drive + debugInterfaceVice->PrepareDriveForBasicRun(); +} + +bool CMainMenuHelper::LoadPRGNotThreaded(CByteBuffer *byteBuffer, bool autoStart, bool showAddressInfo) +{ + LOGD("CViewMainMenu::LoadPRGNotThreaded: byteBuffer=%x autoStart=%s showAddressInfo=%s", byteBuffer, STRBOOL(autoStart), STRBOOL(showAddressInfo)); + viewC64->debugInterfaceC64->LockMutex(); + + u16 startAddr; + u16 endAddr; + + LoadPRG(byteBuffer, &startAddr, &endAddr); + + bool foundBasicSys = false; + +// bool isRunBasicCompatibleMode = true; + + if (autoStart == true) + { + LOGD("LoadPRG: autostart"); + + //http://www.lemon64.com/forum/viewtopic.php?t=870&sid=a13a63a952d295ff70c67d93409bc392 + + if (startAddr == 0x0801 || startAddr == 0x0800) + { +// if (isRunBasicCompatibleMode) + { + // new "RUN" + SetBasicVectors(endAddr); + +// viewC64->ShowMessage("LoadPRGNotThreaded"); + + viewC64->debugInterfaceC64->symbols->memory->ClearReadWriteDebugMarkers(); + viewC64->debugInterfaceC64->symbolsDrive1541->memory->ClearReadWriteDebugMarkers(); + + + viewC64->debugInterfaceC64->MakeJMPToBasicRunC64(); + +// viewC64->ShowMainScreen(); + + viewC64->debugInterfaceC64->ForceRunAndUnJamCpu(); + + + + + } + /* + else + { + // search for SYS + + // 1001 SYS 2066 + + // hidden SYS: $0805 1 0 0 1 SYS B + // 0800: 00 10 08 E9 03 00 31 30 30 31 9E 32 30 36 36 00 + + // not hidden SYS: + // 0800: 00 0C 08 E9 03 9E 20 32 30 36 36 00 + + int sysNumberAddr = -1; + + u8 b = viewC64->debugInterfaceC64->GetByteC64(0x0805); + + if (b == 0x9E) + { + // regular SYS + sysNumberAddr = 0x0806; + } + else if (b == 0x00) + { + // hidden SYS, scan for SYS ($9E), hope $0900 is enough :) + for (int i = 0x0806; i < 0x0900; i++) + { + if (viewC64->debugInterfaceC64->GetByteC64(i) == 0x9E) + { + sysNumberAddr = i + 1; + break; + } + } + } + + if (sysNumberAddr != -1) + { + char *buf = SYS_GetCharBuf(); + int i = 0; + + u16 addr = sysNumberAddr; + + bool isOK = true; + + while (true) + { + byte c = viewC64->debugInterfaceC64->GetByteC64(addr); + + LOGD("addr=%4.4x c=%2.2x '%c'", addr, c, c); + buf[i] = c; + + if (c == 0x20) + { + addr++; + continue; + } + + if (c < 0x30 || c > 0x39) + break; + + addr++; + i++; + + if (i == 254) + { + isOK = false; + break; + } + } + + if (isOK) + { + int startAddr = -1; + + if (isOK) + { + foundBasicSys = true; + startAddr = atoi(buf); + } + + SetBasicEndAddr(endAddr); + + viewC64->viewC64MemoryMap->ClearReadWriteMarkers(); + viewC64->viewDrive1541MemoryMap->ClearReadWriteMarkers(); + + viewC64->debugInterfaceC64->MakeJsrC64(startAddr); + + viewC64->ShowMainScreen(); + + if (viewC64->debugInterfaceC64->IsCpuJam()) + { + viewC64->debugInterfaceC64->ForceRunAndUnJamCpu(); + } + } + + SYS_ReleaseCharBuf(buf); + } + } + */ + } + } + + if (autoStart && c64SettingsAutoJmpAlwaysToLoadedPRGAddress && !foundBasicSys) // && !isRunBasicCompatibleMode) + { + LOGD("LoadPRG: c64SettingsAutoJmpAlwaysToLoadedPRGAddress"); + + if (c64SettingsResetCountersOnAutoRun) + { + viewC64->debugInterfaceC64->ResetEmulationFrameCounter(); + viewC64->debugInterfaceC64->ResetMainCpuDebugCycleCounter(); + } + + viewC64->debugInterfaceC64->MakeJsrC64(startAddr); + viewC64->ShowMainScreen(); + + if (viewC64->debugInterfaceC64->IsCpuJam()) + { + viewC64->debugInterfaceC64->ForceRunAndUnJamCpu(); + } + + } + + if ((c64SettingsAutoJmpAlwaysToLoadedPRGAddress || autoStart) && showAddressInfo) + { + char *buf = SYS_GetCharBuf(); + + sprintf(buf, "Loaded from $%04X to $%04X", startAddr, endAddr); + viewC64->ShowMessage(buf); + + SYS_ReleaseCharBuf(buf); + } + + if (c64SettingsForceUnpause) + { + LOGD("LoadPRG: unpause"); + viewC64->debugInterfaceC64->SetDebugMode(DEBUGGER_MODE_RUNNING); + } + + viewC64->debugInterfaceC64->UnlockMutex(); + + LOGD("CViewMainMenu::LoadPRGNotThreaded COMPLETED"); + + return true; +} + + +void CMainMenuHelper::LoadPRG(CByteBuffer *byteBuffer, u16 *startAddr, u16 *endAddr) +{ + LOGD("ViewMainMenu::LoadPRG: byteBuffer=%x"); + u16 b1 = byteBuffer->GetByte(); + u16 b2 = byteBuffer->GetByte(); + + u16 loadPoint = (b2 << 8) | b1; + + LOGD("..loadPoint=%4.4x", loadPoint); + + u16 addr = loadPoint; + while (!byteBuffer->IsEof()) + { + u8 b = byteBuffer->GetByte(); + + + // viewC64->debugInterface->SetByteC64(addr, b); + + viewC64->debugInterfaceC64->SetByteToRamC64(addr, b); + addr++; + } + + LOGD("LoadPRG: ..loaded till=%4.4x", addr); + + *startAddr = loadPoint; + *endAddr = addr; +} + +void CMainMenuHelper::ResetAndJSR(int startAddr) +{ + viewC64->debugInterfaceC64->ResetSoft(); + viewC64->debugInterfaceC64->MakeJsrC64(startAddr); + +} + +void CMainMenuHelper::ReloadAndRestartPRG() +{ + LOGM("CViewMainMenu::ReloadAndRestartPRG"); + + if (c64SettingsPathToPRG != NULL) + { + char *asciiPath = c64SettingsPathToPRG->GetStdASCII(); + LOGD("asciiPath='%s'", asciiPath); + + CSlrFileFromOS *file = new CSlrFileFromOS(asciiPath); + if (!file->Exists()) + { + delete file; + viewC64->ShowMessageError("Error loading PRG file, no such file path:\n%s", asciiPath); + return; + } + + guiMain->LockMutex(); + LoadLabelsAndWatches(c64SettingsPathToPRG, viewC64->debugInterfaceC64); + guiMain->UnlockMutex(); + + CByteBuffer *byteBuffer = new CByteBuffer(file, false); + LoadPRG(byteBuffer, true, false, false); + + delete asciiPath; + delete file; + + delete byteBuffer; + + return; + } + else + { + viewC64->ShowMessageError("Please select PRG file first"); + } +} + + +void CMainMenuHelper::SystemDialogFileOpenCancelled() +{ +} + +void CMainMenuHelper::MessageBoxCallback() +{ +} + + + +CViewC64MenuItem::CViewC64MenuItem(float height, CSlrString *strIn, CSlrKeyboardShortcut *shortcut, float r, float g, float b) +: CGuiViewMenuItem(height) +{ + this->str = NULL; + this->str2 = NULL; + this->shortcut = shortcut; + this->r = r; + this->g = g; + this->b = b; + + if (strIn != NULL) + { + this->SetString(strIn); + } +} + +// sub item +CViewC64MenuItem::CViewC64MenuItem(float height, CSlrString *str, CSlrKeyboardShortcut *shortcut, float r, float g, float b, + CGuiViewMenu *mainMenu) +: CGuiViewMenuItem(height, mainMenu) +{ + this->str = NULL; + this->str2 = NULL; + this->shortcut = shortcut; + this->r = r; + this->g = g; + this->b = b; + + if (str != NULL) + this->SetString(str); +} + +void CViewC64MenuItem::SetString(CSlrString *str) +{ + if (this->str != NULL) + { + delete this->str; + } + this->str = str; + if (this->isSelected) + { + this->isSelected = false; + this->SetSelected(true); + this->isSelected = true; + } +} + +void CViewC64MenuItem::Execute() +{ +} + +void CViewC64MenuItem::DebugPrint() +{ + LOGD("CGuiViewMenuItem: %x menu=%x subMenu=%x str=%x", this, this->menu, this->subMenu, this->str); + +// if (this->str != NULL) +// { +// this->str->DebugPrint("menu item str="); +// LOGD("color=%f %f %f", r, g, b); +// } +} + +void CViewC64MenuItem::SetSelected(bool selected) +{ + if (this->isSelected != selected == true) + { + for (int i = 0; i < str->GetLength(); i++) + { + u16 chr = str->GetChar(i); + chr ^= CBMSHIFTEDFONT_INVERT; + str->SetChar(i, chr); + } + return; + } +} + +void CViewC64MenuItem::RenderItem(float px, float py, float pz) +{ + viewC64->mainMenuHelper->font->BlitTextColor(str, px, py, pz, + viewC64->mainMenuHelper->fontScale, r, g, b, 1); + + if (shortcut != NULL && shortcut->str != NULL) + { + viewC64->mainMenuHelper->font->BlitTextColor(shortcut->str, px + 510, py, pz, + viewC64->mainMenuHelper->fontScale, + viewC64->colorsTheme->colorTextKeyShortcutR, + viewC64->colorsTheme->colorTextKeyShortcutG, + viewC64->colorsTheme->colorTextKeyShortcutB, 1, + FONT_ALIGN_RIGHT); + } + + if (str2 != NULL) + { + py += viewC64->mainMenuHelper->fontHeight; + viewC64->mainMenuHelper->font->BlitTextColor(str2, px, py, pz, + viewC64->mainMenuHelper->fontScale, r, g, b, 1); + } +} + +// + +CViewC64MenuItemOption::CViewC64MenuItemOption(float height, CSlrString *str, CSlrKeyboardShortcut *shortcut, float r, float g, float b, + std::vector *options, CSlrFont *font, float fontScale) +: CViewC64MenuItem(height, NULL, shortcut, r, g, b) +{ + this->options = options; + this->selectedOption = 0; + + textStr = NULL; + + // update display string + this->SetString(str); +} + +void CViewC64MenuItemOption::SetOptions(std::vector *options) +{ + if (this->options != NULL) + { + while (!this->options->empty()) + { + CSlrString *opt = this->options->back(); + this->options->pop_back(); + delete opt; + } + delete this->options; + } + + this->options = options; + + UpdateDisplayString(); +} + +void CViewC64MenuItemOption::SetOptionsWithoutDelete(std::vector *options) +{ + this->options = options; + + UpdateDisplayString(); +} + +void CViewC64MenuItemOption::SetString(CSlrString *str) +{ + if (this->textStr != NULL) + delete this->textStr; + + this->textStr = str; + + UpdateDisplayString(); +} + +void CViewC64MenuItemOption::UpdateDisplayString() +{ + if (this->options != NULL) + { + CSlrString *newStr = new CSlrString(this->textStr); + newStr->Concatenate((*this->options)[selectedOption]); + + CViewC64MenuItem::SetString(newStr); + } +} + +void CViewC64MenuItemOption::SwitchToPrev() +{ + if (selectedOption == 0) + { + selectedOption = options->size()-1; + } + else + { + selectedOption--; + } + + this->UpdateDisplayString(); + + this->menu->callback->MenuCallbackItemChanged(this); +} + +void CViewC64MenuItemOption::SwitchToNext() +{ + if (selectedOption == options->size()-1) + { + selectedOption = 0; + } + else + { + selectedOption++; + } + + this->UpdateDisplayString(); + + this->menu->callback->MenuCallbackItemChanged(this); +} + +void CViewC64MenuItemOption::SetSelectedOption(int newSelectedOption, bool runCallback) +{ + selectedOption = newSelectedOption; + this->UpdateDisplayString(); + + if (runCallback) + this->menu->callback->MenuCallbackItemChanged(this); +} + +bool CViewC64MenuItemOption::KeyDown(u32 keyCode) +{ + if (keyCode == MTKEY_ARROW_LEFT) + { + SwitchToPrev(); + return true; + } + else if (keyCode == MTKEY_ARROW_RIGHT || keyCode == MTKEY_ENTER) + { + SwitchToNext(); + return true; + } + + return false; +} + +void CViewC64MenuItemOption::Execute() +{ + SwitchToNext(); +} + +// +CViewC64MenuItemFloat::CViewC64MenuItemFloat(float height, CSlrString *str, CSlrKeyboardShortcut *shortcut, float r, float g, float b, + float minimum, float maximum, float step, CSlrFont *font, float fontScale) +: CViewC64MenuItem(height, NULL, shortcut, r, g, b) +{ + this->minimum = minimum; + this->maximum = maximum; + this->step = step; + + textStr = NULL; + + numLeadingDigits = 5; + numDecimalsDigits = 2; + value = 0; + + // update display string + this->SetString(str); +} + +void CViewC64MenuItemFloat::SetValue(float value, bool runCallback) +{ + this->value = value; + + UpdateDisplayString(); + + if (runCallback) + this->menu->callback->MenuCallbackItemChanged(this); +} + +void CViewC64MenuItemFloat::SetString(CSlrString *str) +{ + if (this->textStr != NULL) + delete this->textStr; + + this->textStr = str; + + UpdateDisplayString(); + +} + +void CViewC64MenuItemFloat::UpdateDisplayString() +{ + char *buf = SYS_GetCharBuf(); + char *bufFormat = SYS_GetCharBuf(); + + sprintf(bufFormat, "%%-%d.%df", numLeadingDigits, numDecimalsDigits); + sprintf(buf, bufFormat, value); + CSlrString *valStr = new CSlrString(buf); + + SYS_ReleaseCharBuf(buf); + SYS_ReleaseCharBuf(bufFormat); + + CSlrString *newStr = new CSlrString(this->textStr); + newStr->Concatenate(valStr); + CViewC64MenuItem::SetString(newStr); + + delete valStr; +} + +void CViewC64MenuItemFloat::SwitchToPrev() +{ + value -= step; + + if (value < minimum) + value = minimum; + + this->UpdateDisplayString(); + + this->menu->callback->MenuCallbackItemChanged(this); +} + +void CViewC64MenuItemFloat::SwitchToNext() +{ + value += step; + + if (value > maximum) + value = maximum; + + this->UpdateDisplayString(); + + this->menu->callback->MenuCallbackItemChanged(this); +} + +bool CViewC64MenuItemFloat::KeyDown(u32 keyCode) +{ + if (keyCode == MTKEY_ARROW_LEFT) + { + SwitchToPrev(); + return true; + } + else if (keyCode == MTKEY_ARROW_RIGHT || keyCode == MTKEY_ENTER) + { + SwitchToNext(); + return true; + } + + return false; +} + +void CViewC64MenuItemFloat::Execute() +{ + SwitchToNext(); +} + diff --git a/src/Screens/CMainMenuHelper.h b/src/Screens/CMainMenuHelper.h new file mode 100644 index 0000000..d6dbdfe --- /dev/null +++ b/src/Screens/CMainMenuHelper.h @@ -0,0 +1,189 @@ +#ifndef _VIEW_C64MAINMENU_ +#define _VIEW_C64MAINMENU_ + +#include "CGuiMain.h" +#include "CGuiButton.h" +#include "CGuiViewMenu.h" +#include "SYS_FileSystem.h" +#include "SYS_Threading.h" +#include "CColorsTheme.h" +#include "CSlrKeyboardShortcuts.h" +#include + +class CSlrKeyboardShortcut; +class CViewC64MenuItem; +class CViewC64MenuItemOption; +class CDebugInterface; + +class CMainMenuHelper : public CGuiView, CGuiButtonCallback, CGuiViewMenuCallback, CSystemFileDialogCallback, CSlrThread, CSlrKeyboardShortcutCallback, CUiMessageBoxCallback +{ +public: + CMainMenuHelper(float posX, float posY, float posZ, float sizeX, float sizeY); + virtual ~CMainMenuHelper(); + + CSlrFont *font; + float fontScale; + float fontHeight; + float tr; + float tg; + float tb; + + CGuiViewMenu *viewMenu; + + std::list openFileExtensions; + std::list diskExtensions; + std::list tapeExtensions; + std::list crtExtensions; + std::list reuExtensions; + std::list jukeboxExtensions; + std::list romsFileExtensions; + + void OpenDialogOpenFile(); + + void LoadFile(CSlrString *path); + void OpenDialogInsertD64(); + bool InsertD64(CSlrString *path, bool updatePathToD64, bool autoRun, int autoRunEntryNum, bool showLoadAddressInfo); + std::list cDiskExtensions; + void InsertNextD64(); + void OpenDialogInsertCartridge(); + bool InsertCartridge(CSlrString *path, bool updatePathToCRT); + void OpenDialogInsertAtariCartridge(); + + bool LoadPRG(CSlrString *path, bool autoStart, bool updatePRGFolderPath, bool showAddressInfo, bool forceFastReset); + bool LoadPRG(CByteBuffer *byteBuffer, bool autoStart, bool showAddressInfo, bool forceFastReset); + void LoadPRG(CByteBuffer *byteBuffer, u16 *startAddr, u16 *endAddr); + bool LoadPRGNotThreaded(CByteBuffer *byteBuffer, bool autoStart, bool showAddressInfo); + void SetupC64Defaults(); + + bool LoadSID(CSlrString *filePath); + + void OpenDialogInsertTape(); + bool LoadTape(CSlrString *path, bool autoStart, bool updateTAPFolderPath, bool showAddressInfo); + void DetachTape(); + + // + void OpenDialogAttachReu(); + void OpenDialogSaveReu(); + bool AttachReu(CSlrString *path, bool updatePathToReu, bool showDetails); + bool SaveReu(CSlrString *path, bool updatePathToReu, bool showDetails); + + // + bool LoadXEX(CSlrString *path, bool autoStart, bool updatePRGFolderPath, bool showAddressInfo); + bool LoadCAS(CSlrString *path, bool autoStart, bool updatePRGFolderPath, bool showAddressInfo); + bool InsertAtariCartridge(CSlrString *path, bool autoStart, bool updatePRGFolderPath, bool showAddressInfo); + bool LoadASAP(CSlrString *filePath); + + void OpenDialogInsertATR(); + bool InsertATR(CSlrString *path, bool updatePathToATR, bool autoRun, int autoRunEntryNum, bool showLoadAddressInfo); + + // + CViewC64MenuItem *menuItemSetFolderWithNesROMs; + void OpenDialogSetFolderWithNesROMs(); + + bool LoadNES(CSlrString *path, bool updateNESFolderPath); + + + void LoadLabelsAndWatches(CSlrString *path, CDebugInterface *debugInterface); + void SetBasicVectors(int endAddr); + + void OpenDialogStartJukeboxPlaylist(); + + // LoadPRG threaded + bool loadPrgAutoStart; + bool loadPrgShowAddressInfo; + bool loadPrgForceFastReset; + virtual void ThreadRun(void *data); + + void ReloadAndRestartPRG(); + void ResetAndJSR(int startAddr); + + virtual void MessageBoxCallback(); + + u8 openDialogFunction; + virtual void SystemDialogFileOpenSelected(CSlrString *path); + virtual void SystemDialogFileOpenCancelled(); + virtual void SystemDialogFileSaveSelected(CSlrString *path); + virtual void SystemDialogFileSaveCancelled(); + +}; + +class CViewC64MenuItem : public CGuiViewMenuItem +{ +public: + CViewC64MenuItem(float height, CSlrString *str, CSlrKeyboardShortcut *shortcut, float r, float g, float b); + CViewC64MenuItem(float height, CSlrString *str, CSlrKeyboardShortcut *shortcut, float r, float g, float b, + CGuiViewMenu *mainMenu); + + virtual void SetSelected(bool selected); + virtual void RenderItem(float px, float py, float pz); + + virtual void SetString(CSlrString *str); + + CSlrString *str; + CSlrString *str2; + CSlrKeyboardShortcut *shortcut; + float r; + float g; + float b; + + virtual void Execute(); + + virtual void DebugPrint(); +}; + +class CViewC64MenuItemOption : public CViewC64MenuItem +{ +public: + CViewC64MenuItemOption(float height, CSlrString *str, CSlrKeyboardShortcut *shortcut, float r, float g, float b, + std::vector *options, CSlrFont *font, float fontScale); + + void SetOptions(std::vector *options); + void SetOptionsWithoutDelete(std::vector *options); + + std::vector *options; + + CSlrString *textStr; + + virtual void SetString(CSlrString *str); + virtual void UpdateDisplayString(); + + virtual bool KeyDown(u32 keyCode); + + virtual void SwitchToNext(); + virtual void SwitchToPrev(); + + virtual void Execute(); + + int selectedOption; + virtual void SetSelectedOption(int newSelectedOption, bool runCallback); +}; + +class CViewC64MenuItemFloat : public CViewC64MenuItem +{ +public: + CViewC64MenuItemFloat(float height, CSlrString *str, CSlrKeyboardShortcut *shortcut, float r, float g, float b, + float minimum, float maximum, float step, CSlrFont *font, float fontScale); + + float minimum, maximum, step; + + CSlrString *textStr; + + virtual void SetString(CSlrString *str); + virtual void UpdateDisplayString(); + + virtual bool KeyDown(u32 keyCode); + + virtual void SwitchToNext(); + virtual void SwitchToPrev(); + + virtual void Execute(); + + int numLeadingDigits; + int numDecimalsDigits; + + float value; + virtual void SetValue(float value, bool runCallback); +}; + + +#endif //_VIEW_C64MAINMENU_ diff --git a/src/Screens/CViewAbout.cpp b/src/Screens/CViewAbout.cpp index 945d269..5dd38f4 100644 --- a/src/Screens/CViewAbout.cpp +++ b/src/Screens/CViewAbout.cpp @@ -311,7 +311,7 @@ void CViewAbout::Render(float posX, float posY) bool CViewAbout::DoTap(float x, float y) { LOGG("CViewAbout::DoTap: x=%f y=%f", x, y); - guiMain->SetView(viewC64->viewC64MainMenu); + guiMain->SetView(viewC64->mainMenuHelper); return CGuiView::DoTap(x, y); } @@ -374,7 +374,7 @@ void CViewAbout::SwitchAboutScreen() { if (guiMain->currentView == this) { - guiMain->SetView(viewC64->viewC64MainMenu); + guiMain->SetView(viewC64->mainMenuHelper); } else { @@ -384,7 +384,7 @@ void CViewAbout::SwitchAboutScreen() bool CViewAbout::KeyDown(u32 keyCode, bool isShift, bool isAlt, bool isControl, bool isSuper) { - guiMain->SetView(viewC64->viewC64MainMenu); + guiMain->SetView(viewC64->mainMenuHelper); // if (keyCode == MTKEY_BACKSPACE) // { diff --git a/src/Screens/CViewBreakpointsOLD.cpp b/src/Screens/CViewBreakpointsOLD.cpp index c4b4519..8a744d3 100644 --- a/src/Screens/CViewBreakpointsOLD.cpp +++ b/src/Screens/CViewBreakpointsOLD.cpp @@ -888,7 +888,7 @@ void CViewBreakpointsOLD::StartEditingSelectedAddrBreakpoint(CDebugBreakpointsAd { if (cursorElement < addrBreakpoints->breakpoints.size()) { - std::map::iterator it = addrBreakpoints->breakpoints.begin(); + std::map::iterator it = addrBreakpoints->breakpoints.begin(); for (int i = 0; i < cursorElement; i++) { it++; @@ -905,21 +905,21 @@ void CViewBreakpointsOLD::StartEditingSelectedAddrBreakpoint(CDebugBreakpointsAd } -void CViewBreakpointsOLD::StartEditingSelectedMemoryBreakpoint(CDebugBreakpointsMemory *memoryBreakpoints) +void CViewBreakpointsOLD::StartEditingSelectedMemoryBreakpoint(CDebugBreakpointsData *memoryBreakpoints) { if (cursorElement < memoryBreakpoints->breakpoints.size()) { - std::map::iterator it = memoryBreakpoints->breakpoints.begin(); + std::map::iterator it = memoryBreakpoints->breakpoints.begin(); for (int i = 0; i < cursorElement; i++) { it++; } - editingBreakpoint = (CBreakpointMemory *)it->second; + editingBreakpoint = (CDebugBreakpointData *)it->second; editHex->SetValue(editingBreakpoint->addr, 4); } else { - editingBreakpoint = new CBreakpointMemory(0, MEMORY_BREAKPOINT_ACCESS_WRITE, MemoryBreakpointComparison::MEMORY_BREAKPOINT_EQUAL, 0); + editingBreakpoint = new CDebugBreakpointData(0, MEMORY_BREAKPOINT_ACCESS_WRITE, DataBreakpointComparison::MEMORY_BREAKPOINT_EQUAL, 0); editHex->SetText(new CSlrString("....")); } isEditingValue = true; @@ -931,29 +931,29 @@ void CViewBreakpointsOLD::DeleteSelectedAddrBreakpoint(CDebugBreakpointsAddr *ad debugInterface->LockMutex(); if (cursorElement < addrBreakpoints->breakpoints.size()) { - std::map::iterator it = addrBreakpoints->breakpoints.begin(); + std::map::iterator it = addrBreakpoints->breakpoints.begin(); for (int i = 0; i < cursorElement; i++) { it++; } - CBreakpointAddr *breakpoint = it->second; + CDebugBreakpointAddr *breakpoint = it->second; addrBreakpoints->breakpoints.erase(it); delete breakpoint; } debugInterface->UnlockMutex(); } -void CViewBreakpointsOLD::DeleteSelectedMemoryBreakpoint(CDebugBreakpointsMemory *memoryBreakpoints) +void CViewBreakpointsOLD::DeleteSelectedMemoryBreakpoint(CDebugBreakpointsData *memoryBreakpoints) { debugInterface->LockMutex(); if (cursorElement < memoryBreakpoints->breakpoints.size()) { - std::map::iterator it = memoryBreakpoints->breakpoints.begin(); + std::map::iterator it = memoryBreakpoints->breakpoints.begin(); for (int i = 0; i < cursorElement; i++) { it++; } - CBreakpointAddr *breakpoint = it->second; + CDebugBreakpointAddr *breakpoint = it->second; memoryBreakpoints->breakpoints.erase(it); delete breakpoint; } @@ -1007,32 +1007,32 @@ void CViewBreakpointsOLD::GuiEditHexEnteredValueAddr(CGuiEditHex *editHex, CDebu { if (cursorElement < addrBreakpoints->breakpoints.size()) { - std::map::iterator it = addrBreakpoints->breakpoints.begin(); + std::map::iterator it = addrBreakpoints->breakpoints.begin(); for (int i = 0; i < cursorElement; i++) { it++; } - CBreakpointAddr *addrBreakpoint = it->second; + CDebugBreakpointAddr *addrBreakpoint = it->second; addrBreakpoints->breakpoints.erase(it); addrBreakpoint->addr = editHex->value; addrBreakpoints->breakpoints[addrBreakpoint->addr] = addrBreakpoint; } else { - std::map::iterator it = addrBreakpoints->breakpoints.find(editHex->value); + std::map::iterator it = addrBreakpoints->breakpoints.find(editHex->value); if (it == addrBreakpoints->breakpoints.end()) { - CBreakpointAddr *addrBreakpoint = new CBreakpointAddr(editHex->value); + CDebugBreakpointAddr *addrBreakpoint = new CDebugBreakpointAddr(editHex->value); addrBreakpoints->breakpoints[addrBreakpoint->addr] = addrBreakpoint; } } // position cursor on this cursorElement = 0; - for (std::map::iterator it = addrBreakpoints->breakpoints.begin(); + for (std::map::iterator it = addrBreakpoints->breakpoints.begin(); it != addrBreakpoints->breakpoints.end(); it++) { - CBreakpointAddr *addrBreakpoint = it->second; + CDebugBreakpointAddr *addrBreakpoint = it->second; if (addrBreakpoint->addr == editHex->value) break; @@ -1043,13 +1043,13 @@ void CViewBreakpointsOLD::GuiEditHexEnteredValueAddr(CGuiEditHex *editHex, CDebu this->cursorPosition = -1; } -void CViewBreakpointsOLD::GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 lastKeyCode, CDebugBreakpointsMemory *memoryBreakpoints) +void CViewBreakpointsOLD::GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 lastKeyCode, CDebugBreakpointsData *memoryBreakpoints) { if (cursorPosition == 1) { if (lastKeyCode != MTKEY_ARROW_LEFT) { - CBreakpointMemory *memoryBreakpoint = (CBreakpointMemory *)editingBreakpoint; + CDebugBreakpointData *memoryBreakpoint = (CDebugBreakpointData *)editingBreakpoint; memoryBreakpoint->addr = editHex->value; isEditingValue = false; cursorPosition = 2; @@ -1059,7 +1059,7 @@ void CViewBreakpointsOLD::GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 { if (lastKeyCode == MTKEY_ARROW_LEFT) { - CBreakpointMemory *memoryBreakpoint = (CBreakpointMemory *)editingBreakpoint; + CDebugBreakpointData *memoryBreakpoint = (CDebugBreakpointData *)editingBreakpoint; memoryBreakpoint->value = editHex->value; cursorPosition = 2; isEditingValue = false; @@ -1070,12 +1070,12 @@ void CViewBreakpointsOLD::GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 if (cursorElement < memoryBreakpoints->breakpoints.size()) { - std::map::iterator it = memoryBreakpoints->breakpoints.begin(); + std::map::iterator it = memoryBreakpoints->breakpoints.begin(); for (int i = 0; i < cursorElement; i++) { it++; } - CBreakpointMemory *memoryBreakpoint = (CBreakpointMemory*)it->second; + CDebugBreakpointData *memoryBreakpoint = (CDebugBreakpointData*)it->second; memoryBreakpoints->breakpoints.erase(it); memoryBreakpoint->value = editHex->value; memoryBreakpoints->breakpoints[memoryBreakpoint->addr] = memoryBreakpoint; @@ -1083,8 +1083,8 @@ void CViewBreakpointsOLD::GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 } else { - CBreakpointMemory *memoryBreakpoint = (CBreakpointMemory *)editingBreakpoint; - std::map::iterator it = memoryBreakpoints->breakpoints.find(memoryBreakpoint->addr); + CDebugBreakpointData *memoryBreakpoint = (CDebugBreakpointData *)editingBreakpoint; + std::map::iterator it = memoryBreakpoints->breakpoints.find(memoryBreakpoint->addr); if (it == memoryBreakpoints->breakpoints.end()) { memoryBreakpoints->breakpoints[memoryBreakpoint->addr] = memoryBreakpoint; @@ -1094,7 +1094,7 @@ void CViewBreakpointsOLD::GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 else { delete memoryBreakpoint; - memoryBreakpoint = (CBreakpointMemory*)it->second; + memoryBreakpoint = (CDebugBreakpointData*)it->second; memoryBreakpoint->value = editHex->value; addr = memoryBreakpoint->addr; } @@ -1102,10 +1102,10 @@ void CViewBreakpointsOLD::GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 // position cursor on this cursorElement = 0; - for (std::map::iterator it = memoryBreakpoints->breakpoints.begin(); + for (std::map::iterator it = memoryBreakpoints->breakpoints.begin(); it != memoryBreakpoints->breakpoints.end(); it++) { - CBreakpointAddr *addrBreakpoint = it->second; + CDebugBreakpointAddr *addrBreakpoint = it->second; if (addrBreakpoint->addr == addr) break; @@ -1389,10 +1389,10 @@ void CViewBreakpointsOLD::RenderAddrBreakpoints(CDebugBreakpointsAddr *addrBreak float py = pStartY; int elemNum = 0; - for (std::map::iterator it = addrBreakpoints->breakpoints.begin(); + for (std::map::iterator it = addrBreakpoints->breakpoints.begin(); it != addrBreakpoints->breakpoints.end(); it++) { - CBreakpointAddr *addrBreakpoint = it->second; + CDebugBreakpointAddr *addrBreakpoint = it->second; int addr = addrBreakpoint->addr; sprintf(buf, addrFormatStr, addr); @@ -1449,7 +1449,7 @@ void CViewBreakpointsOLD::RenderAddrBreakpoints(CDebugBreakpointsAddr *addrBreak font->BlitTextColor(strTemp, px, py, -1, fontNumbersScale, tr, tg, tb, 1, FONT_ALIGN_LEFT); } -void CViewBreakpointsOLD::RenderMemoryBreakpoints(CDebugBreakpointsMemory *memoryBreakpoints, float pStartX, float pStartY, int cursorGroupId) +void CViewBreakpointsOLD::RenderMemoryBreakpoints(CDebugBreakpointsData *memoryBreakpoints, float pStartX, float pStartY, int cursorGroupId) { float width = fontWidth*8.5f; @@ -1458,10 +1458,10 @@ void CViewBreakpointsOLD::RenderMemoryBreakpoints(CDebugBreakpointsMemory *memor /// memory int elemNum = 0; - for (std::map::iterator it = memoryBreakpoints->breakpoints.begin(); + for (std::map::iterator it = memoryBreakpoints->breakpoints.begin(); it != memoryBreakpoints->breakpoints.end(); it++) { - CBreakpointMemory *memoryBreakpoint = (CBreakpointMemory*)it->second; + CDebugBreakpointData *memoryBreakpoint = (CDebugBreakpointData*)it->second; char buf2[3] = {0}; @@ -1578,7 +1578,7 @@ void CViewBreakpointsOLD::RenderMemoryBreakpoints(CDebugBreakpointsMemory *memor /// ugh, again copy pasted code here with only slight differences... remember this is only a POC :D - CBreakpointMemory *memoryBreakpoint = (CBreakpointMemory *)editingBreakpoint; + CDebugBreakpointData *memoryBreakpoint = (CDebugBreakpointData *)editingBreakpoint; char buf2[3] = {0}; @@ -1701,7 +1701,7 @@ bool CViewBreakpointsOLD::CheckTapAddrBreakpoints(float x, float y, } bool CViewBreakpointsOLD::CheckTapMemoryBreakpoints(float x, float y, - CDebugBreakpointsMemory *memoryBreakpoints, + CDebugBreakpointsData *memoryBreakpoints, float pStartX, float pStartY, int cursorGroupId) { float width = fontWidth*8.5f; diff --git a/src/Screens/CViewBreakpointsOLD.h b/src/Screens/CViewBreakpointsOLD.h index 6c86b44..79ce7de 100644 --- a/src/Screens/CViewBreakpointsOLD.h +++ b/src/Screens/CViewBreakpointsOLD.h @@ -8,10 +8,10 @@ #include "CGuiEditHex.h" #include "CColorsTheme.h" -class CBreakpointAddr; -class CBreakpointMemory; +class CDebugBreakpointAddr; +class CDebugBreakpointData; class CDebugBreakpointsAddr; -class CDebugBreakpointsMemory; +class CDebugBreakpointsData; class CViewBreakpointsOLD : public CGuiView, CGuiButtonSwitchCallback, CGuiEditHexCallback { @@ -117,31 +117,31 @@ class CViewBreakpointsOLD : public CGuiView, CGuiButtonSwitchCallback, CGuiEditH virtual void GuiEditHexEnteredValue(CGuiEditHex *editHex, u32 lastKeyCode, bool isCancelled); - CBreakpointAddr *editingBreakpoint; + CDebugBreakpointAddr *editingBreakpoint; CGuiEditHex *editHex; // void RenderAddrBreakpoints(CDebugBreakpointsAddr *addrBreakpoints, float pStartX, float pStartY, int cursorGroupId, char *addrFormatStr, char *addrEmptyStr); - void RenderMemoryBreakpoints(CDebugBreakpointsMemory *memoryBreakpoints, float pStartX, float pStartY, int cursorGroupId); + void RenderMemoryBreakpoints(CDebugBreakpointsData *memoryBreakpoints, float pStartX, float pStartY, int cursorGroupId); bool CheckTapAddrBreakpoints(float x, float y, CDebugBreakpointsAddr *addrBreakpoints, float pStartX, float pStartY, int cursorGroupId); bool CheckTapMemoryBreakpoints(float x, float y, - CDebugBreakpointsMemory *memoryBreakpoints, + CDebugBreakpointsData *memoryBreakpoints, float pStartX, float pStartY, int cursorGroupId); void GuiEditHexEnteredValueAddr(CGuiEditHex *editHex, CDebugBreakpointsAddr *addrBreakpoints); - void GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 lastKeyCode, CDebugBreakpointsMemory *memoryBreakpoints); + void GuiEditHexEnteredValueMemory(CGuiEditHex *editHex, u32 lastKeyCode, CDebugBreakpointsData *memoryBreakpoints); void StartEditingSelectedAddrBreakpoint(CDebugBreakpointsAddr *addrBreakpoints, char *emptyAddrStr); - void StartEditingSelectedMemoryBreakpoint(CDebugBreakpointsMemory *memoryBreakpoints); + void StartEditingSelectedMemoryBreakpoint(CDebugBreakpointsData *memoryBreakpoints); void DeleteSelectedAddrBreakpoint(CDebugBreakpointsAddr *addrBreakpoints); - void DeleteSelectedMemoryBreakpoint(CDebugBreakpointsMemory *memoryBreakpoints); + void DeleteSelectedMemoryBreakpoint(CDebugBreakpointsData *memoryBreakpoints); CGuiView *prevView; diff --git a/src/Screens/CViewC64.cpp b/src/Screens/CViewC64.cpp index d534fa1..4f23955 100644 --- a/src/Screens/CViewC64.cpp +++ b/src/Screens/CViewC64.cpp @@ -106,7 +106,7 @@ extern "C"{ #include "CViewEmulationState.h" -#include "CViewMainMenu.h" +#include "CMainMenuHelper.h" #include "CViewSettingsMenu.h" #include "CViewDrive1541Browser.h" @@ -158,17 +158,23 @@ extern "C"{ #include "CDebugAsmSource.h" #include "CDebuggerEmulatorPlugin.h" #include "CSnapshotsManager.h" + #include "CDebugSymbolsC64.h" #include "CDebugSymbolsSegmentC64.h" #include "CDebugSymbolsDrive1541.h" #include "CDebugInterfaceMenuItemFolder.h" #include "CDebugInterfaceMenuItemView.h" + #include "C64D_InitPlugins.h" +#include "CPipeProtocolDebuggerCallback.h" +#include "CDebuggerServer.h" + #include "CDebugInterfaceVice.h" #include "CDebugInterfaceAtari.h" #include "CDebugInterfaceNes.h" + #include "CSlrFileZlib.h" #include #include @@ -188,6 +194,10 @@ void TEST_Editor_Render(); const ImGuiInputTextFlags defaultHexInputFlags = ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_EnterReturnsTrue; +// workaround: external API due to stupid MS Windows winsock2 clashes +CDebuggerServer *REMOTE_CreateDebuggerServerWebSockets(int port); +void REMOTE_DebuggerServerWebSocketsSetPort(CDebuggerServer *debuggerServer, int port); + // TODO: refactor this. after transition to ImGui the CViewC64 is no longer a view, it is just a application holder of other views. CViewC64::CViewC64(float posX, float posY, float posZ, float sizeX, float sizeY) : CGuiView("CViewC64", posX, posY, posZ, sizeX, sizeY) @@ -396,7 +406,7 @@ CViewC64::CViewC64(float posX, float posY, float posZ, float sizeX, float sizeY) // DO NOT ADD YOUSELF YOU'VE BEEN ADDED ALREADY: guiMain->AddGuiElement(this); // other screens. These screens are obsolete: - viewC64MainMenu = new CViewMainMenu(0, 0, -3.0, SCREEN_WIDTH, SCREEN_HEIGHT); + mainMenuHelper = new CMainMenuHelper(0, 0, -3.0, SCREEN_WIDTH, SCREEN_HEIGHT); // guiMain->AddGuiElement(viewC64MainMenu); viewC64SettingsMenu = new CViewSettingsMenu(0, 0, -3.0, SCREEN_WIDTH, SCREEN_HEIGHT); @@ -531,6 +541,8 @@ CViewC64::CViewC64(float posX, float posY, float posZ, float sizeX, float sizeY) if (c64SettingsUsePipeIntegration) { PIPE_Init("retrodebugger"); + pipeProtocolCallback = new CPipeProtocolDebuggerCallback(); + PIPE_AddCallback(pipeProtocolCallback); } // @@ -614,6 +626,13 @@ CViewC64::CViewC64(float posX, float posY, float posZ, float sizeX, float sizeY) // start post-init ui tasks SYS_StartThread(this); + // start remote debugger server + debuggerServer = NULL; + if (c64SettingsRunDebuggerServerWebSockets) + { + DebuggerServerWebSocketsStart(); + } + // TEST_Editor(); } @@ -627,7 +646,7 @@ void CViewC64::ThreadRun(void *passData) { if (debugInterface->isRunning) { - CGuiView *view = debugInterface->GetViewScreen(); + CViewEmulatorScreen *view = debugInterface->GetViewScreen(); if (view && view->IsVisible()) { CUiThreadTaskSetViewFocus *task = new CUiThreadTaskSetViewFocus(view); @@ -884,9 +903,9 @@ void CViewC64::InitViceViews() viewC64MemoryMap->SetDataDumpView(viewC64MemoryDataDump); // - viewC64BreakpointsPC = new CViewBreakpoints("C64 PC Breakpoints", 10, 40, posZ, 400, 300, this->debugInterfaceC64->symbols, BREAKPOINT_TYPE_CPU_PC); + viewC64BreakpointsPC = new CViewBreakpoints("C64 PC Breakpoints", 10, 40, posZ, 400, 300, this->debugInterfaceC64->symbols, BREAKPOINT_TYPE_ADDR); - viewC64BreakpointsMemory = new CViewBreakpoints("C64 Memory Breakpoints", 30, 50, posZ, 400, 300, this->debugInterfaceC64->symbols, BREAKPOINT_TYPE_MEMORY); + viewC64BreakpointsMemory = new CViewBreakpoints("C64 Memory Breakpoints", 30, 50, posZ, 400, 300, this->debugInterfaceC64->symbols, BREAKPOINT_TYPE_DATA); viewC64BreakpointsRaster = new CViewBreakpoints("C64 Raster Breakpoints", 40, 40, posZ, 400, 300, this->debugInterfaceC64->symbols, BREAKPOINT_TYPE_RASTER_LINE); @@ -894,9 +913,9 @@ void CViewC64::InitViceViews() viewC64DebugEventsHistory = new CViewDebugEventsHistory("C64 Debug Events History", 180, 60, posZ, 400, 200, this->debugInterfaceC64); - viewDrive1541BreakpointsPC = new CViewBreakpoints("1541 PC Breakpoints", 60, 60, posZ, 400, 300, this->debugInterfaceC64->symbolsDrive1541, BREAKPOINT_TYPE_CPU_PC); + viewDrive1541BreakpointsPC = new CViewBreakpoints("1541 PC Breakpoints", 60, 60, posZ, 400, 300, this->debugInterfaceC64->symbolsDrive1541, BREAKPOINT_TYPE_ADDR); - viewDrive1541BreakpointsMemory = new CViewBreakpoints("1541 Memory Breakpoints", 70, 70, posZ, 400, 300, this->debugInterfaceC64->symbolsDrive1541, BREAKPOINT_TYPE_MEMORY); + viewDrive1541BreakpointsMemory = new CViewBreakpoints("1541 Memory Breakpoints", 70, 70, posZ, 400, 300, this->debugInterfaceC64->symbolsDrive1541, BREAKPOINT_TYPE_DATA); viewDrive1541BreakpointsIrq = new CViewDrive1541BreakpointsIrq("1541 IRQ Breakpoints", 80, 80, posZ, 400, 300, this->debugInterfaceC64->symbolsDrive1541); @@ -912,7 +931,7 @@ void CViewC64::InitViceViews() debugInterfaceC64->symbolsCartridgeC64, viewC64CartridgeMemoryMap, viewC64Disassembly); // - viewC64SourceCode = new CViewSourceCode("C64 Assembler source", 40, 70, posZ, 500, 350, + viewC64SourceCode = new CViewSourceCode("C64 Source code", 40, 70, posZ, 500, 350, debugInterfaceC64, debugInterfaceC64->symbols, viewC64Disassembly); // viewC64StateCIA = new CViewC64StateCIA("C64 CIA", 10, 40, posZ, 400, 200, debugInterfaceC64); @@ -1150,6 +1169,7 @@ void CViewC64::InitViceViews() // debugInterfaceC64->viewScreen = viewC64Screen; + debugInterfaceC64->viewDisassembly = viewC64Disassembly; // add timeline view to snapshots manager debugInterfaceC64->snapshotsManager->viewTimeline = viewC64Timeline; @@ -1175,9 +1195,9 @@ void CViewC64::InitAtari800Views() debugInterfaceAtari->symbols, NULL); // - viewAtariBreakpointsPC = new CViewBreakpoints("Atari PC Breakpoints", 70, 70, posZ, 200, 300, this->debugInterfaceAtari->symbols, BREAKPOINT_TYPE_CPU_PC); + viewAtariBreakpointsPC = new CViewBreakpoints("Atari PC Breakpoints", 70, 70, posZ, 200, 300, this->debugInterfaceAtari->symbols, BREAKPOINT_TYPE_ADDR); - viewAtariBreakpointsMemory = new CViewBreakpoints("Atari Memory Breakpoints", 90, 70, posZ, 200, 300, this->debugInterfaceAtari->symbols, BREAKPOINT_TYPE_MEMORY); + viewAtariBreakpointsMemory = new CViewBreakpoints("Atari Memory Breakpoints", 90, 70, posZ, 200, 300, this->debugInterfaceAtari->symbols, BREAKPOINT_TYPE_DATA); // viewAtariSourceCode = new CViewSourceCode("Atari Assembler source", 40, 70, posZ, 500, 350, @@ -1252,6 +1272,7 @@ void CViewC64::InitAtari800Views() // debugInterfaceAtari->viewScreen = viewAtariScreen; + debugInterfaceAtari->viewDisassembly = viewAtariDisassembly; // add timeline view to snapshots manager debugInterfaceAtari->snapshotsManager->viewTimeline = viewAtariTimeline; @@ -1273,9 +1294,9 @@ void CViewC64::InitNestopiaViews() debugInterfaceNes->symbols, NULL); // - viewNesBreakpointsPC = new CViewBreakpoints("NES PC Breakpoints", 70, 70, posZ, 200, 300, this->debugInterfaceNes->symbols, BREAKPOINT_TYPE_CPU_PC); + viewNesBreakpointsPC = new CViewBreakpoints("NES PC Breakpoints", 70, 70, posZ, 200, 300, this->debugInterfaceNes->symbols, BREAKPOINT_TYPE_ADDR); - viewNesBreakpointsMemory = new CViewBreakpoints("NES Memory Breakpoints", 90, 70, posZ, 200, 300, this->debugInterfaceNes->symbols, BREAKPOINT_TYPE_MEMORY); + viewNesBreakpointsMemory = new CViewBreakpoints("NES Memory Breakpoints", 90, 70, posZ, 200, 300, this->debugInterfaceNes->symbols, BREAKPOINT_TYPE_DATA); // viewNesSourceCode = new CViewSourceCode("NES Assembler source", 40, 70, posZ, 500, 350, @@ -1375,6 +1396,7 @@ void CViewC64::InitNestopiaViews() // debugInterfaceNes->viewScreen = viewNesScreen; + debugInterfaceNes->viewDisassembly = viewNesDisassembly; // add timeline view to snapshots manager debugInterfaceNes->snapshotsManager->viewTimeline = viewNesTimeline; @@ -1451,7 +1473,7 @@ void CViewC64::StartViceC64EmulationThread() // restart emulation debugInterfaceC64->isRunning = true; // debugInterfaceC64->ClearHistory(); -// debugInterfaceC64->HardReset(); +// debugInterfaceC64->ResetHard(); debugInterfaceC64->SetDebugMode(DEBUGGER_MODE_RUNNING); debugInterfaceC64->RestartAudio(); } @@ -1486,7 +1508,7 @@ void CViewC64::StartAtari800EmulationThread() // restart emulation debugInterfaceAtari->isRunning = true; // debugInterfaceAtari->ClearHistory(); -// debugInterfaceAtari->HardReset(); +// debugInterfaceAtari->ResetHard(); debugInterfaceAtari->SetDebugMode(DEBUGGER_MODE_RUNNING); debugInterfaceAtari->RestartAudio(); } @@ -1521,7 +1543,7 @@ void CViewC64::StartNestopiaEmulationThread() // restart emulation debugInterfaceNes->isRunning = true; // debugInterfaceNes->ClearHistory(); -// debugInterfaceNes->HardReset(); +// debugInterfaceNes->ResetHard(); debugInterfaceNes->SetDebugMode(DEBUGGER_MODE_RUNNING); debugInterfaceNes->audioChannel->Start(); } @@ -1728,13 +1750,15 @@ void CViewC64::Render() ////////// #ifdef RUN_COMMODORE64 + debugInterfaceC64->snapshotsManager->LockMutex(); + // copy current state of VIC c64d_vicii_copy_state(&(this->currentViciiState)); viewC64VicDisplay->UpdateViciiState(); this->UpdateViciiColors(); - + ////////// if (viewC64VicDisplay->canScrollDisassembly) @@ -1774,6 +1798,8 @@ void CViewC64::Render() } } + debugInterfaceC64->snapshotsManager->UnlockMutex(); + #endif /// @@ -2039,7 +2065,7 @@ void CViewC64::RunContinueEmulation() } } -void CViewC64::HardReset() +void CViewC64::ResetHard() { if (c64SettingsRestartAudioOnEmulationReset) { @@ -2054,57 +2080,32 @@ void CViewC64::HardReset() CDebugInterface *debugInterface = *it; debugInterface->SetDebugMode(DEBUGGER_MODE_RUNNING); } - - } - - // TODO: CViewC64::HardReset make generic & move execute markers to debug interface - if (debugInterfaceC64) - { - debugInterfaceC64->HardReset(); - debugInterfaceC64->ClearDebugMarkers(); - } - - if (debugInterfaceAtari) - { - debugInterfaceAtari->HardReset(); - debugInterfaceAtari->ClearDebugMarkers(); - } - - if (debugInterfaceNes) - { - debugInterfaceNes->ClearDebugMarkers(); - debugInterfaceNes->HardReset(); } - - if (c64SettingsIsInVicEditor) + + for (std::vector::iterator it = debugInterfaces.begin(); + it != debugInterfaces.end(); it++) { - viewC64->viewC64VicControl->UnlockAll(); + CDebugInterface *debugInterface = *it; + debugInterface->ResetHard(); + debugInterface->ClearDebugMarkers(); } } -void CViewC64::SoftReset() +void CViewC64::ResetSoft() { if (c64SettingsRestartAudioOnEmulationReset) { // TODO: gSoundEngine->RestartAudioUnit(); } - // TODO: make a list of avaliable interfaces and iterate - if (debugInterfaceC64) - { - debugInterfaceC64->Reset(); - } - - if (debugInterfaceAtari) - { - debugInterfaceAtari->Reset(); - } - - if (debugInterfaceNes) + for (std::vector::iterator it = debugInterfaces.begin(); + it != debugInterfaces.end(); it++) { - debugInterfaceNes->Reset(); + CDebugInterface *debugInterface = *it; + debugInterface->ResetSoft(); + debugInterface->ClearDebugMarkers(); } - + if (c64SettingsIsInVicEditor) { viewC64->viewC64VicControl->UnlockAll(); @@ -2324,7 +2325,7 @@ bool CViewC64::KeyDownRepeat(u32 keyCode, bool isShift, bool isAlt, bool isContr // if emulator screen has focus then it takes precedence for (CDebugInterface *debugInterface : debugInterfaces) { - CGuiView *view = debugInterface->GetViewScreen(); + CViewEmulatorScreen *view = debugInterface->GetViewScreen(); if (view && view->HasFocus()) { view->KeyDownRepeat(keyCode, isShift, isAlt, isControl, isSuper); @@ -2372,7 +2373,7 @@ bool CViewC64::KeyDown(u32 keyCode, bool isShift, bool isAlt, bool isControl, bo // if emulator screen has focus then it takes precedence for (CDebugInterface *debugInterface : debugInterfaces) { - CGuiView *view = debugInterface->GetViewScreen(); + CViewEmulatorScreen *view = debugInterface->GetViewScreen(); if (view && view->HasFocus()) { if (view->KeyDown(keyCode, isShift, isAlt, isControl, isSuper)) @@ -2579,7 +2580,7 @@ bool CViewC64::PostKeyDown(u32 keyCode, bool isShift, bool isAlt, bool isControl // not consumed key send to screen for (CDebugInterface *debugInterface : debugInterfaces) { - CGuiView *view = debugInterface->GetViewScreen(); + CViewEmulatorScreen *view = debugInterface->GetViewScreen(); if (view->IsVisible()) { if (view->KeyDown(keyCode, isShift, isAlt, isControl, isSuper)) @@ -2659,7 +2660,7 @@ bool CViewC64::KeyUp(u32 keyCode, bool isShift, bool isAlt, bool isControl, bool if (!debugInterface->isRunning) continue; - CGuiView *viewScreen = debugInterface->GetViewScreen(); + CViewEmulatorScreen *viewScreen = debugInterface->GetViewScreen(); if (!viewScreen) continue; @@ -2676,7 +2677,7 @@ bool CViewC64::KeyUp(u32 keyCode, bool isShift, bool isAlt, bool isControl, bool if (!debugInterface->isRunning) continue; - CGuiView *viewScreen = debugInterface->GetViewScreen(); + CViewEmulatorScreen *viewScreen = debugInterface->GetViewScreen(); if (!viewScreen) continue; @@ -2747,18 +2748,22 @@ bool CViewC64::DoNotTouchedMove(float x, float y) { LOGG("CViewC64::DoNotTouchedMove, mouseCursor=%f %f", mouseCursorX, mouseCursorY); + mouseCursorX = x; + mouseCursorY = y; + + if (c64SettingsEmulatedMouseC64Enabled && c64SettingsEmulatedMouseCursorAutoHide) + { + // do not show mouse cursor on mouse move when emulated mouse is autohide or grabbed + return false; + } + if (guiMain->IsMouseCursorVisible() == false) { guiMain->SetMouseCursorVisible(true); mouseCursorVisibilityCounter = 0; } - - mouseCursorX = x; - mouseCursorY = y; return false; - - return CGuiView::DoNotTouchedMove(x, y); } bool CViewC64::DoScrollWheel(float deltaX, float deltaY) @@ -3155,10 +3160,10 @@ void CViewC64::CheckMouseCursorVisibility() // cursor is already hidden return; } - - // cursor is visible - if (mouseCursorNumFramesToHideCursor > 0 - && mouseCursorVisibilityCounter > mouseCursorNumFramesToHideCursor) + + // we are full screen, do we need to grab cursor by emulated mouse? + if (c64SettingsEmulatedMouseC64Enabled && guiMain->viewFullScreen == viewC64Screen + && c64SettingsEmulatedMouseCursorAutoHide) { // hide cursor guiMain->SetMouseCursorVisible(false); @@ -3166,19 +3171,44 @@ void CViewC64::CheckMouseCursorVisibility() } else { - mouseCursorVisibilityCounter++; + // cursor is visible, wait till mouseCursorNumFramesToHideCursor and hide + if (mouseCursorNumFramesToHideCursor > 0 + && mouseCursorVisibilityCounter > mouseCursorNumFramesToHideCursor) + { + // hide cursor + guiMain->SetMouseCursorVisible(false); + mouseCursorVisibilityCounter = 0; + } + else + { + mouseCursorVisibilityCounter++; + } } } else { - // not fullscreen, show cursor - if (guiMain->IsMouseCursorVisible() == false) + // not fullscreen + if (c64SettingsEmulatedMouseC64Enabled && c64SettingsEmulatedMouseCursorAutoHide) { - mouseCursorVisibilityCounter = 0; - guiMain->SetMouseCursorVisible(true); + // hide mouse cursor when on c64 screen + if (viewC64Screen->IsInsideView(guiMain->mousePosX, guiMain->mousePosY)) + { + guiMain->SetMouseCursorVisible(false); + } + else + { + guiMain->SetMouseCursorVisible(true); + } + } + else + { + if (guiMain->IsMouseCursorVisible() == false) + { + mouseCursorVisibilityCounter = 0; + guiMain->SetMouseCursorVisible(true); + } } } - } void CViewC64::ShowMouseCursor() @@ -3747,6 +3777,34 @@ char *CViewC64::ATRD_GetPathForRoms_IMPL() return buf; } +void CViewC64::DebuggerServerWebSocketsStart() +{ + if (debuggerServer != NULL) + { + if (debuggerServer->isRunning) + { + LOGWarning("CViewC64::DebuggerServerWebSocketsStart: debuggerServer != NULL and isRunning=true"); + } + else + { + debuggerServer->Start(); + } + } + else + { + debuggerServer = REMOTE_CreateDebuggerServerWebSockets(c64SettingsRunDebuggerServerWebSocketsPort); + debuggerServer->Start(); + } +} + +void CViewC64::DebuggerServerWebSocketsSetPort(int port) +{ + if (this->debuggerServer) + { + REMOTE_DebuggerServerWebSocketsSetPort(this->debuggerServer, port); + } +} + void CViewC64::ApplicationShutdown() { LOGD("CViewC64::ApplicationShutdown"); @@ -3774,12 +3832,12 @@ void CViewC64::ApplicationShutdown() std::set CViewC64::GetSupportedFileExtensions() { std::set extensions = { - u8"prg", u8"d64", u8"x64", u8"g64", u8"p64", u8"crt", u8"reu", u8"sid", u8"snap", u8"vsf", u8"tap", u8"t64", - u8"xex", u8"obx", u8"atr", u8"a8s", - u8"sap", u8"cmc", u8"cm3", u8"cmr", u8"cms", u8"dmc", u8"dlt", u8"fc", u8"mpt", u8"mpd", u8"rmt", u8"tmc", u8"tm8", u8"tm2", u8"stil", - u8"nes", - u8"c64jukebox", u8"rtdl", u8"rdtl", - u8"png", u8"jpg", u8"jpeg", u8"bmp", u8"gif", u8"psd", u8"pic", u8"hdr", u8"tga", u8"kla", u8"dd", u8"ddl", u8"aas", u8"art", u8"vce" + "prg", "d64", "x64", "g64", "p64", "crt", "reu", "sid", "snap", "vsf", "tap", "t64", + "xex", "obx", "atr", "a8s", + "sap", "cmc", "cm3", "cmr", "cms", "dmc", "dlt", "fc", "mpt", "mpd", "rmt", "tmc", "tm8", "tm2", "stil", + "nes", + "c64jukebox", "rtdl", "rdtl", + "png", "jpg", "jpeg", "bmp", "gif", "psd", "pic", "hdr", "tga", "kla", "dd", "ddl", "aas", "art", "vce" }; return extensions; } @@ -3799,14 +3857,14 @@ void CViewC64::GlobalDropFileCallback(char *filePath, bool consumedByView) } CSlrString *slrPath = new CSlrString(filePath); - viewC64->viewC64MainMenu->LoadFile(slrPath); + viewC64->mainMenuHelper->LoadFile(slrPath); delete slrPath; } } void CViewC64::RecentlyOpenedFilesCallbackSelectedMenuItem(CSlrString *filePath) { - viewC64->viewC64MainMenu->LoadFile(filePath); + viewC64->mainMenuHelper->LoadFile(filePath); } void CViewC64::ViewFileBrowserCallbackOpenFile(fs::path path) @@ -3819,10 +3877,10 @@ void CViewC64::ViewFileBrowserCallbackOpenFile(fs::path path) void CViewC64::OpenFile(CSlrString *path) { - viewC64->viewC64MainMenu->LoadFile(path); + viewC64->mainMenuHelper->LoadFile(path); } void CViewC64::OpenFileDialog() { - viewC64->viewC64MainMenu->OpenDialogOpenFile(); + viewC64->mainMenuHelper->OpenDialogOpenFile(); } diff --git a/src/Screens/CViewC64.h b/src/Screens/CViewC64.h index a9704b8..197cce9 100644 --- a/src/Screens/CViewC64.h +++ b/src/Screens/CViewC64.h @@ -15,7 +15,7 @@ #include "SYS_Threading.h" #include "SYS_Defs.h" #include "SYS_PauseResume.h" -#include "CViewMainMenu.h" +#include "CMainMenuHelper.h" #include "CViewSettingsMenu.h" #include "SYS_SharedMemory.h" #include "CGuiViewSaveFile.h" @@ -133,7 +133,7 @@ class CViewNesPpuPalette; class CViewNesPianoKeyboard; class CViewJukeboxPlaylist; -class CViewMainMenu; +class CMainMenuHelper; class CViewSettingsMenu; class CViewDrive1541Browser; class CViewC64KeyMap; @@ -141,12 +141,14 @@ class CViewKeyboardShortcuts; class CViewSnapshots; class CViewColodore; class CViewAbout; - class CViewAudioMixer; -class CMainMenuBar; +class CMainMenuBar; class CColorsTheme; +class CPipeProtocolDebuggerCallback; +class CDebuggerServer; + class CEmulationThreadC64 : public CSlrThread { void ThreadRun(void *data); @@ -247,7 +249,7 @@ class CViewC64 : public CGuiView, CGuiButtonCallback, CApplicationPauseResumeLis CGuiViewMessages *viewMessages; CViewFileBrowser *viewFileBrowser; - CViewMainMenu *viewC64MainMenu; + CMainMenuHelper *mainMenuHelper; CViewSettingsMenu *viewC64SettingsMenu; CViewC64KeyMap *viewC64KeyMap; CViewKeyboardShortcuts *viewKeyboardShortcuts; @@ -481,8 +483,8 @@ class CViewC64 : public CGuiView, CGuiButtonCallback, CApplicationPauseResumeLis void StepOneCycle(); void StepBackInstruction(); void RunContinueEmulation(); - void HardReset(); - void SoftReset(); + void ResetHard(); + void ResetSoft(); void SwitchIsDataDirectlyFromRam(); void SwitchIsDataDirectlyFromRam(bool isFromRam); @@ -616,6 +618,10 @@ class CViewC64 : public CGuiView, CGuiButtonCallback, CApplicationPauseResumeLis virtual std::set GetSupportedFileExtensions(); virtual void GlobalDropFileCallback(char *filePath, bool consumedByView); + // + void DebuggerServerWebSocketsStart(); + void DebuggerServerWebSocketsSetPort(int port); + // CRecentlyOpenedFiles *recentlyOpenedFiles; virtual void RecentlyOpenedFilesCallbackSelectedMenuItem(CSlrString *filePath); @@ -628,6 +634,10 @@ class CViewC64 : public CGuiView, CGuiButtonCallback, CApplicationPauseResumeLis // void OpenFileDialog(); void OpenFile(CSlrString *path); + + // remote debugger + CPipeProtocolDebuggerCallback *pipeProtocolCallback; + CDebuggerServer *debuggerServer; }; extern CViewC64 *viewC64; diff --git a/src/Screens/CViewColodore.cpp b/src/Screens/CViewColodore.cpp index bdde5df..d839d69 100644 --- a/src/Screens/CViewColodore.cpp +++ b/src/Screens/CViewColodore.cpp @@ -176,7 +176,7 @@ void CViewColodore::SwitchAboutScreen() { if (guiMain->currentView == this) { - guiMain->SetView(viewC64->viewC64MainMenu); + guiMain->SetView(viewC64->mainMenuHelper); } else { diff --git a/src/Screens/CViewSettingsMenu.cpp b/src/Screens/CViewSettingsMenu.cpp index b629a5a..2168942 100644 --- a/src/Screens/CViewSettingsMenu.cpp +++ b/src/Screens/CViewSettingsMenu.cpp @@ -876,7 +876,7 @@ void CViewSettingsMenu::MenuCallbackItemEntered(CGuiViewMenuItem *menuItem) } else if (menuItem == menuItemStartJukeboxPlaylist) { - viewC64->viewC64MainMenu->OpenDialogStartJukeboxPlaylist(); + viewC64->mainMenuHelper->OpenDialogStartJukeboxPlaylist(); } else if (menuItem == menuItemClearSettings) { diff --git a/src/Screens/CViewSnapshots.cpp b/src/Screens/CViewSnapshots.cpp index 8eb1c8d..932fe20 100644 --- a/src/Screens/CViewSnapshots.cpp +++ b/src/Screens/CViewSnapshots.cpp @@ -25,7 +25,7 @@ extern "C" { #include "CViewDataMap.h" #include "CGuiMain.h" -#include "CViewMainMenu.h" +#include "CMainMenuHelper.h" #include "CDebugInterface.h" #include "CDebugInterfaceC64.h" @@ -826,7 +826,7 @@ void CSnapshotUpdateThread::ThreadRun(void *data) SYS_Sleep(200); - viewC64->debugInterfaceC64->HardReset(); + viewC64->debugInterfaceC64->ResetHard(); } // perform update diff --git a/src/Tools/C64CommandLine.cpp b/src/Tools/C64CommandLine.cpp index b715620..323305d 100644 --- a/src/Tools/C64CommandLine.cpp +++ b/src/Tools/C64CommandLine.cpp @@ -5,7 +5,7 @@ #include "CViewC64.h" #include "SYS_CommandLine.h" #include "CDebugSymbols.h" -#include "CViewMainMenu.h" +#include "CMainMenuHelper.h" #include "CViewSnapshots.h" #include "CSlrString.h" #include "RES_ResourceManager.h" @@ -669,12 +669,12 @@ void c64PerformStartupTasksThreaded() { SYS_Sleep(100); } - viewC64->viewC64MainMenu->InsertD64(c64SettingsPathToD64, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + viewC64->mainMenuHelper->InsertD64(c64SettingsPathToD64, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); } else { // just load disk, do not start, we will start PRG instead - viewC64->viewC64MainMenu->InsertD64(c64SettingsPathToD64, false, false, 0, false); + viewC64->mainMenuHelper->InsertD64(c64SettingsPathToD64, false, false, 0, false); } } @@ -693,14 +693,14 @@ void c64PerformStartupTasksThreaded() // else { // just load tape, do not start - viewC64->viewC64MainMenu->LoadTape(c64SettingsPathToTAP, false, false, false); + viewC64->mainMenuHelper->LoadTape(c64SettingsPathToTAP, false, false, false); } } if (c64SettingsPathToCartridge != NULL) { - viewC64->viewC64MainMenu->InsertCartridge(c64SettingsPathToCartridge, false); + viewC64->mainMenuHelper->InsertCartridge(c64SettingsPathToCartridge, false); SYS_Sleep(666); } } @@ -716,13 +716,18 @@ void c64PerformStartupTasksThreaded() } else //if (isPRGInCommandLine == true) { - viewC64->viewC64MainMenu->LoadPRG(c64SettingsPathToPRG, cmdLineOptionDoAutoJmp, false, true, false); + viewC64->mainMenuHelper->LoadPRG(c64SettingsPathToPRG, cmdLineOptionDoAutoJmp, false, true, false); } } if (c64CommandLineHardReset) { - viewC64->debugInterfaceC64->HardReset(); + viewC64->debugInterfaceC64->ResetHard(); + } + + if (c64SettingsEmulatedMouseC64Enabled) + { + viewC64->debugInterfaceC64->EmulatedMouseUpdateSettings(); } } @@ -757,13 +762,13 @@ void c64PerformStartupTasksThreaded() { SYS_Sleep(100); } - viewC64->viewC64MainMenu->InsertATR(c64SettingsPathToATR, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + viewC64->mainMenuHelper->InsertATR(c64SettingsPathToATR, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); } else { // just load disk, do not start, we will start XEX instead - viewC64->viewC64MainMenu->InsertATR(c64SettingsPathToATR, false, false, 0, false); + viewC64->mainMenuHelper->InsertATR(c64SettingsPathToATR, false, false, 0, false); } } @@ -796,7 +801,7 @@ void c64PerformStartupTasksThreaded() if (c64CommandLineHardReset) { - viewC64->debugInterfaceAtari->HardReset(); + viewC64->debugInterfaceAtari->ResetHard(); } } @@ -811,7 +816,7 @@ void c64PerformStartupTasksThreaded() } else //if (isXEXInCommandLine == true) { - viewC64->viewC64MainMenu->LoadXEX(c64SettingsPathToXEX, cmdLineOptionDoAutoJmp, false, true); + viewC64->mainMenuHelper->LoadXEX(c64SettingsPathToXEX, cmdLineOptionDoAutoJmp, false, true); } } @@ -823,7 +828,7 @@ void c64PerformStartupTasksThreaded() { if (c64SettingsPathToNES != NULL) { - viewC64->viewC64MainMenu->LoadNES(c64SettingsPathToNES, false); + viewC64->mainMenuHelper->LoadNES(c64SettingsPathToNES, false); } } @@ -1381,38 +1386,38 @@ void c64PerformNewConfigurationTasksThreaded(CByteBuffer *byteBuffer) else if (t == C64D_PASS_CONFIG_DATA_PATH_TO_D64) { CSlrString *str = byteBuffer->GetSlrString(); - viewC64->viewC64MainMenu->InsertD64(str, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + viewC64->mainMenuHelper->InsertD64(str, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); delete str; } else if (t == C64D_PASS_CONFIG_DATA_PATH_TO_TAP) { CSlrString *str = byteBuffer->GetSlrString(); - viewC64->viewC64MainMenu->LoadTape(str, false, false, true); + viewC64->mainMenuHelper->LoadTape(str, false, false, true); delete str; } else if (t == C64D_PASS_CONFIG_DATA_PATH_TO_CRT) { CSlrString *str = byteBuffer->GetSlrString(); - viewC64->viewC64MainMenu->InsertCartridge(str, false); + viewC64->mainMenuHelper->InsertCartridge(str, false); SYS_Sleep(666); delete str; } else if (t == C64D_PASS_CONFIG_DATA_PATH_TO_XEX) { CSlrString *str = byteBuffer->GetSlrString(); - viewC64->viewC64MainMenu->LoadXEX(str, cmdLineOptionDoAutoJmp, false, true); + viewC64->mainMenuHelper->LoadXEX(str, cmdLineOptionDoAutoJmp, false, true); delete str; } else if (t == C64D_PASS_CONFIG_DATA_PATH_TO_ATR) { CSlrString *str = byteBuffer->GetSlrString(); - viewC64->viewC64MainMenu->InsertATR(str, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + viewC64->mainMenuHelper->InsertATR(str, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); delete str; } else if (t == C64D_PASS_CONFIG_DATA_PATH_TO_NES) { CSlrString *str = byteBuffer->GetSlrString(); - viewC64->viewC64MainMenu->LoadNES(str, true); + viewC64->mainMenuHelper->LoadNES(str, true); delete str; } else if (t == C64D_PASS_CONFIG_DATA_SET_AUTOJMP) @@ -1438,7 +1443,7 @@ void c64PerformNewConfigurationTasksThreaded(CByteBuffer *byteBuffer) else if (t == C64D_PASS_CONFIG_DATA_PATH_TO_PRG) { CSlrString *str = byteBuffer->GetSlrString(); - viewC64->viewC64MainMenu->LoadPRG(str, cmdLineOptionDoAutoJmp, false, true, false); + viewC64->mainMenuHelper->LoadPRG(str, cmdLineOptionDoAutoJmp, false, true, false); delete str; } // else if (t == C64D_PASS_CONFIG_DATA_LAYOUT) @@ -1471,7 +1476,7 @@ void c64PerformNewConfigurationTasksThreaded(CByteBuffer *byteBuffer) } else if (t == C64D_PASS_CONFIG_DATA_HARD_RESET) { - debugInterface->HardReset(); + debugInterface->ResetHard(); } else if (t == C64D_PASS_CONFIG_DATA_FULL_SCREEN) { diff --git a/src/Tools/C64SettingsStorage.cpp b/src/Tools/C64SettingsStorage.cpp index 6d99b4b..0b6fe70 100644 --- a/src/Tools/C64SettingsStorage.cpp +++ b/src/Tools/C64SettingsStorage.cpp @@ -79,7 +79,7 @@ bool c64SettingsPassConfigToRunningInstance = false; int c64SettingsScreenSupersampleFactor = 4; bool c64SettingsEmulatorScreenBypassKeyboardShortcuts = true; -bool c64SettingsUsePipeIntegration = true; +bool c64SettingsUsePipeIntegration = false; bool c64SettingsWindowAlwaysOnTop = false; CByteBuffer *c64SettingsWindowPosition = NULL; @@ -256,6 +256,11 @@ bool c64SettingsRunSIDWhenInWarp = true; u8 c64SettingsSelectedJoystick1 = 0; u8 c64SettingsSelectedJoystick2 = 0; +bool c64SettingsEmulatedMouseC64Enabled = false; +int c64SettingsEmulatedMouseC64Type = 0; +u8 c64SettingsEmulatedMouseC64Port = 0; +bool c64SettingsEmulatedMouseCursorAutoHide = true; + // float c64SettingsPaintGridCharactersColorR = 0.7f; float c64SettingsPaintGridCharactersColorG = 0.7f; @@ -302,7 +307,11 @@ u8 c64SettingsAtariVideoSystem = ATARI_VIDEO_SYSTEM_PAL; u8 c64SettingsAtariMachineType = 4; u8 c64SettingsAtariRamSizeOption = 9; +// websockets server +bool c64SettingsRunDebuggerServerWebSockets = false; +int c64SettingsRunDebuggerServerWebSocketsPort = 0x0DEB; +//// void storeSettingBlock(CByteBuffer *byteBuffer, u8 value) { byteBuffer->PutU8(C64DEBUGGER_SETTING_BLOCK); @@ -555,6 +564,12 @@ void C64DebuggerStoreSettings() storeSettingU8(byteBuffer, "SelectedJoystick1", c64SettingsSelectedJoystick1); storeSettingU8(byteBuffer, "SelectedJoystick2", c64SettingsSelectedJoystick2); + // + storeSettingU8(byteBuffer, "EmulatedMouseCursorAutoHide", c64SettingsEmulatedMouseCursorAutoHide); + storeSettingBool(byteBuffer, "EmulatedMouseC64Enabled", c64SettingsEmulatedMouseC64Enabled); + storeSettingI32(byteBuffer, "EmulatedMouseC64Type", c64SettingsEmulatedMouseC64Type); + storeSettingU8(byteBuffer, "EmulatedMouseC64Port", c64SettingsEmulatedMouseC64Port); + // storeSettingU8(byteBuffer, "DisassemblyBackgroundColor", c64SettingsDisassemblyBackgroundColor); storeSettingU8(byteBuffer, "DisassemblyExecuteColor", c64SettingsDisassemblyExecuteColor); @@ -583,14 +598,16 @@ void C64DebuggerStoreSettings() storeSettingI32(byteBuffer, "SnapshotsManagerStoreInterval", c64SettingsSnapshotsIntervalNumFrames); storeSettingI32(byteBuffer, "SnapshotsManagerLimit", c64SettingsSnapshotsLimit); storeSettingU8(byteBuffer, "SnapshotsManagerSaveZlibCompressionLevel", c64SettingsTimelineSaveZlibCompressionLevel); - + storeSettingBlock(byteBuffer, C64DEBUGGER_BLOCK_EOF); // new settings gApplicationDefaultConfig->SetBoolSkipConfigSave("DisassemblyPressCtrlToSetBreakpoint", &c64SettingsPressCtrlToSetBreakpoint); gApplicationDefaultConfig->SetBoolSkipConfigSave("AlwaysUnpauseEmulationAfterReset", &c64SettingsAlwaysUnpauseEmulationAfterReset); gApplicationDefaultConfig->SetBoolSkipConfigSave("EmulatorScreenBypassKeyboardShortcuts", &c64SettingsEmulatorScreenBypassKeyboardShortcuts); - + gApplicationDefaultConfig->SetBoolSkipConfigSave("RunDebuggerServerWebSockets", &c64SettingsRunDebuggerServerWebSockets); + gApplicationDefaultConfig->SetIntSkipConfigSave("RunDebuggerServerWebSocketsPort", &c64SettingsRunDebuggerServerWebSocketsPort); + #if !defined(DEBUG_SETTINGS_FILE_PATH) LOGD("C64D_SETTINGS_FILE_PATH is set to=%s", C64D_SETTINGS_FILE_PATH); CSlrString *fileName = new CSlrString(C64D_SETTINGS_FILE_PATH); @@ -667,10 +684,13 @@ void C64DebuggerRestoreSettings(uint8 settingsBlockType) gApplicationDefaultConfig->GetBool("DisassemblyPressCtrlToSetBreakpoint", &c64SettingsPressCtrlToSetBreakpoint, false); gApplicationDefaultConfig->GetBool("AlwaysUnpauseEmulationAfterReset", &c64SettingsAlwaysUnpauseEmulationAfterReset, true); gApplicationDefaultConfig->GetBool("EmulatorScreenBypassKeyboardShortcuts", &c64SettingsEmulatorScreenBypassKeyboardShortcuts, true); - + gApplicationDefaultConfig->GetBool("DisassemblyUseNearLabels", &c64SettingsDisassemblyUseNearLabels, true); gApplicationDefaultConfig->GetBool("DisassemblyUseNearLabelsForJumps", &c64SettingsDisassemblyUseNearLabelsForJumps, false); gApplicationDefaultConfig->GetInt("DisassemblyNearLabelMaxOffset", &c64SettingsDisassemblyNearLabelMaxOffset, 6); + + gApplicationDefaultConfig->GetBool("RunDebuggerServerWebSockets", &c64SettingsRunDebuggerServerWebSockets, false); + gApplicationDefaultConfig->GetInt("RunDebuggerServerWebSocketsPort", &c64SettingsRunDebuggerServerWebSocketsPort, 0x0DEB); } void C64DebuggerReadSettingsValues(CByteBuffer *byteBuffer, uint8 settingsBlockType) @@ -937,7 +957,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceC64 && viewC64->debugInterfaceC64->isRunning) { - viewC64->viewC64MainMenu->InsertD64(c64SettingsPathToD64, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + viewC64->mainMenuHelper->InsertD64(c64SettingsPathToD64, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); } return; } @@ -952,7 +972,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceC64 && viewC64->debugInterfaceC64->isRunning) { - viewC64->viewC64MainMenu->LoadPRG(c64SettingsPathToPRG, false, false, true, false); + viewC64->mainMenuHelper->LoadPRG(c64SettingsPathToPRG, false, false, true, false); } return; } @@ -965,7 +985,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceC64 && viewC64->debugInterfaceC64->isRunning) { - viewC64->viewC64MainMenu->LoadTape(c64SettingsPathToTAP, false, false, false); + viewC64->mainMenuHelper->LoadTape(c64SettingsPathToTAP, false, false, false); } return; } @@ -979,7 +999,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceC64 && viewC64->debugInterfaceC64->isRunning) { - viewC64->viewC64MainMenu->InsertCartridge(c64SettingsPathToCartridge, false); + viewC64->mainMenuHelper->InsertCartridge(c64SettingsPathToCartridge, false); } return; } @@ -1544,7 +1564,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceAtari && viewC64->debugInterfaceAtari->isRunning) { - viewC64->viewC64MainMenu->InsertATR(c64SettingsPathToATR, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); + viewC64->mainMenuHelper->InsertATR(c64SettingsPathToATR, false, c64SettingsAutoJmpFromInsertedDiskFirstPrg, 0, true); } return; } @@ -1566,7 +1586,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceAtari && viewC64->debugInterfaceAtari->isRunning) { - viewC64->viewC64MainMenu->LoadXEX(c64SettingsPathToXEX, false, false, true); + viewC64->mainMenuHelper->LoadXEX(c64SettingsPathToXEX, false, false, true); } return; } @@ -1589,7 +1609,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceAtari && viewC64->debugInterfaceAtari->isRunning) { - viewC64->viewC64MainMenu->LoadCAS(c64SettingsPathToCAS, false, false, true); + viewC64->mainMenuHelper->LoadCAS(c64SettingsPathToCAS, false, false, true); } return; } @@ -1612,7 +1632,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceAtari && viewC64->debugInterfaceAtari->isRunning) { - viewC64->viewC64MainMenu->InsertAtariCartridge(c64SettingsPathToAtariCartridge, false, false, true); + viewC64->mainMenuHelper->InsertAtariCartridge(c64SettingsPathToAtariCartridge, false, false, true); } return; } @@ -1679,7 +1699,7 @@ void C64DebuggerSetSetting(const char *name, void *value) // the setting will be updated later by c64PerformStartupTasksThreaded if (viewC64->debugInterfaceNes && viewC64->debugInterfaceNes->isRunning) { - viewC64->viewC64MainMenu->LoadNES(c64SettingsPathToNES, false); + viewC64->mainMenuHelper->LoadNES(c64SettingsPathToNES, false); } return; } @@ -1887,6 +1907,31 @@ void C64DebuggerSetSetting(const char *name, void *value) viewC64->mainMenuBar->selectedJoystick2 = v; return; } + else if (!strcmp(name, "EmulatedMouseCursorAutoHide")) + { + bool v = *((bool*)value); + c64SettingsEmulatedMouseCursorAutoHide = v; + return; + } + + else if (!strcmp(name, "EmulatedMouseC64Enabled")) + { + bool v = *((bool*)value); + c64SettingsEmulatedMouseC64Enabled = v; + return; + } + else if (!strcmp(name, "EmulatedMouseC64Type")) + { + i32 v = *((i32*)value); + c64SettingsEmulatedMouseC64Type = v; + return; + } + else if (!strcmp(name, "EmulatedMouseC64Port")) + { + u8 v = *((u8*)value); + c64SettingsEmulatedMouseC64Port = v; + return; + } else if (!strcmp(name, "DisassemblyBackgroundColor")) { u8 v = *((u8*)value); diff --git a/src/Tools/C64SettingsStorage.h b/src/Tools/C64SettingsStorage.h index 067b663..fcab0b1 100644 --- a/src/Tools/C64SettingsStorage.h +++ b/src/Tools/C64SettingsStorage.h @@ -127,6 +127,11 @@ extern bool c64SettingsShowPositionsInHex; extern u8 c64SettingsSelectedJoystick1; extern u8 c64SettingsSelectedJoystick2; +extern bool c64SettingsEmulatedMouseCursorAutoHide; +extern bool c64SettingsEmulatedMouseC64Enabled; +extern int c64SettingsEmulatedMouseC64Type; +extern u8 c64SettingsEmulatedMouseC64Port; + // startup extern int c64SettingsWaitOnStartup; extern CSlrString *c64SettingsPathToRomsC64; @@ -272,6 +277,10 @@ extern bool c64SettingsRunVice; extern bool c64SettingsRunAtari800; extern bool c64SettingsRunNestopia; +// debugger websockets server +extern bool c64SettingsRunDebuggerServerWebSockets; +extern int c64SettingsRunDebuggerServerWebSocketsPort; + // set setting void C64DebuggerSetSetting(const char *name, void *value); void C64DebuggerSetSettingInt(const char *settingName, int param); diff --git a/src/Tools/CSnapshotsManager.cpp b/src/Tools/CSnapshotsManager.cpp index 0036e11..686f3ff 100644 --- a/src/Tools/CSnapshotsManager.cpp +++ b/src/Tools/CSnapshotsManager.cpp @@ -3,6 +3,7 @@ #include "VID_Main.h" #include "CGuiMain.h" #include "CViewC64.h" +#include "CDebugMemory.h" #include "SND_SoundEngine.h" #include "C64SettingsStorage.h" #include "CSlrFileFromOS.h" @@ -486,6 +487,9 @@ bool CSnapshotsManager::CheckSnapshotRestore() // TODO: WTF c64d_reset_sound_clk? generalize c64d_reset_sound_clk(); + // clear all history events after restored cycle (mem write history, execute history) + debugInterface->symbols->memory->ClearEventsAfterCycle(snapshotToRestore->cycle); + gSoundEngine->UnlockMutex("CSnapshotsManager::CheckSnapshotRestore: restore snapshot"); LOGS("CSnapshotsManager::CheckSnapshotRestore: UnlockMutex (1)"); diff --git a/src/Views/C64/CViewC64KeyMap.cpp b/src/Views/C64/CViewC64KeyMap.cpp index 2a2054d..35b8a13 100644 --- a/src/Views/C64/CViewC64KeyMap.cpp +++ b/src/Views/C64/CViewC64KeyMap.cpp @@ -1362,7 +1362,7 @@ void CViewC64KeyMap::SwitchScreen() { if (guiMain->currentView == this) { - guiMain->SetView(viewC64->viewC64MainMenu); + guiMain->SetView(viewC64->mainMenuHelper); } else { diff --git a/src/Views/C64/CViewC64Screen.cpp b/src/Views/C64/CViewC64Screen.cpp index 72c905b..f8cab76 100644 --- a/src/Views/C64/CViewC64Screen.cpp +++ b/src/Views/C64/CViewC64Screen.cpp @@ -4,6 +4,8 @@ #include "CColorsTheme.h" #include "C64SettingsStorage.h" +#include "CDebugInterfaceVice.h" + CViewC64Screen::CViewC64Screen(const char *name, float posX, float posY, float posZ, float sizeX, float sizeY, CDebugInterface *debugInterface) : CViewEmulatorScreen(name, posX, posY, posZ, sizeX, sizeY, debugInterface) @@ -142,6 +144,131 @@ void CViewC64Screen::UpdateRasterCrossFactors() rasterCrossSizeX34 = rasterCrossSizeX2+rasterCrossSizeX4; rasterCrossSizeY34 = rasterCrossSizeY2+rasterCrossSizeY4; } + +//// debug +//static int tx = 0; +//static int ty = 50; + +// mouse +bool CViewC64Screen::DoTap(float x, float y) +{ + CDebugInterfaceVice *vice = (CDebugInterfaceVice*)viewC64->debugInterfaceC64; + vice->EmulatedMouseButtonLeft(true); + +// tx = 0; +// ty = 50; + + return true; +} + +bool CViewC64Screen::DoFinishTap(float x, float y) +{ + CDebugInterfaceVice *vice = (CDebugInterfaceVice*)viewC64->debugInterfaceC64; + vice->EmulatedMouseButtonLeft(false); + return true; +} + +bool CViewC64Screen::DoRightClick(float x, float y) +{ + CDebugInterfaceVice *vice = (CDebugInterfaceVice*)viewC64->debugInterfaceC64; + vice->EmulatedMouseButtonRight(true); + return true; +} + +bool CViewC64Screen::DoFinishRightClick(float x, float y) +{ + CDebugInterfaceVice *vice = (CDebugInterfaceVice*)viewC64->debugInterfaceC64; + vice->EmulatedMouseButtonRight(false); + return true; +} + +bool CViewC64Screen::DoNotTouchedMove(float x, float y) +{ + CDebugInterfaceVice *vice = (CDebugInterfaceVice*)viewC64->debugInterfaceC64; + + if (IsInside(x, y) == false) + return false; + + float mx = x - this->posX; + float my = y - this->posY; + + float fx = mx / sizeX; + float fy = my / sizeY; + +// LOGD("mx=%5.2f my=%5.2f sx=%5.2f sy=%5.2f fx=%5.3f fy=%5.3f", mx, my, this->sizeX, this->sizeY, fx, fy); + + float rx = fx * 475.0f; //950.0f; + float ry = 400 - (fy * 400.0f); + +// LOGD("rx=%5.2f ry=%5.2f", rx, ry); + + // 817 + 136=950 + + if (rx < 0) + rx = 0; + if (ry < 0) + ry = 0; + +// debug +// tx++; ty++; +// vice->EmulatedMouseSetPosition((int)tx, ty); + + vice->EmulatedMouseSetPosition((int)rx, ry); + +// LOGD("tx=%d ty=%d", tx, ty); + + // NOTE, hiding mouse was moved to CViewC64 as a workaround +// if (this->IsInsideView(x, y)) +// { +// LOGD("x=%f y=%f INSIDE"); +// guiMain->SetMouseCursorVisible(false); +// } +// else +// { +// LOGD("x=%f y=%f NOT INSIDE"); +// guiMain->SetMouseCursorVisible(true); +// } + +// vice->EmulatedMouseSetPosition(x, y); + return CViewEmulatorScreen::DoNotTouchedMove(x, y); +} + +bool CViewC64Screen::DoScrollWheel(float deltaX, float deltaY) +{ + return CViewEmulatorScreen::DoFinishTap(deltaX, deltaY); +} + +bool CViewC64Screen::ShouldAutoHideMouse() +{ + if (ImGui::IsPopupOpen("CGuiViewContextMenu")) + return false; + + if (c64SettingsEmulatedMouseC64Enabled) + { + if (IsInsideView(guiMain->mousePosX, guiMain->mousePosY)) + { + return true; + } + } + return false; +} + +bool CViewC64Screen::HasContextMenuItems() +{ + if (ImGui::IsPopupOpen("CGuiViewContextMenu")) + return true; + + // do not show context menu when mouse is enabled (r-click will be used by mouse then) + if (c64SettingsEmulatedMouseC64Enabled) + { + if (IsInsideView(guiMain->mousePosX, guiMain->mousePosY)) + { + return false; + } + } + return CViewEmulatorScreen::HasContextMenuItems(); +} + CViewC64Screen::~CViewC64Screen() { diff --git a/src/Views/C64/CViewC64Screen.h b/src/Views/C64/CViewC64Screen.h index 9f0b7cc..b366924 100644 --- a/src/Views/C64/CViewC64Screen.h +++ b/src/Views/C64/CViewC64Screen.h @@ -9,12 +9,23 @@ class CViewC64Screen : public CViewEmulatorScreen CViewC64Screen(const char *name, float posX, float posY, float posZ, float sizeX, float sizeY, CDebugInterface *debugInterface); virtual ~CViewC64Screen(); + virtual bool DoTap(float x, float y); + virtual bool DoFinishTap(float x, float y); + virtual bool DoRightClick(float x, float y); + virtual bool DoFinishRightClick(float x, float y); + virtual bool DoScrollWheel(float deltaX, float deltaY); + virtual bool DoNotTouchedMove(float x, float y); + + virtual bool HasContextMenuItems(); + virtual bool IsSkipKey(u32 keyCode, bool isShift, bool isAlt, bool isControl, bool isSuper); virtual u32 ConvertKeyCode(u32 keyCode, bool isShift, bool isAlt, bool isControl, bool isSuper); virtual void PostDebugInterfaceKeyDown(u32 keyCode, bool isShift, bool isAlt, bool isControl, bool isSuper); virtual void PostDebugInterfaceKeyUp(u32 keyCode, bool isShift, bool isAlt, bool isControl, bool isSuper); + bool ShouldAutoHideMouse(); + bool shiftDown; float rasterScaleFactorX; diff --git a/src/Views/C64/CViewDrive1541Browser.cpp b/src/Views/C64/CViewDrive1541Browser.cpp index db3ae9d..54f141d 100644 --- a/src/Views/C64/CViewDrive1541Browser.cpp +++ b/src/Views/C64/CViewDrive1541Browser.cpp @@ -123,7 +123,7 @@ void CViewDrive1541Browser::StartFileEntry(DiskImageFileEntry *fileEntry, bool s UpdateDriveDiskID(); // load the PRG - bool ret = viewC64->viewC64MainMenu->LoadPRG(byteBuffer, true, showLoadAddressInfo, false); + bool ret = viewC64->mainMenuHelper->LoadPRG(byteBuffer, true, showLoadAddressInfo, false); if (ret == false) { @@ -496,7 +496,7 @@ void CViewDrive1541Browser::RefreshDiskImageMenu() if (this->viewMenu->menuItems.size() > 0) { targetScrollPosition = std::distance(this->viewMenu->menuItems.begin(), this->viewMenu->selectedItem); - LOGD("size=%d", this->viewMenu->menuItems.size()); +// LOGD("size=%d", this->viewMenu->menuItems.size()); } LOGD("targetScrollPosition=%d", targetScrollPosition); @@ -1109,7 +1109,7 @@ CViewDrive1541FileD64EntryItem::~CViewDrive1541FileD64EntryItem() void CViewDrive1541FileD64EntryItem::RenderItem(float px, float py, float pz) { viewC64->fontCBM1->BlitTextColor(str, px, py, pz, - viewC64->viewC64MainMenu->fontScale, r, g, b, 1); + viewC64->mainMenuHelper->fontScale, r, g, b, 1); } diff --git a/src/Views/C64/VicDisplay/CViewC64VicControl.cpp b/src/Views/C64/VicDisplay/CViewC64VicControl.cpp index 60f7ea6..d8df5c5 100644 --- a/src/Views/C64/VicDisplay/CViewC64VicControl.cpp +++ b/src/Views/C64/VicDisplay/CViewC64VicControl.cpp @@ -1083,10 +1083,10 @@ void CViewC64VicControl::Render() // LOGD("rasterLine=%02x", rasterLine); - std::map *breakpointsMap = &(segment->breakpointsRasterLine->breakpoints); + std::map *breakpointsMap = &(segment->breakpointsRasterLine->breakpoints); // find if breakpoint exists - std::map::iterator it = breakpointsMap->find(rasterLine); + std::map::iterator it = breakpointsMap->find(rasterLine); if (it == breakpointsMap->end()) { btnToggleBreakpoint->SetOn(false); diff --git a/src/Views/C64/VicDisplay/CViewC64VicDisplay.cpp b/src/Views/C64/VicDisplay/CViewC64VicDisplay.cpp index b0714f7..4411085 100644 --- a/src/Views/C64/VicDisplay/CViewC64VicDisplay.cpp +++ b/src/Views/C64/VicDisplay/CViewC64VicDisplay.cpp @@ -39,6 +39,7 @@ extern "C" { #include "CDebugMemory.h" #include "CDebugMemoryCell.h" #include "CViewC64VicEditor.h" +#include "CSnapshotsManager.h" #include "C64KeyboardShortcuts.h" @@ -957,8 +958,10 @@ void CViewC64VicDisplay::RefreshScreenStateOnly(vicii_cycle_state_t *viciiState) void CViewC64VicDisplay::RefreshScreen(vicii_cycle_state_t *viciiState) { //LOGD("CViewC64VicDisplay::RefreshScreen"); - + + debugInterface->snapshotsManager->LockMutex(); RefreshScreenImageData(viciiState, this->backgroundColorAlpha, this->foregroundColorAlpha); + debugInterface->snapshotsManager->UnlockMutex(); imageScreen->ReBindImageData(imageDataScreen); @@ -1162,6 +1165,10 @@ void CViewC64VicDisplay::Render() // render UI CGuiView::Render(); + +//// const float lineWidth = 0.7f; +// BlitRectangle(this->fullScanScreenPosX, this->fullScanScreenPosY, this->posZ, this->fullScanScreenSizeX, this->fullScanScreenSizeY, 1.0f, 0.0f, 0.0f, 0.5f, lineWidth); + } void CViewC64VicDisplay::GetScreenPosFromRasterPos(float rasterX, float rasterY, float *x, float *y) @@ -2006,14 +2013,14 @@ void CViewC64VicDisplay::RenderBreakpointsLines() if (segment) { - std::map *breakpointsMap = &(segment->breakpointsRasterLine->breakpoints); + std::map *breakpointsMap = &(segment->breakpointsRasterLine->breakpoints); float cy = displayPosY + rasterCrossOffsetY - (0x33 * rasterScaleFactorY) + rasterScaleFactorY/2.0f; - for (std::map::iterator it = breakpointsMap->begin(); + for (std::map::iterator it = breakpointsMap->begin(); it != breakpointsMap->end(); it++) { - CBreakpointAddr *breakpoint = it->second; + CDebugBreakpointAddr *breakpoint = it->second; float rasterLine = breakpoint->addr; float lineY = cy + rasterScaleFactorY * rasterLine; BlitFilledRectangle(posX, lineY, posZ, sizeX, rasterScaleFactorY, 1.0f, 0.0f, 0.0f, c64SettingsScreenGridLinesAlpha); @@ -2688,21 +2695,21 @@ void CViewC64VicDisplay::ToggleVICRasterBreakpoint() viewC64->debugInterfaceC64->LockMutex(); CDebugSymbolsSegmentC64 *segment = (CDebugSymbolsSegmentC64 *) debugInterface->symbols->currentSegment; - std::map *breakpointsMap = &(segment->breakpointsRasterLine->breakpoints); + std::map *breakpointsMap = &(segment->breakpointsRasterLine->breakpoints); // find if breakpoint exists - std::map::iterator it = breakpointsMap->find(rasterLine); + std::map::iterator it = breakpointsMap->find(rasterLine); if (it == breakpointsMap->end()) { - CBreakpointAddr *addrBreakpoint = new CBreakpointAddr(rasterLine); - (*breakpointsMap)[addrBreakpoint->addr] = addrBreakpoint; + CDebugBreakpointRasterLine *rasterBreakpoint = new CDebugBreakpointRasterLine(debugInterface->symbols, rasterLine); + (*breakpointsMap)[rasterBreakpoint->addr] = rasterBreakpoint; sprintf(buf, "Created raster breakpoint line $%03X", rasterLine); } else { - CBreakpointAddr *breakpoint = it->second; + CDebugBreakpointAddr *breakpoint = it->second; breakpointsMap->erase(it); delete breakpoint; @@ -3015,6 +3022,12 @@ void CViewC64VicDisplay::RenderContextMenuItems() } // Layout +void CViewC64VicDisplay::LayoutParameterChanged(CLayoutParameter *layoutParameter) +{ + CGuiView::LayoutParameterChanged(layoutParameter); + this->UpdateGridLinesVisibleOnCurrentZoom(); +} + void CViewC64VicDisplay::Serialize(CByteBuffer *byteBuffer) { } @@ -3022,3 +3035,6 @@ void CViewC64VicDisplay::Serialize(CByteBuffer *byteBuffer) void CViewC64VicDisplay::Deserialize(CByteBuffer *byteBuffer) { } + + + diff --git a/src/Views/C64/VicDisplay/CViewC64VicDisplay.h b/src/Views/C64/VicDisplay/CViewC64VicDisplay.h index 9ba4184..982880a 100644 --- a/src/Views/C64/VicDisplay/CViewC64VicDisplay.h +++ b/src/Views/C64/VicDisplay/CViewC64VicDisplay.h @@ -366,6 +366,7 @@ class CViewC64VicDisplay : public CGuiView virtual bool IsTopWindow(); // Layout + virtual void LayoutParameterChanged(CLayoutParameter *layoutParameter); virtual void Serialize(CByteBuffer *byteBuffer); virtual void Deserialize(CByteBuffer *byteBuffer); diff --git a/src/Views/C64/VicEditor/CViewC64Charset.cpp b/src/Views/C64/VicEditor/CViewC64Charset.cpp index a4a22f6..764b50d 100644 --- a/src/Views/C64/VicEditor/CViewC64Charset.cpp +++ b/src/Views/C64/VicEditor/CViewC64Charset.cpp @@ -350,6 +350,37 @@ int CViewC64Charset::ImportCharset(CSlrString *path) return importCharsetAddr; } +int CViewC64Charset::ImportCharset(u8 *data) +{ + u8 *screen_ptr; + u8 *color_ram_ptr; + u8 *chargen_ptr; + u8 *bitmap_low_ptr; + u8 *bitmap_high_ptr; + u8 colors[0x0F]; + + vicEditor->viewVicDisplay->GetViciiPointers(&(viewC64->viciiStateToShow), &screen_ptr, &color_ram_ptr, &chargen_ptr, &bitmap_low_ptr, &bitmap_high_ptr, colors); + + int importCharsetAddr = vicEditor->viewVicDisplay->charsetAddress; + + int charsetAddr = importCharsetAddr; + + for (int i = 0; i < 0x800; i++) + { + u8 v = data[i]; + + viewC64->debugInterfaceC64->SetByteToRamC64(charsetAddr, v); + + charsetAddr++; + if (charsetAddr > 0xFFFF) + { + break; + } + } + + return importCharsetAddr; +} + void CViewC64Charset::SystemDialogFileOpenCancelled() { } diff --git a/src/Views/C64/VicEditor/CViewC64Charset.h b/src/Views/C64/VicEditor/CViewC64Charset.h index 93d3de2..5d079a4 100644 --- a/src/Views/C64/VicEditor/CViewC64Charset.h +++ b/src/Views/C64/VicEditor/CViewC64Charset.h @@ -76,6 +76,7 @@ class CViewC64Charset : public CGuiView, CGuiEditHexCallback, public CGuiViewToo // returns charset addr int ImportCharset(CSlrString *path); + int ImportCharset(u8 *data); void ImportCharsetAndShowMessage(CSlrString *path); bool ExportCharset(CSlrString *path); diff --git a/src/Views/C64/VicEditor/CViewC64VicEditor.cpp b/src/Views/C64/VicEditor/CViewC64VicEditor.cpp index 6e48d54..be872c3 100644 --- a/src/Views/C64/VicEditor/CViewC64VicEditor.cpp +++ b/src/Views/C64/VicEditor/CViewC64VicEditor.cpp @@ -307,6 +307,11 @@ void CViewC64VicEditor::UpdateReferenceLayers() } } +void CViewC64VicEditor::ResetPosition() +{ + this->SetPosition(this->posX, this->posY, this->posZ, this->sizeX, this->sizeY); +} + void CViewC64VicEditor::SetPosition(float posX, float posY, float posZ, float sizeX, float sizeY) { LOGD("CViewC64VicEditor::SetPosition: %f %f", posX, posY); @@ -428,6 +433,16 @@ void CViewC64VicEditor::UpdateDisplayRasterPos() if (!viewC64->viewC64VicDisplay->isCursorLocked) { + if ( (guiMain->FindTopWindow(mouseX, mouseY) == this)) + { + LOGG("CViewC64VicEditor::UpdateDisplayRasterPos: IsInsideView(%3.2f, %3.2f)=%s", mouseX, mouseY, STRBOOL(IsInsideView(mouseX, mouseY))); + + if (viewVicDisplay) + { + LOGG("CViewC64VicEditor::UpdateDisplayRasterPos: IsInsideScreen(%3.2f, %3.2f)=%s", mouseX, mouseY, STRBOOL(viewVicDisplay->IsInsideScreen(mouseX, mouseY))); + } + } + if ( (guiMain->FindTopWindow(mouseX, mouseY) == this) && IsInsideView(mouseX, mouseY) && viewVicDisplay->IsInsideScreen(mouseX, mouseY)) @@ -1687,7 +1702,7 @@ u8 CViewC64VicEditor::PaintPixel(int rx, int ry, u8 colorSource) return result; } -// pure pixel paiting (for external API) +// pure pixel painting (for external API) u8 CViewC64VicEditor::PaintPixelColor(bool forceColorReplace, int rx, int ry, u8 color, int selectedChar) { guiMain->LockMutex(); @@ -1704,7 +1719,7 @@ u8 CViewC64VicEditor::PaintPixelColor(bool forceColorReplace, int rx, int ry, u8 return result; } -// pure pixel paiting (for external API) +// pure pixel painting (for external API) u8 CViewC64VicEditor::PaintPixelColor(int rx, int ry, u8 color) { guiMain->LockMutex(); @@ -2270,7 +2285,7 @@ void CViewC64VicEditor::EnsureCorrectScreenAndBitmapAddr() void CViewC64VicEditor::SetVicMode(bool isBitmapMode, bool isMultiColor, bool isExtendedBackground) { - this->SetVicModeRegsOnly(isBitmapMode, isMultiColor, isExtendedBackground); + this->SetVicModeRegsOnly(true, isBitmapMode, isMultiColor, isExtendedBackground); vicii_cycle_state_t *viciiState = &(viewC64->viciiStateToShow); viewVicDisplay->SetCurrentCanvas(isBitmapMode, isMultiColor, isExtendedBackground, 1); @@ -2279,13 +2294,22 @@ void CViewC64VicEditor::SetVicMode(bool isBitmapMode, bool isMultiColor, bool is // viewVicDisplaySmall->currentCanvas->SetViciiState(viciiState); } -void CViewC64VicEditor::SetVicModeRegsOnly(bool isBitmapMode, bool isMultiColor, bool isExtendedBackground) +void CViewC64VicEditor::SetVicModeRegsOnly(bool screenIsOn, bool isBitmapMode, bool isMultiColor, bool isExtendedBackground) { vicii_cycle_state_t *viciiState = &(viewC64->viciiStateToShow); u8 d011 = viciiState->regs[0x11]; u8 d016 = viciiState->regs[0x16]; + if (screenIsOn) + { + d011 = (d011 & 0xEF) | 0x10; + } + else + { + d011 = (d011 & 0xEF); + } + if (isBitmapMode) { d011 = (d011 & 0xDF) | 0x20; @@ -2320,8 +2344,10 @@ void CViewC64VicEditor::SetVicModeRegsOnly(bool isBitmapMode, bool isMultiColor, void CViewC64VicEditor::SetVicAddresses(int vbank, int screenAddr, int charsetAddr, int bitmapAddr) { LOGD("CViewVicEditor::SetVicAddresses: vbank=%04x screen=%04x charset=%04x bitmap=%04x", vbank, screenAddr, charsetAddr, bitmapAddr); - vbank = vbank >> 14; - c64_glue_set_vbank(vbank, 0); + int vbankNum = vbank >> 14; + + LOGD("vbankNum=%04x", vbankNum); + c64_glue_set_vbank(vbankNum, 0); int screen = (screenAddr - vbank) / 0x0400; int charset = (charsetAddr - vbank) / 0x0800; @@ -2475,7 +2501,7 @@ void CViewC64VicEditor::Deserialize(CByteBuffer *byteBuffer, int version) // viewC64->viewC64VicControl->btnModeExtended->SetOn(isExtColor); // viewC64->viewC64VicControl->btnModeStandard->SetOn(!isExtColor); - SetVicModeRegsOnly(isBitmap, isMultiColor, isExtColor); + SetVicModeRegsOnly(true, isBitmap, isMultiColor, isExtColor); // set VBank int vbank = byteBuffer->getInt(); @@ -2667,7 +2693,7 @@ void CViewC64VicEditor::ImportImage(CSlrString *filePath, bool onlyVicEditorForm else if (!onlyVicEditorFormats) { // TODO: move this into common open file interface, path will be deleted by SystemDialogFileOpenSelected - viewC64->viewC64MainMenu->SystemDialogFileOpenSelected(filePath); + viewC64->mainMenuHelper->SystemDialogFileOpenSelected(filePath); } else { @@ -3681,7 +3707,7 @@ bool CViewC64VicEditor::ExportPNG(CSlrString *path) CImageData *c64Screen = viewC64->debugInterfaceC64->GetScreenImageData(); CImageData *imageCrop = IMG_CropSupersampleImageRGBA(c64Screen, viewC64->debugInterfaceC64->screenSupersampleFactor, - 0, 0, 384, 272); + 0, 0, viewC64->debugInterfaceC64->GetScreenSizeX(), viewC64->debugInterfaceC64->GetScreenSizeY()); viewVicDisplay->RefreshScreenImageData(&(viewC64->viciiStateToShow), 255, 255); layerVirtualSprites->SimpleScanSpritesInThisFrame(); @@ -4083,7 +4109,7 @@ bool CViewC64VicEditor::ImportVCE(CSlrString *path) viewC64->debugInterfaceC64->SetPatchKernalFastBoot(true); viewC64->debugInterfaceC64->DetachCartridge(); - // viewC64->debugInterfaceC64->HardReset(); + // viewC64->debugInterfaceC64->ResetHard(); SYS_Sleep(350); @@ -4109,6 +4135,13 @@ bool CViewC64VicEditor::ImportVCE(CSlrString *path) return true; } +void CViewC64VicEditor::ResetBorderType() +{ + u8 borderType = viewVicDisplay->showDisplayBorderType; + viewVicDisplay->SetShowDisplayBorderType(borderType); + ResetPosition(); +} + // context menu bool CViewC64VicEditor::HasContextMenuItems() { @@ -4202,14 +4235,17 @@ void CViewC64VicEditor::RenderContextMenuItems() if (ImGui::MenuItem("Automatic grid lines", NULL, &viewVicDisplay->gridLinesAutomatic)) { viewC64->config->SetBool("VicDisplayAutomaticGridLines", &viewVicDisplay->gridLinesAutomatic); + viewVicDisplay->UpdateGridLinesVisibleOnCurrentZoom(); } if (ImGui::SliderFloat("Grid lines zoom level", &viewVicDisplay->gridLinesShowZoomLevel, 0.1f, 10.0f)) { viewC64->config->SetFloat("VicDisplayAutomaticGridLinesShowZoomLevel", &viewVicDisplay->gridLinesShowZoomLevel); + viewVicDisplay->UpdateGridLinesVisibleOnCurrentZoom(); } if (ImGui::SliderFloat("Pixel values zoom level", &viewVicDisplay->gridLinesShowValuesZoomLevel, 0.1f, 40.0f)) { viewC64->config->SetFloat("VicDisplayAutomaticValuesShowZoomLevel", &viewVicDisplay->gridLinesShowValuesZoomLevel); + viewVicDisplay->UpdateGridLinesVisibleOnCurrentZoom(); } ImGui::Separator(); char *buf = SYS_GetCharBuf(); @@ -4271,6 +4307,8 @@ bool CViewC64VicEditor::DeserializeLayout(CByteBuffer *byteBuffer, int version) UpdateDisplayFrame(); + viewVicDisplay->UpdateGridLinesVisibleOnCurrentZoom(); + LOGD("display posX=%f posY=%f", viewVicDisplay->posX, viewVicDisplay->posY); return true; } diff --git a/src/Views/C64/VicEditor/CViewC64VicEditor.h b/src/Views/C64/VicEditor/CViewC64VicEditor.h index 25d9500..d74f95c 100644 --- a/src/Views/C64/VicEditor/CViewC64VicEditor.h +++ b/src/Views/C64/VicEditor/CViewC64VicEditor.h @@ -175,9 +175,12 @@ class CViewC64VicEditor : public CGuiView, public CViewC64PaletteCallback, publi // helpers void EnsureCorrectScreenAndBitmapAddr(); void SetVicMode(bool isBitmapMode, bool isMultiColor, bool isExtendedBackground); - void SetVicModeRegsOnly(bool isBitmapMode, bool isMultiColor, bool isExtendedBackground); + void SetVicModeRegsOnly(bool screenIsOn, bool isBitmapMode, bool isMultiColor, bool isExtendedBackground); void SetVicAddresses(int vbank, int screenAddr, int charsetAddr, int bitmapAddr); + void ResetPosition(); + void ResetBorderType(); + // keyboard shortcuts CSlrKeyboardShortcut *kbsVicEditorCreateNewPicture; CSlrKeyboardShortcut *kbsVicEditorPreviewScale; diff --git a/src/Views/C64/VicEditor/CViewC64VicEditorCreateNewPicture.cpp b/src/Views/C64/VicEditor/CViewC64VicEditorCreateNewPicture.cpp index 2c5dcba..de22c4f 100644 --- a/src/Views/C64/VicEditor/CViewC64VicEditorCreateNewPicture.cpp +++ b/src/Views/C64/VicEditor/CViewC64VicEditorCreateNewPicture.cpp @@ -186,7 +186,7 @@ void CViewC64VicEditorCreateNewPicture::CreateNewPicture(u8 mode, u8 backgroundC debugInterfaceVice->SetPatchKernalFastBoot(true); viewC64->debugInterfaceC64->DetachCartridge(); -// viewC64->debugInterfaceC64->HardReset(); +// viewC64->debugInterfaceC64->ResetHard(); SYS_Sleep(350); @@ -204,6 +204,20 @@ void CViewC64VicEditorCreateNewPicture::CreateNewPicture(u8 mode, u8 backgroundC vicEditor->viewCharset->SetVisible(true); } + if (mode == C64_PICTURE_MODE_TEXT_HIRES_EXTENDED) + { + vicEditor->SetVicMode(false, false, true); + vicEditor->SetVicAddresses(0, 0x0C00, 0x1000, 0x0000); + + vicEditor->viewCharset->SetVisible(true); + } + else if (mode == C64_PICTURE_MODE_TEXT_MULTI_EXTENDED) + { + vicEditor->SetVicMode(false, true, true); + vicEditor->SetVicAddresses(0, 0x0C00, 0x1000, 0x0000); + + vicEditor->viewCharset->SetVisible(true); + } else if (mode == C64_PICTURE_MODE_BITMAP_HIRES) { vicEditor->SetVicMode(true, false, false); diff --git a/src/Views/CMainMenuBar.cpp b/src/Views/CMainMenuBar.cpp index bde26da..b0f9b0b 100644 --- a/src/Views/CMainMenuBar.cpp +++ b/src/Views/CMainMenuBar.cpp @@ -45,6 +45,7 @@ #include "CViewC64Charset.h" #include "CViewC64VicEditor.h" #include "CViewC64KeyMap.h" +#include "CDebuggerServer.h" #include "CConfigStorageHjson.h" #include "imgui.h" #include "imgui_internal.h" @@ -232,11 +233,11 @@ CMainMenuBar::CMainMenuBar() kbsReloadAndRestart = new CSlrKeyboardShortcut(KBZONE_GLOBAL, "Open most recent", 'l', false, false, true, false, this); guiMain->AddKeyboardShortcut(kbsReloadAndRestart); - kbsSoftReset = new CSlrKeyboardShortcut(KBZONE_GLOBAL, "Soft Reset", 'r', false, false, true, false, this); - guiMain->AddKeyboardShortcut(kbsSoftReset); + kbsResetSoft = new CSlrKeyboardShortcut(KBZONE_GLOBAL, "Soft Reset", 'r', false, false, true, false, this); + guiMain->AddKeyboardShortcut(kbsResetSoft); - kbsHardReset = new CSlrKeyboardShortcut(KBZONE_GLOBAL, "Hard Reset", 'r', true, false, true, false, this); - guiMain->AddKeyboardShortcut(kbsHardReset); + kbsResetHard = new CSlrKeyboardShortcut(KBZONE_GLOBAL, "Hard Reset", 'r', true, false, true, false, this); + guiMain->AddKeyboardShortcut(kbsResetHard); // kbsIsWarpSpeed = new CSlrKeyboardShortcut(KBZONE_GLOBAL, "Warp speed", 'p', false, false, true, false, this); @@ -477,7 +478,7 @@ void CMainMenuBar::RenderImGui() // viewC64->ShowDialogOpenFile(this, &openFileExtensions, c64SettingsDefaultPRGFolder, windowTitle); // delete windowTitle; - viewC64->viewC64MainMenu->OpenDialogOpenFile(); + viewC64->mainMenuHelper->OpenDialogOpenFile(); } bool mostRecentIsAvailable = viewC64->recentlyOpenedFiles->IsMostRecentFilePathAvailable(); @@ -505,13 +506,13 @@ void CMainMenuBar::RenderImGui() } ImGui::Separator(); - if (ImGui::MenuItem("Soft Reset", kbsSoftReset->cstr)) + if (ImGui::MenuItem("Soft Reset", kbsResetSoft->cstr)) { - kbsSoftReset->Run(); + kbsResetSoft->Run(); } - if (ImGui::MenuItem("Hard Reset", kbsHardReset->cstr)) + if (ImGui::MenuItem("Hard Reset", kbsResetHard->cstr)) { - kbsHardReset->Run(); + kbsResetHard->Run(); } if (viewC64->debugInterfaceC64->isRunning) @@ -1459,7 +1460,11 @@ void CMainMenuBar::RenderImGui() { currentBorderMode = i; viewC64->config->SetInt("viceViciiBorderMode", ¤tBorderMode); + debugInterfaceVice->SetViciiBorderMode(currentBorderMode); + + viewC64->viewC64Screen->RefreshEmulatorScreenImageData(); + viewC64->viewVicEditor->ResetBorderType(); } } ImGui::EndMenu(); @@ -2481,6 +2486,44 @@ void CMainMenuBar::RenderImGui() ImGui::EndMenu(); } + ImGui::Separator(); + if (ImGui::MenuItem("WebSockets debugger server", "", &c64SettingsRunDebuggerServerWebSockets)) + { + if (viewC64->debuggerServer == NULL) + { + viewC64->DebuggerServerWebSocketsStart(); + } + if (viewC64->debuggerServer != NULL) + { + if (c64SettingsRunDebuggerServerWebSockets) + { + viewC64->debuggerServer->Start(); + char *buf = SYS_GetCharBuf(); + sprintf(buf, "WebSockets server started on port %d.", c64SettingsRunDebuggerServerWebSocketsPort); + guiMain->ShowNotification("Information", buf); + SYS_ReleaseCharBuf(buf); + } + else + { + viewC64->debuggerServer->Stop(); + if (viewC64->debuggerServer->AreClientsConnected()) + { + guiMain->ShowMessageBox("Clients connected", "Please disconnect all clients or restart RetroDebugger to stop the WebSocket server. Save your work before proceeding."); + } + else + { + guiMain->ShowNotification("Information", "WebSockets server stopped."); + } + } + } + C64DebuggerStoreSettings(); + } + if (ImGui::InputInt("Port", &c64SettingsRunDebuggerServerWebSocketsPort, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue)) + { + guiMain->ShowMessageBox("Required restart", "To apply changes to the WebSocket server port setting, please restart the server."); + viewC64->DebuggerServerWebSocketsSetPort(c64SettingsRunDebuggerServerWebSocketsPort); + C64DebuggerStoreSettings(); + } ImGui::EndMenu(); } ImGui::Separator(); @@ -2601,6 +2644,84 @@ void CMainMenuBar::RenderImGui() // TODO: copypasted code ^^^^^^ + if (ImGui::BeginMenu("Mouse")) + { + if (ImGui::MenuItem("Mouse enabled", + NULL, + &c64SettingsEmulatedMouseC64Enabled)) + { + debugInterfaceVice->EmulatedMouseEnable(c64SettingsEmulatedMouseC64Enabled); + debugInterfaceVice->EmulatedMouseSetType(c64SettingsEmulatedMouseC64Type); + C64DebuggerStoreSettings(); + } + + if (ImGui::MenuItem("Mouse auto-hide cursor", + NULL, + &c64SettingsEmulatedMouseCursorAutoHide)) + { + C64DebuggerStoreSettings(); + } + + if (ImGui::BeginMenu("Mouse type")) + { + //#define MOUSE_TYPE_1351 0 + //#define MOUSE_TYPE_NEOS 1 + //#define MOUSE_TYPE_AMIGA 2 + //#define MOUSE_TYPE_PADDLE 3 + //#define MOUSE_TYPE_CX22 4 + //#define MOUSE_TYPE_ST 5 + //#define MOUSE_TYPE_SMART 6 + //#define MOUSE_TYPE_MICROMYS 7 + //#define MOUSE_TYPE_KOALAPAD 8 + //#define MOUSE_TYPE_NUM 9 + + std::vector mouseTypeNames; + mouseTypeNames.push_back("1351"); + mouseTypeNames.push_back("NEOS"); + mouseTypeNames.push_back("Amiga"); + mouseTypeNames.push_back("Paddles"); + mouseTypeNames.push_back("Atari CX-22"); + mouseTypeNames.push_back("Atari ST"); + mouseTypeNames.push_back("Smart"); + mouseTypeNames.push_back("MicroMys"); + + int i = 0; + for (std::vector::iterator it = mouseTypeNames.begin(); it != mouseTypeNames.end(); it++) + { + const char *name = *it; + bool selected = (i == c64SettingsEmulatedMouseC64Type); + if (ImGui::MenuItem(name, NULL, &selected)) + { + c64SettingsEmulatedMouseC64Type = i; + debugInterfaceVice->EmulatedMouseSetType(c64SettingsEmulatedMouseC64Type); + C64DebuggerStoreSettings(); + } + i++; + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Mouse port")) + { + bool isSelected = (c64SettingsEmulatedMouseC64Port == 0); + if (ImGui::MenuItem("Port 1", NULL, &isSelected)) + { + c64SettingsEmulatedMouseC64Port = 0; + C64DebuggerStoreSettings(); + } + isSelected = (c64SettingsEmulatedMouseC64Port == 1); + if (ImGui::MenuItem("Port 2", NULL, &isSelected)) + { + c64SettingsEmulatedMouseC64Port = 1; + C64DebuggerStoreSettings(); + } + ImGui::EndMenu(); + } + + ImGui::EndMenu(); + } + ImGui::Separator(); if (ImGui::BeginMenu("Audio")) @@ -2773,7 +2894,7 @@ void CMainMenuBar::RenderImGui() { ImGui::Begin("Retro Debugger v" RETRODEBUGGER_VERSION_STRING " About", &show_retro_debugger_about); ImGui::Text("Retro Debugger is a multiplatform debugger APIs host with ImGui implementation."); - ImGui::Text("(C) 2016-2023 Marcin 'slajerek' Skoczylas, see README for libraries copyright."); + ImGui::Text("(C) 2016-2024 Marcin 'slajerek' Skoczylas, see README for libraries copyright."); ImGui::Separator(); ImGui::Text(""); ImGui::Text("If you like this tool and you feel that you would like to share with me some beers,"); @@ -2782,6 +2903,7 @@ void CMainMenuBar::RenderImGui() ImGui::TextURL("http://tinyurl.com/C64Debugger-PayPal", "https://www.paypal.com/donate/?business=7CQZJRKL9BXPL&no_recurring=0&item_name=For+the+Retro+Debugger¤cy_code=EUR", true, false); ImGui::Text(""); ImGui::Separator(); + ImGui::Text(" Built for %s %s", SYS_GetPlatformNameString(), SYS_GetPlatformArchitectureString()); for (std::vector::iterator it = viewC64->debugInterfaces.begin(); it != viewC64->debugInterfaces.end(); it++) { @@ -2980,7 +3102,7 @@ bool CMainMenuBar::ProcessKeyboardShortcut(u32 zone, u8 actionType, CSlrKeyboard if (shortcut == kbsOpenFile) { - viewC64->viewC64MainMenu->OpenDialogOpenFile(); + viewC64->mainMenuHelper->OpenDialogOpenFile(); return true; } @@ -3154,13 +3276,13 @@ bool CMainMenuBar::ProcessKeyboardShortcut(u32 zone, u8 actionType, CSlrKeyboard if (shortcut == kbsInsertD64) { - viewC64->viewC64MainMenu->OpenDialogInsertD64(); + viewC64->mainMenuHelper->OpenDialogInsertD64(); return true; } if (shortcut == kbsInsertNextD64) { - viewC64->viewC64MainMenu->InsertNextD64(); + viewC64->mainMenuHelper->InsertNextD64(); return true; } if (shortcut == kbsAutoJmpFromInsertedDiskFirstPrg) @@ -3183,7 +3305,7 @@ bool CMainMenuBar::ProcessKeyboardShortcut(u32 zone, u8 actionType, CSlrKeyboard CSlrString *filePath = viewC64->recentlyOpenedFiles->GetMostRecentFilePath(); if (filePath) { - viewC64->viewC64MainMenu->LoadFile(filePath); + viewC64->mainMenuHelper->LoadFile(filePath); } return true; } @@ -3191,7 +3313,7 @@ bool CMainMenuBar::ProcessKeyboardShortcut(u32 zone, u8 actionType, CSlrKeyboard // datasette if (shortcut == kbsTapeAttach) { - viewC64->viewC64MainMenu->OpenDialogInsertTape(); + viewC64->mainMenuHelper->OpenDialogInsertTape(); return true; } else if (shortcut == kbsTapeDetach) @@ -3267,7 +3389,7 @@ bool CMainMenuBar::ProcessKeyboardShortcut(u32 zone, u8 actionType, CSlrKeyboard { if (shortcut == kbsInsertATR) { - viewC64->viewC64MainMenu->OpenDialogInsertATR(); + viewC64->mainMenuHelper->OpenDialogInsertATR(); return true; } } @@ -3386,12 +3508,12 @@ bool CMainMenuBar::ProcessKeyboardShortcut(u32 zone, u8 actionType, CSlrKeyboard if (shortcut == kbsInsertCartridge) { - viewC64->viewC64MainMenu->OpenDialogInsertCartridge(); + viewC64->mainMenuHelper->OpenDialogInsertCartridge(); return true; } else if (shortcut == kbsInsertAtariCartridge) { - viewC64->viewC64MainMenu->OpenDialogInsertAtariCartridge(); + viewC64->mainMenuHelper->OpenDialogInsertAtariCartridge(); return true; } @@ -3433,14 +3555,14 @@ bool CMainMenuBar::ProcessKeyboardShortcut(u32 zone, u8 actionType, CSlrKeyboard viewC64->debugInterfaceC64->DiskDriveReset(); return true; } - else if (shortcut == kbsSoftReset) + else if (shortcut == kbsResetSoft) { - viewC64->SoftReset(); + viewC64->ResetSoft(); return true; } - else if (shortcut == kbsHardReset) + else if (shortcut == kbsResetHard) { - viewC64->HardReset(); + viewC64->ResetHard(); return true; } else if (shortcut == kbsStepOverInstruction) @@ -3897,41 +4019,41 @@ void CMainMenuBar::DetachEverything(bool showMessage, bool storeSettings) } -// if (viewC64->debugInterfaceNes) -// { -// viewC64->debugInterfaceNes->DetachEverything(); -// -// guiMain->LockMutex(); -// -//// if (viewC64->viewC64MainMenu->menuItemInsertATR->str2 != NULL) -//// delete viewC64->viewC64MainMenu->menuItemInsertATR->str2; -//// viewC64->viewC64MainMenu->menuItemInsertATR->str2 = NULL; -// -// delete c64SettingsPathToATR; -// c64SettingsPathToATR = NULL; -// -//// if (viewC64->viewC64MainMenu->menuItemInsertAtariCartridge->str2 != NULL) -//// delete viewC64->viewC64MainMenu->menuItemInsertAtariCartridge->str2; -//// viewC64->viewC64MainMenu->menuItemInsertAtariCartridge->str2 = NULL; -// -// delete c64SettingsPathToAtariCartridge; -// c64SettingsPathToAtariCartridge = NULL; -// -//// if (viewC64->viewC64MainMenu->menuItemOpenFile->str2 != NULL) -//// delete viewC64->viewC64MainMenu->menuItemOpenFile->str2; -//// viewC64->viewC64MainMenu->menuItemOpenFile->str2 = NULL; -// -// delete c64SettingsPathToXEX; -// c64SettingsPathToXEX = NULL; -// -// delete c64SettingsPathToCAS; -// c64SettingsPathToCAS = NULL; -// -// viewC64->debugInterfaceAtari->ClearDebugMarkers(); -// -// guiMain->UnlockMutex(); -// -// } + if (viewC64->debugInterfaceNes) + { + viewC64->debugInterfaceNes->DetachEverything(); + + guiMain->LockMutex(); + +// if (viewC64->viewC64MainMenu->menuItemInsertATR->str2 != NULL) +// delete viewC64->viewC64MainMenu->menuItemInsertATR->str2; +// viewC64->viewC64MainMenu->menuItemInsertATR->str2 = NULL; + + delete c64SettingsPathToATR; + c64SettingsPathToATR = NULL; + +// if (viewC64->viewC64MainMenu->menuItemInsertAtariCartridge->str2 != NULL) +// delete viewC64->viewC64MainMenu->menuItemInsertAtariCartridge->str2; +// viewC64->viewC64MainMenu->menuItemInsertAtariCartridge->str2 = NULL; + + delete c64SettingsPathToAtariCartridge; + c64SettingsPathToAtariCartridge = NULL; + +// if (viewC64->viewC64MainMenu->menuItemOpenFile->str2 != NULL) +// delete viewC64->viewC64MainMenu->menuItemOpenFile->str2; +// viewC64->viewC64MainMenu->menuItemOpenFile->str2 = NULL; + + delete c64SettingsPathToXEX; + c64SettingsPathToXEX = NULL; + + delete c64SettingsPathToCAS; + c64SettingsPathToCAS = NULL; + + viewC64->debugInterfaceAtari->ClearDebugMarkers(); + + guiMain->UnlockMutex(); + + } if (storeSettings) { @@ -4056,7 +4178,7 @@ void CMainMenuBar::DetachC64PRG(bool showMessage) } viewC64->debugInterfaceC64->ClearDebugMarkers(); - viewC64->debugInterfaceC64->HardReset(); + viewC64->debugInterfaceC64->ResetHard(); C64DebuggerStoreSettings(); @@ -4078,7 +4200,7 @@ void CMainMenuBar::DetachAtariXEX(bool showMessage) } viewC64->debugInterfaceAtari->ClearDebugMarkers(); - viewC64->debugInterfaceAtari->HardReset(); + viewC64->debugInterfaceAtari->ResetHard(); C64DebuggerStoreSettings(); @@ -4306,13 +4428,13 @@ void CMainMenuBar::SystemDialogFileOpenSelected(CSlrString *path) else if (systemDialogOperation == SystemDialogOperationLoadREU) { - viewC64->viewC64MainMenu->AttachReu(path, true, true); + viewC64->mainMenuHelper->AttachReu(path, true, true); C64DebuggerStoreSettings(); } else if (systemDialogOperation == SystemDialogOperationSaveREU) { - viewC64->viewC64MainMenu->SaveReu(path, true, true); + viewC64->mainMenuHelper->SaveReu(path, true, true); C64DebuggerStoreSettings(); } diff --git a/src/Views/CMainMenuBar.h b/src/Views/CMainMenuBar.h index 458fe57..4ffa810 100644 --- a/src/Views/CMainMenuBar.h +++ b/src/Views/CMainMenuBar.h @@ -127,8 +127,8 @@ class CMainMenuBar : public CSlrKeyboardShortcutCallback, public CSystemFileDial CSlrKeyboardShortcut *kbsOpenFile; CSlrKeyboardShortcut *kbsReloadAndRestart; - CSlrKeyboardShortcut *kbsSoftReset; - CSlrKeyboardShortcut *kbsHardReset; + CSlrKeyboardShortcut *kbsResetSoft; + CSlrKeyboardShortcut *kbsResetHard; CSlrKeyboardShortcut *kbsDiskDriveReset; CSlrKeyboardShortcut *kbsDetachEverything; diff --git a/src/Views/CViewDataDump.cpp b/src/Views/CViewDataDump.cpp index 39d63d3..cc48d5c 100644 --- a/src/Views/CViewDataDump.cpp +++ b/src/Views/CViewDataDump.cpp @@ -1533,12 +1533,9 @@ void CViewDataDump::RenderContextMenuItems() } char *buf = SYS_GetCharBuf(); - dataAdapter->GetAddressStringForCell(currentDataIndex, buf, MAX_STRING_LENGTH); - - char *dataAddressStr = SYS_GetCharBuf(); - sprintf(dataAddressStr, "Address %s: %02X", buf, val); - SYS_ReleaseCharBuf(dataAddressStr); + char *buf2 = SYS_GetCharBuf(); + dataAdapter->GetAddressStringForCell(currentDataIndex, buf, MAX_STRING_LENGTH); ImGui::Text(buf); ImGui::SameLine(); @@ -1568,7 +1565,12 @@ void CViewDataDump::RenderContextMenuItems() } } } - + + FUN_IntToBinaryStr(val, buf2); + + sprintf(buf, "%02X %3d %s", val, val, buf2); + ImGui::Text(buf); + /* if (ImGui::CollapsingHeader("Statistics", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::Text("Written by PC address: %04x", cell->writePC); @@ -1597,12 +1599,14 @@ void CViewDataDump::RenderContextMenuItems() } */ + + ImGui::Separator(); // if (ImGui::CollapsingHeader("Breakpoints", ImGuiTreeNodeFlags_DefaultOpen)) { // breakpoints - if (currentSegment && currentSegment->supportBreakpoints && currentSegment->breakpointsMemory) + if (currentSegment && currentSegment->supportBreakpoints && currentSegment->breakpointsData) { bool supportsWriteBreakpoint, supportsReadBreakpoint; currentSegment->symbols->debugInterface->SupportsBreakpoints(&supportsWriteBreakpoint, &supportsReadBreakpoint); @@ -1612,7 +1616,7 @@ void CViewDataDump::RenderContextMenuItems() currentSegment->symbols->debugInterface->LockMutex(); ImGui::Text("Breakpoint:"); - CBreakpointMemory *memoryBreakpoint = (CBreakpointMemory*)currentSegment->breakpointsMemory->GetBreakpoint(currentDataIndex); + CDebugBreakpointData *memoryBreakpoint = (CDebugBreakpointData*)currentSegment->breakpointsData->GetBreakpoint(currentDataIndex); if (!memoryBreakpoint) { @@ -1621,7 +1625,7 @@ void CViewDataDump::RenderContextMenuItems() bool isWrite = false; if (ImGui::Checkbox("Write##memoryBreakpoint", &isWrite)) { - currentSegment->AddBreakpointMemory(currentDataIndex, MEMORY_BREAKPOINT_ACCESS_WRITE, MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL, 0xFF); + currentSegment->AddBreakpointMemory(currentDataIndex, MEMORY_BREAKPOINT_ACCESS_WRITE, DataBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL, 0xFF); } } @@ -1631,7 +1635,7 @@ void CViewDataDump::RenderContextMenuItems() ImGui::SameLine(); if (ImGui::Checkbox("Read##memoryBreakpoint", &isRead)) { - currentSegment->AddBreakpointMemory(currentDataIndex, MEMORY_BREAKPOINT_ACCESS_READ, MemoryBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL, 0xFF); + currentSegment->AddBreakpointMemory(currentDataIndex, MEMORY_BREAKPOINT_ACCESS_READ, DataBreakpointComparison::MEMORY_BREAKPOINT_LESS_OR_EQUAL, 0xFF); } } } @@ -1639,16 +1643,16 @@ void CViewDataDump::RenderContextMenuItems() { if (supportsWriteBreakpoint) { - bool isWrite = IS_SET(memoryBreakpoint->memoryAccess, MEMORY_BREAKPOINT_ACCESS_WRITE); + bool isWrite = IS_SET(memoryBreakpoint->dataAccess, MEMORY_BREAKPOINT_ACCESS_WRITE); if (ImGui::Checkbox("Write##memoryBreakpoint", &isWrite)) { if (isWrite) { - SET_BIT(memoryBreakpoint->memoryAccess, MEMORY_BREAKPOINT_ACCESS_WRITE); + SET_BIT(memoryBreakpoint->dataAccess, MEMORY_BREAKPOINT_ACCESS_WRITE); } else { - REMOVE_BIT(memoryBreakpoint->memoryAccess, MEMORY_BREAKPOINT_ACCESS_WRITE); + REMOVE_BIT(memoryBreakpoint->dataAccess, MEMORY_BREAKPOINT_ACCESS_WRITE); } } } @@ -1656,17 +1660,17 @@ void CViewDataDump::RenderContextMenuItems() if (supportsReadBreakpoint) { // TODO: read breakpoint in Vice is fired on STA (because it reads) - bool isRead = IS_SET(memoryBreakpoint->memoryAccess, MEMORY_BREAKPOINT_ACCESS_READ); + bool isRead = IS_SET(memoryBreakpoint->dataAccess, MEMORY_BREAKPOINT_ACCESS_READ); ImGui::SameLine(); if (ImGui::Checkbox("Read##memoryBreakpoint", &isRead)) { if (isRead) { - SET_BIT(memoryBreakpoint->memoryAccess, MEMORY_BREAKPOINT_ACCESS_READ); + SET_BIT(memoryBreakpoint->dataAccess, MEMORY_BREAKPOINT_ACCESS_READ); } else { - REMOVE_BIT(memoryBreakpoint->memoryAccess, MEMORY_BREAKPOINT_ACCESS_READ); + REMOVE_BIT(memoryBreakpoint->dataAccess, MEMORY_BREAKPOINT_ACCESS_READ); } } } @@ -1684,7 +1688,7 @@ void CViewDataDump::RenderContextMenuItems() int comparison = memoryBreakpoint->comparison; if (ImGui::Combo("##memoryBreakpointComparison", &comparison, "==\0!=\0<\0<=\0>\0>=\0\0")) { - memoryBreakpoint->comparison = (MemoryBreakpointComparison)comparison; + memoryBreakpoint->comparison = (DataBreakpointComparison)comparison; } ImGui::PopItemWidth(); @@ -1711,7 +1715,7 @@ void CViewDataDump::RenderContextMenuItems() // if (ImGui::CollapsingHeader("Rewind", ImGuiTreeNodeFlags_DefaultOpen)) - if (currentSegment && currentSegment->supportBreakpoints && currentSegment->breakpointsMemory) + if (currentSegment && currentSegment->supportBreakpoints && currentSegment->breakpointsData) { if (viewDisassembly) { @@ -1729,19 +1733,19 @@ void CViewDataDump::RenderContextMenuItems() if (debugInterface->snapshotsManager) { - if (ImGui::MenuItem("Rewind to last read", "Alt+" PLATFORM_STR_KEY_CTRL "+Shift+click", false, (cell->readCycle != -1) )) + if (ImGui::MenuItem("Rewind to previous read", "Alt+" PLATFORM_STR_KEY_CTRL "+Shift+click", false, (cell->readCycle != -1) )) { LOGM("============######################### RESTORE TO READ CYCLE=%d", cell->readCycle); debugInterface->snapshotsManager->RestoreSnapshotByCycle(cell->readCycle); } - if (ImGui::MenuItem("Rewind to last write", "Alt+" PLATFORM_STR_KEY_CTRL "+click", false, (cell->writeCycle != -1))) + if (ImGui::MenuItem("Rewind to previous write", "Alt+" PLATFORM_STR_KEY_CTRL "+click", false, (cell->writeCycle != -1))) { LOGM("============######################### RESTORE TO WRITE CYCLE=%d", cell->writeCycle); debugInterface->snapshotsManager->RestoreSnapshotByCycle(cell->writeCycle); } - if (ImGui::MenuItem("Rewind to last execute", "", false, (cell->executeCycle != -1))) + if (ImGui::MenuItem("Rewind to previous execute", "", false, (cell->executeCycle != -1))) { LOGM("============######################### RESTORE TO EXECUTE CYCLE=%d", cell->executeCycle); debugInterface->snapshotsManager->RestoreSnapshotByCycle(cell->executeCycle); @@ -1752,6 +1756,7 @@ void CViewDataDump::RenderContextMenuItems() } SYS_ReleaseCharBuf(buf); + SYS_ReleaseCharBuf(buf2); // if (ImGui::CollapsingHeader("Config", ImGuiTreeNodeFlags_DefaultOpen)) } diff --git a/src/Views/CViewDebugEventsHistory.h b/src/Views/CViewDebugEventsHistory.h index 2a1bd1b..4a2d9f1 100644 --- a/src/Views/CViewDebugEventsHistory.h +++ b/src/Views/CViewDebugEventsHistory.h @@ -15,7 +15,7 @@ class CViewDebugEventsHistory : public CGuiView virtual bool HasContextMenuItems(); virtual void RenderContextMenuItems(); - + virtual void ActivateView(); virtual void DeactivateView(); diff --git a/src/Views/CViewDisassembly.cpp b/src/Views/CViewDisassembly.cpp index 2ffd4ea..e23226c 100644 --- a/src/Views/CViewDisassembly.cpp +++ b/src/Views/CViewDisassembly.cpp @@ -974,10 +974,10 @@ int CViewDisassembly::RenderDisassemblyLine(float px, float py, int addr, uint8 CDebugBreakpointsAddr *breakpoints = symbols->currentSegment->breakpointsPC; - std::map::iterator it = breakpoints->renderBreakpoints.find(addr); + std::map::iterator it = breakpoints->renderBreakpoints.find(addr); if (it != breakpoints->renderBreakpoints.end()) { - CBreakpointAddr *breakpoint = it->second; + CDebugBreakpointAddr *breakpoint = it->second; // is active? if (breakpoint->isActive) @@ -1692,10 +1692,10 @@ void CViewDisassembly::RenderHexLine(float px, float py, int addr) CDebugBreakpointsAddr *breakpoints = symbols->currentSegment->breakpointsPC; - std::map::iterator it = breakpoints->renderBreakpoints.find(addr); + std::map::iterator it = breakpoints->renderBreakpoints.find(addr); if (it != breakpoints->renderBreakpoints.end()) { - CBreakpointAddr *breakpoint = it->second; + CDebugBreakpointAddr *breakpoint = it->second; // is active? if (breakpoint->isActive == true) @@ -1968,7 +1968,6 @@ void CViewDisassembly::UpdateDisassembly(int startAddress, int endAddress) UpdateLocalMemoryCopy(startAddress, endAddress); - CalcDisassemblyStart(startAddress, &renderAddress, &renderLinesBefore); renderSkipLines = numberOfLinesBack - renderLinesBefore; @@ -2020,7 +2019,7 @@ void CViewDisassembly::UpdateDisassembly(int startAddress, int endAddress) addr = renderAddress; // +0 - CDebugMemoryCell *cell0 = debugMemory->GetMemoryCell(addr); //% memoryLength + CDebugMemoryCell *cell0 = debugMemory->GetMemoryCell(addr % memoryLength); if (cell0->isExecuteCode) { opcode = memory[addr]; //% memoryLength @@ -2030,7 +2029,7 @@ void CViewDisassembly::UpdateDisassembly(int startAddress, int endAddress) else { // +1 - CDebugMemoryCell *cell1 = debugMemory->GetMemoryCell( addr+1 ); //% memoryLength + CDebugMemoryCell *cell1 = debugMemory->GetMemoryCell( (addr+1) % memoryLength); if (cell1->isExecuteCode) { // check if at addr is 1-length opcode @@ -2065,7 +2064,7 @@ void CViewDisassembly::UpdateDisassembly(int startAddress, int endAddress) else { // +2 - CDebugMemoryCell *cell2 = debugMemory->GetMemoryCell( addr+2 ); //% memoryLength + CDebugMemoryCell *cell2 = debugMemory->GetMemoryCell( (addr+2) % memoryLength ); if (cell2->isExecuteCode) { // check if at addr is 2-length opcode @@ -2097,7 +2096,7 @@ void CViewDisassembly::UpdateDisassembly(int startAddress, int endAddress) op[i] = memory[addr]; } - opcode = memory[ (renderAddress) ]; //% memoryLength + opcode = memory[ (renderAddress % memoryLength) ]; renderAddress += UpdateDisassemblyOpcodeLine(py, renderAddress, op[0], op[1], op[2]); py += fontSize; } @@ -2156,7 +2155,7 @@ void CViewDisassembly::UpdateDisassembly(int startAddress, int endAddress) int addr; addr = renderAddress-1; - CDebugMemoryCell *cell1 = debugMemory->GetMemoryCell(addr); + CDebugMemoryCell *cell1 = debugMemory->GetMemoryCell(addr % memoryLength); if (cell1->isExecuteCode) { op = memory[addr]; @@ -2173,7 +2172,7 @@ void CViewDisassembly::UpdateDisassembly(int startAddress, int endAddress) } addr = renderAddress-2; - CDebugMemoryCell *cell2 = debugMemory->GetMemoryCell(addr); + CDebugMemoryCell *cell2 = debugMemory->GetMemoryCell(addr % memoryLength); if (cell2->isExecuteCode) { op = memory[addr]; @@ -2195,7 +2194,7 @@ void CViewDisassembly::UpdateDisassembly(int startAddress, int endAddress) } addr = renderAddress-3; - CDebugMemoryCell *cell3 = debugMemory->GetMemoryCell(addr); + CDebugMemoryCell *cell3 = debugMemory->GetMemoryCell(addr % memoryLength); if (cell3->isExecuteCode) { op = memory[addr]; @@ -2473,7 +2472,7 @@ void CViewDisassembly::TogglePCBreakpoint(int addr) CDebugBreakpointsAddr *breakpoints = symbols->currentSegment->breakpointsPC; // keep copy of breakpoints to not lock mutex during rendering - std::map::iterator it = breakpoints->renderBreakpoints.find(addr); + std::map::iterator it = breakpoints->renderBreakpoints.find(addr); if (it != breakpoints->renderBreakpoints.end()) { // remove breakpoint @@ -2490,7 +2489,7 @@ void CViewDisassembly::TogglePCBreakpoint(int addr) // add breakpoint LOGD("add breakpoint addr=%4.4x", addr); - CBreakpointAddr *breakpoint = new CBreakpointAddr(addr); + CDebugBreakpointAddr *breakpoint = new CDebugBreakpointAddr(addr); breakpoint->actions = ADDR_BREAKPOINT_ACTION_STOP; breakpoints->AddBreakpoint(breakpoint); @@ -2500,6 +2499,56 @@ void CViewDisassembly::TogglePCBreakpoint(int addr) debugInterface->UnlockMutex(); } +CDebugBreakpointAddr *CViewDisassembly::AddPCBreakpoint(int addr) +{ + debugInterface->LockMutex(); + + CDebugBreakpointsAddr *breakpoints = symbols->currentSegment->breakpointsPC; + + // keep copy of breakpoints to not lock mutex during rendering + std::map::iterator it = breakpoints->renderBreakpoints.find(addr); + if (it != breakpoints->renderBreakpoints.end()) + { + debugInterface->UnlockMutex(); + return it->second; + } + + // add breakpoint + LOGD("add breakpoint addr=%4.4x", addr); + + CDebugBreakpointAddr *breakpoint = new CDebugBreakpointAddr(addr); + breakpoint->actions = ADDR_BREAKPOINT_ACTION_STOP; + + breakpoints->AddBreakpoint(breakpoint); + breakpoints->renderBreakpoints[addr] = breakpoint; + + debugInterface->UnlockMutex(); + + return breakpoint; +} + +u64 CViewDisassembly::RemovePCBreakpoint(int addr) +{ + debugInterface->LockMutex(); + + CDebugBreakpointsAddr *breakpoints = symbols->currentSegment->breakpointsPC; + + u64 breakpointId = UNKNOWN_BREAKPOINT_ID; + + // keep copy of breakpoints to not lock mutex during rendering + std::map::iterator it = breakpoints->renderBreakpoints.find(addr); + if (it != breakpoints->renderBreakpoints.end()) + { + // remove breakpoint + //LOGD("remove breakpoint addr=%4.4x", addr); + + breakpoints->renderBreakpoints.erase(it); + breakpointId = breakpoints->DeleteBreakpoint(addr); + } + debugInterface->UnlockMutex(); + return breakpointId; +} + //@returns is consumed bool CViewDisassembly::DoTap(float x, float y) { @@ -3114,7 +3163,7 @@ void CViewDisassembly::SetBreakpointPC(int address, bool setOn) bool found = false; - std::map::iterator it2 = breakpoints->renderBreakpoints.find(address); + std::map::iterator it2 = breakpoints->renderBreakpoints.find(address); if (it2 != breakpoints->renderBreakpoints.end()) { if (setOn) @@ -3141,7 +3190,7 @@ void CViewDisassembly::SetBreakpointPC(int address, bool setOn) // add breakpoint LOGD("CViewDisassembly::SetBreakpointPC: add breakpoint addr=%04x", address); - CBreakpointAddr *breakpoint = new CBreakpointAddr(address); + CDebugBreakpointAddr *breakpoint = new CDebugBreakpointAddr(address); breakpoint->actions = ADDR_BREAKPOINT_ACTION_STOP; breakpoints->AddBreakpoint(breakpoint); @@ -3162,10 +3211,10 @@ void CViewDisassembly::SetBreakpointPCIsActive(int address, bool setActive) debugInterface->LockMutex(); CDebugBreakpointsAddr *breakpoints = symbols->currentSegment->breakpointsPC; - std::map::iterator itBp = breakpoints->renderBreakpoints.find(address); + std::map::iterator itBp = breakpoints->renderBreakpoints.find(address); if (itBp != breakpoints->renderBreakpoints.end()) { - CBreakpointAddr *bp = itBp->second; + CDebugBreakpointAddr *bp = itBp->second; bp->isActive = setActive; } else @@ -3175,10 +3224,10 @@ void CViewDisassembly::SetBreakpointPCIsActive(int address, bool setActive) // as a workaround create one this->SetBreakpointPC(address, true); - std::map::iterator itBp = breakpoints->renderBreakpoints.find(address); + std::map::iterator itBp = breakpoints->renderBreakpoints.find(address); if (itBp != breakpoints->renderBreakpoints.end()) { - CBreakpointAddr *bp = itBp->second; + CDebugBreakpointAddr *bp = itBp->second; bp->isActive = setActive; } } @@ -4286,17 +4335,17 @@ void CViewDisassembly::RenderContextMenuItems() } // update breakpoint PC - CBreakpointAddr *breakpointPC = currentSegment->breakpointsPC->GetBreakpoint(existingLabel->address); + CDebugBreakpointAddr *breakpointPC = currentSegment->breakpointsPC->GetBreakpoint(existingLabel->address); if (breakpointPC) { currentSegment->breakpointsPC->RemoveBreakpoint(breakpointPC); } // update breakpoint memory - CBreakpointAddr *breakpointMemory = currentSegment->breakpointsMemory->GetBreakpoint(existingLabel->address); + CDebugBreakpointAddr *breakpointMemory = currentSegment->breakpointsData->GetBreakpoint(existingLabel->address); if (breakpointMemory) { - currentSegment->breakpointsMemory->RemoveBreakpoint(breakpointMemory); + currentSegment->breakpointsData->RemoveBreakpoint(breakpointMemory); } // update label @@ -4319,7 +4368,7 @@ void CViewDisassembly::RenderContextMenuItems() if (breakpointMemory) { breakpointMemory->addr = cursorAddress; - currentSegment->breakpointsMemory->AddBreakpoint(breakpointMemory); + currentSegment->breakpointsData->AddBreakpoint(breakpointMemory); } } else @@ -4371,6 +4420,26 @@ void CViewDisassembly::RenderContextMenuItems() } } + ImGui::Separator(); + + // #if defined(EXPERIMENTAL_EVENTS_HISTORY) + /* + bool canRewindToPreviousExecute = false; + if (cell) + { + if (cell->executeHistory.size > 0) + { + canRewindToPreviousExecute = true; + } + } + + if (ImGui::MenuItem("Rewind to previous execute", "", false, canRewindToPreviousExecute)) + { + + } + ImGui::Separator(); + */ + CGuiView::RenderContextMenuLayoutParameters(false); // if (ImGui::MenuItem("Execute-aware disassembly", NULL, &c64SettingsExecuteAwareDisassembly)) diff --git a/src/Views/CViewDisassembly.h b/src/Views/CViewDisassembly.h index f8b22d1..041ee6f 100644 --- a/src/Views/CViewDisassembly.h +++ b/src/Views/CViewDisassembly.h @@ -15,7 +15,7 @@ class CDebugInterface; class CDebugBreakpointsAddr; class CSlrMutex; class CSlrString; -class CBreakpointAddr; +class CDebugBreakpointAddr; class CViewDataDump; class CDebugSymbols; class CDebugMemory; @@ -98,7 +98,9 @@ class CViewDisassembly : public CGuiView, CGuiEditHexCallback, CGuiEditBoxTextCa std::map jumpOpcodes; void TogglePCBreakpoint(int addr); - + CDebugBreakpointAddr *AddPCBreakpoint(int addr); + u64 RemovePCBreakpoint(int addr); + void ScrollDown(); void ScrollUp(); diff --git a/src/Views/CViewEmulatorScreen.cpp b/src/Views/CViewEmulatorScreen.cpp index 33fc56b..9972a52 100644 --- a/src/Views/CViewEmulatorScreen.cpp +++ b/src/Views/CViewEmulatorScreen.cpp @@ -23,7 +23,7 @@ CViewEmulatorScreen::CViewEmulatorScreen(const char *name, float posX, float pos InitImage(); } -void CViewEmulatorScreen::CreateImageData() +void CViewEmulatorScreen::RefreshEmulatorScreenImageData() { this->imageData = debugInterface->GetScreenImageData(); this->paneWidth = debugInterface->GetScreenSizeX() * debugInterface->screenSupersampleFactor; @@ -35,6 +35,10 @@ void CViewEmulatorScreen::CreateImageData() float w = (float)debugInterface->GetScreenSizeX(); float h = (float)debugInterface->GetScreenSizeY(); SetKeepAspectRatio(true, w/h); + + UpdatePositionAndZoom(); + + RefreshRenderTextureParameters(); } bool CViewEmulatorScreen::UpdateImageData() @@ -62,10 +66,7 @@ void CViewEmulatorScreen::RefreshImageParameters() guiMain->LockMutex(); debugInterface->LockRenderScreenMutex(); - if (imageData) - delete imageData; - - CreateImageData(); + RefreshEmulatorScreenImageData(); image->RefreshImageParameters(imageData, RESOURCE_PRIORITY_STATIC, false); image->linearScaling = !c64SettingsRenderScreenNearest; @@ -166,11 +167,11 @@ void CViewEmulatorScreen::RenderContextMenuItems() bool CViewEmulatorScreen::DoGamePadButtonDown(CGamePad *gamePad, u8 button) { LOGI("CViewEmulatorScreen::DoGamePadButtonDown: %s %d", gamePad->name, button); - if (gamePad->index == viewC64->mainMenuBar->selectedJoystick1-2) + if (gamePad->index == c64SettingsSelectedJoystick1-2) { debugInterface->JoystickDown(0, ConvertSdlAxisToJoystickAxis(button)); } - if (gamePad->index == viewC64->mainMenuBar->selectedJoystick2-2) + if (gamePad->index == c64SettingsSelectedJoystick2-2) { debugInterface->JoystickDown(1, ConvertSdlAxisToJoystickAxis(button)); } @@ -180,11 +181,11 @@ bool CViewEmulatorScreen::DoGamePadButtonDown(CGamePad *gamePad, u8 button) bool CViewEmulatorScreen::DoGamePadButtonUp(CGamePad *gamePad, u8 button) { LOGI("CViewEmulatorScreen::DoGamePadButtonUp: %s %d", gamePad->name, button); - if (gamePad->index == viewC64->mainMenuBar->selectedJoystick1-2) + if (gamePad->index == c64SettingsSelectedJoystick1-2) { debugInterface->JoystickUp(0, ConvertSdlAxisToJoystickAxis(button)); } - if (gamePad->index == viewC64->mainMenuBar->selectedJoystick2-2) + if (gamePad->index == c64SettingsSelectedJoystick2-2) { debugInterface->JoystickUp(1, ConvertSdlAxisToJoystickAxis(button)); } @@ -242,18 +243,18 @@ bool CViewEmulatorScreen::KeyDown(u32 keyCode, bool isShift, bool isAlt, bool is if (IsSkipKey(keyCode, isShift, isAlt, isControl, isSuper)) return false; - if (viewC64->mainMenuBar->selectedJoystick1 == SelectedJoystick::SelectedJoystickKeyboard - || viewC64->mainMenuBar->selectedJoystick2 == SelectedJoystick::SelectedJoystickKeyboard) + if (c64SettingsSelectedJoystick1 == SelectedJoystick::SelectedJoystickKeyboard + || c64SettingsSelectedJoystick2 == SelectedJoystick::SelectedJoystickKeyboard) { int joyAxis = GetJoystickAxis(keyCode, isShift, isAlt, isControl, isSuper); if (joyAxis != JOYPAD_IDLE) { debugInterface->LockIoMutex(); - if (viewC64->mainMenuBar->selectedJoystick1 == SelectedJoystick::SelectedJoystickKeyboard) + if (c64SettingsSelectedJoystick1 == SelectedJoystick::SelectedJoystickKeyboard) { debugInterface->JoystickDown(0, joyAxis); } - if (viewC64->mainMenuBar->selectedJoystick2 == SelectedJoystick::SelectedJoystickKeyboard) + if (c64SettingsSelectedJoystick2 == SelectedJoystick::SelectedJoystickKeyboard) { debugInterface->JoystickDown(1, joyAxis); } @@ -304,18 +305,18 @@ bool CViewEmulatorScreen::KeyUp(u32 keyCode, bool isShift, bool isAlt, bool isCo { LOGI(".......... CViewEmulatorScreen::KeyUp: keyCode=%d", keyCode); - if (viewC64->mainMenuBar->selectedJoystick1 == SelectedJoystick::SelectedJoystickKeyboard - || viewC64->mainMenuBar->selectedJoystick2 == SelectedJoystick::SelectedJoystickKeyboard) + if (c64SettingsSelectedJoystick1 == SelectedJoystick::SelectedJoystickKeyboard + || c64SettingsSelectedJoystick2 == SelectedJoystick::SelectedJoystickKeyboard) { int joyAxis = GetJoystickAxis(keyCode, isShift, isAlt, isControl, isSuper); if (joyAxis != JOYPAD_IDLE) { debugInterface->LockIoMutex(); - if (viewC64->mainMenuBar->selectedJoystick1 == SelectedJoystick::SelectedJoystickKeyboard) + if (c64SettingsSelectedJoystick1 == SelectedJoystick::SelectedJoystickKeyboard) { debugInterface->JoystickUp(0, joyAxis); } - if (viewC64->mainMenuBar->selectedJoystick2 == SelectedJoystick::SelectedJoystickKeyboard) + if (c64SettingsSelectedJoystick2 == SelectedJoystick::SelectedJoystickKeyboard) { debugInterface->JoystickUp(1, joyAxis); } @@ -387,6 +388,41 @@ void CViewEmulatorScreen::PostDebugInterfaceKeyUp(u32 keyCode, bool isShift, boo { } +bool CViewEmulatorScreen::DoTap(float x, float y) +{ + return CGuiViewMovingPaneImage::DoTap(x, y); +} + +bool CViewEmulatorScreen::DoFinishTap(float x, float y) +{ + return CGuiViewMovingPaneImage::DoFinishTap(x, y); +} + +bool CViewEmulatorScreen::DoRightClick(float x, float y) +{ + return CGuiViewMovingPaneImage::DoRightClick(x, y); +} + +bool CViewEmulatorScreen::DoFinishRightClick(float x, float y) +{ + return CGuiViewMovingPaneImage::DoFinishRightClick(x, y); +} + +bool CViewEmulatorScreen::DoMove(float x, float y, float distX, float distY, float diffX, float diffY) +{ + return CGuiViewMovingPaneImage::DoMove(x, y, distX, distY, diffX, diffY); +} + +bool CViewEmulatorScreen::FinishMove(float x, float y, float distX, float distY, float accelerationX, float accelerationY) +{ + return CGuiViewMovingPaneImage::FinishMove(x, y, distX, distY, accelerationX, accelerationY); +} + +bool CViewEmulatorScreen::DoScrollWheel(float deltaX, float deltaY) +{ + return CGuiViewMovingPaneImage::DoFinishTap(deltaX, deltaY); +} + CViewEmulatorScreen::~CViewEmulatorScreen() { CGuiViewMovingPaneImage::~CGuiViewMovingPaneImage(); diff --git a/src/Views/CViewEmulatorScreen.h b/src/Views/CViewEmulatorScreen.h index 3936890..7c927d4 100644 --- a/src/Views/CViewEmulatorScreen.h +++ b/src/Views/CViewEmulatorScreen.h @@ -15,7 +15,15 @@ class CViewEmulatorScreen : public CGuiViewMovingPaneImage CDebugInterface *debugInterface; - virtual void CreateImageData(); + virtual bool DoTap(float x, float y); + virtual bool DoFinishTap(float x, float y); + virtual bool DoRightClick(float x, float y); + virtual bool DoFinishRightClick(float x, float y); + virtual bool DoMove(float x, float y, float distX, float distY, float diffX, float diffY); + virtual bool FinishMove(float x, float y, float distX, float distY, float accelerationX, float accelerationY); + virtual bool DoScrollWheel(float deltaX, float deltaY); + + virtual void RefreshEmulatorScreenImageData(); virtual bool UpdateImageData(); virtual void RefreshImage(); diff --git a/src/Views/CViewMonitorConsole.cpp b/src/Views/CViewMonitorConsole.cpp index 9c61dfc..5a28c6b 100644 --- a/src/Views/CViewMonitorConsole.cpp +++ b/src/Views/CViewMonitorConsole.cpp @@ -1432,7 +1432,7 @@ void CViewMonitorConsole::CommandMemoryLoad() { //this->viewConsole->PrintLine("Usage: L [PRG] [from addres] [file name]"); // no tokens - just open LOAD PRG dialog - viewC64->viewC64MainMenu->OpenDialogOpenFile(); + viewC64->mainMenuHelper->OpenDialogOpenFile(); return; } diff --git a/src/Views/CViewSourceCode.h b/src/Views/CViewSourceCode.h index 2c701cf..dc5aabe 100644 --- a/src/Views/CViewSourceCode.h +++ b/src/Views/CViewSourceCode.h @@ -14,7 +14,7 @@ class CSlrFont; class CDebugInterface; class CSlrMutex; class CSlrString; -class CBreakpointAddr; +class CDebugBreakpointAddr; class CViewDataMap; class CSlrKeyboardShortcut; class CViewDisassembly; diff --git a/src/Views/JukeboxPlaylist/CViewJukeboxPlaylist.cpp b/src/Views/JukeboxPlaylist/CViewJukeboxPlaylist.cpp index 257fa71..8f1de16 100644 --- a/src/Views/JukeboxPlaylist/CViewJukeboxPlaylist.cpp +++ b/src/Views/JukeboxPlaylist/CViewJukeboxPlaylist.cpp @@ -267,7 +267,7 @@ void CViewJukeboxPlaylist::ThreadRun(void *data) if (entry->resetMode == MACHINE_LOADPRG_RESET_MODE_HARD) { - viewC64->debugInterfaceC64->HardReset(); + viewC64->debugInterfaceC64->ResetHard(); if (entry->delayAfterResetTime < 0) { @@ -280,7 +280,7 @@ void CViewJukeboxPlaylist::ThreadRun(void *data) } else if (entry->resetMode == MACHINE_LOADPRG_RESET_MODE_SOFT) { - viewC64->debugInterfaceC64->Reset(); + viewC64->debugInterfaceC64->ResetSoft(); if (entry->delayAfterResetTime < 0) { @@ -301,24 +301,24 @@ void CViewJukeboxPlaylist::ThreadRun(void *data) CSlrString *ext = entry->filePath->GetFileExtensionComponentFromPath(); if (ext->CompareWith("prg") || ext->CompareWith("PRG")) { - viewC64->viewC64MainMenu->LoadPRG(entry->filePath, currentEntry->autoRun, false, this->playlist->showLoadAddressInfo, false); + viewC64->mainMenuHelper->LoadPRG(entry->filePath, currentEntry->autoRun, false, this->playlist->showLoadAddressInfo, false); } else if (ext->CompareWith("d64") || ext->CompareWith("D64") || ext->CompareWith("g64") || ext->CompareWith("G64")) { - viewC64->viewC64MainMenu->InsertD64(entry->filePath, false, + viewC64->mainMenuHelper->InsertD64(entry->filePath, false, currentEntry->autoRun, currentEntry->runFileNum-1, this->playlist->showLoadAddressInfo); } else if (ext->CompareWith("crt") || ext->CompareWith("CRT")) { - viewC64->viewC64MainMenu->InsertCartridge(entry->filePath, false); + viewC64->mainMenuHelper->InsertCartridge(entry->filePath, false); } else if (ext->CompareWith("reu") || ext->CompareWith("REU")) { bool val = true; C64DebuggerSetSetting("ReuEnabled", &val); - viewC64->viewC64MainMenu->AttachReu(entry->filePath, false, false); + viewC64->mainMenuHelper->AttachReu(entry->filePath, false, false); } else if (ext->CompareWith("snap") || ext->CompareWith("SNAP") || ext->CompareWith("vsf") || ext->CompareWith("VSF")) diff --git a/tools/c64d-champ/c64d-champ.rb b/tools/c64d-champ/c64d-champ.rb old mode 100644 new mode 100755 index b95a0ef..0fdc369 --- a/tools/c64d-champ/c64d-champ.rb +++ b/tools/c64d-champ/c64d-champ.rb @@ -1,5 +1,9 @@ #!/usr/bin/env ruby +# https://github.com/specht/champ +# Champ - N. Harold Cham's 65C02 Profiler +# modified for Retro Debugger by Marcin 'slajerek' Skoczylas + require 'fileutils' require 'open3' require 'set' diff --git a/tools/websockets-debugger-test/.DS_Store b/tools/websockets-debugger-test/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/tools/websockets-debugger-test/.DS_Store differ diff --git a/tools/websockets-debugger-test/client-test.js b/tools/websockets-debugger-test/client-test.js new file mode 100644 index 0000000..af26007 --- /dev/null +++ b/tools/websockets-debugger-test/client-test.js @@ -0,0 +1,171 @@ +// Node.js WebSocket client to test the RetroDebugger server +const WebSocket = require('ws'); + +const ws = new WebSocket('ws://localhost:3563/stream'); + +ws.on('open', () => { + console.log('Connected to WebSocket server'); + + // note: token field is optional and always returned with response + + // // load + jsonMessage = { + "fn": "load", + "params": { + "path": "/Users/mars/develop/c64d/docs/tests/eob v1.00 20221121.crt" + } + }; + ws.send(JSON.stringify(jsonMessage)); + + // hard reset + // jsonMessage = { + // "fn": "c64/reset/hard", + // "token": "blabla" + // }; + // ws.send(JSON.stringify(jsonMessage)); + + // pause/continue + // jsonMessage = { + // "fn": "c64/pause", + // // "fn": "c64/continue", + // }; + // ws.send(JSON.stringify(jsonMessage)); + + // // cpu status + // jsonMessage = { + // "fn": "c64/cpu/status", + // }; + // ws.send(JSON.stringify(jsonMessage)); + + // // writeBlock including I/O, how the CPU sees + // jsonBinMessage = { + // "fn": "c64/cpu/memory/writeBlock", + // "params": { + // "address": 0xD82C, + // } + // }; + // const binaryData = Buffer.from([0xDE, 0xAD, 0xBE, 0xEF]); + // const messageWithBinary = Buffer.concat([Buffer.from(JSON.stringify(jsonBinMessage) + '\0'), binaryData]); + // ws.send(messageWithBinary); + + // // readBlock read without I/O, directly from RAM + // jsonMessage = { + // "fn": "c64/ram/readBlock", + // "params": { + // "address": 0xD800, + // "size": 2024 + // } + // }; + // ws.send(JSON.stringify(jsonMessage)); + + // // VIC + // jsonMessage = { + // "fn": "c64/vic/write", + // "params": { + // "registers": { + // "0xD020": 5, + // "$21": 7, + // "17" : "$3B" + // } + // } + // }; + // ws.send(JSON.stringify(jsonMessage)); + + // // VIC + // jsonMessage = { + // "fn": "c64/vic/read", + // "params": { + // "registers": [ + // "0xD020", "$21", "17" + // ] + // } + // }; + // ws.send(JSON.stringify(jsonMessage)); + + // // breakpoint PC + // jsonMessage = { + // "fn": "c64/cpu/breakpoint/add", + // // "fn": "c64/cpu/breakpoint/remove", + // "params": { + // "addr" : 0xFEAF + // } + // }; + // ws.send(JSON.stringify(jsonMessage)); + + // // breakpoint memory + // jsonMessage = { + // "fn": "c64/cpu/memory/breakpoint/add", + // // "fn": "c64/cpu/memory/breakpoint/remove", + // "params": { + // "addr" : 0x1000, + // "access" : "write", + // "comparison" : "<", + // "value" : 0x80 + // } + // }; + // ws.send(JSON.stringify(jsonMessage)); + + // breakpoint VIC raster line + jsonMessage = { + "fn": "c64/vic/breakpoint/add", + // "fn": "c64/vic/breakpoint/remove", + "params": { + "rasterLine" : 0x32 + } + }; + ws.send(JSON.stringify(jsonMessage)); + + // // current segment + jsonMessage = { + "fn": "c64/segment/read", + //"fn": "c64/segment/write", + "params" : { + "segment" : "Code" + } + }; + ws.send(JSON.stringify(jsonMessage)); + + +}); + +ws.on('message', (data) => { + // Parse JSON response + const nullPos = data.indexOf(0); + let jsonResponse; + let binaryData; + + if (nullPos !== -1) { + // if there is a null byte, separate JSON and binary data + jsonResponse = data.slice(0, nullPos).toString(); + binaryData = data.slice(nullPos + 1); + } else { + // if there is no null byte, the data is just JSON + jsonResponse = data.toString(); + } + + try { + const parsedResponse = JSON.parse(jsonResponse); + console.log('Received:', parsedResponse); + + if (binaryData) { + console.log('Received binary data:', binaryData); + } + + // // on breakpoint - continue run + // jsonMessage = { + // "fn": "c64/continue", + // }; + // ws.send(JSON.stringify(jsonMessage)); + + } catch (e) { + console.error('Error parsing JSON response:', e); + } +}); + +ws.on('close', (code, reason) => { + console.log(`WebSocket connection closed with code: ${code}, reason: ${reason}`); +}); + +ws.on('error', (error) => { + console.error('WebSocket error:', error); +}); diff --git a/tools/websockets-debugger-test/node_modules/.package-lock.json b/tools/websockets-debugger-test/node_modules/.package-lock.json new file mode 100644 index 0000000..470ae27 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/.package-lock.json @@ -0,0 +1,29 @@ +{ + "name": "websockets-debugger-test", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/tools/websockets-debugger-test/node_modules/ws/LICENSE b/tools/websockets-debugger-test/node_modules/ws/LICENSE new file mode 100644 index 0000000..1da5b96 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2011 Einar Otto Stangvik +Copyright (c) 2013 Arnout Kazemier and contributors +Copyright (c) 2016 Luigi Pinca and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/tools/websockets-debugger-test/node_modules/ws/README.md b/tools/websockets-debugger-test/node_modules/ws/README.md new file mode 100644 index 0000000..21f10df --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/README.md @@ -0,0 +1,548 @@ +# ws: a Node.js WebSocket library + +[![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws) +[![CI](https://img.shields.io/github/actions/workflow/status/websockets/ws/ci.yml?branch=master&label=CI&logo=github)](https://github.com/websockets/ws/actions?query=workflow%3ACI+branch%3Amaster) +[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg?logo=coveralls)](https://coveralls.io/github/websockets/ws) + +ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and +server implementation. + +Passes the quite extensive Autobahn test suite: [server][server-report], +[client][client-report]. + +**Note**: This module does not work in the browser. The client in the docs is a +reference to a backend with the role of a client in the WebSocket communication. +Browser clients must use the native +[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) +object. To make the same code work seamlessly on Node.js and the browser, you +can use one of the many wrappers available on npm, like +[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws). + +## Table of Contents + +- [Protocol support](#protocol-support) +- [Installing](#installing) + - [Opt-in for performance](#opt-in-for-performance) + - [Legacy opt-in for performance](#legacy-opt-in-for-performance) +- [API docs](#api-docs) +- [WebSocket compression](#websocket-compression) +- [Usage examples](#usage-examples) + - [Sending and receiving text data](#sending-and-receiving-text-data) + - [Sending binary data](#sending-binary-data) + - [Simple server](#simple-server) + - [External HTTP/S server](#external-https-server) + - [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server) + - [Client authentication](#client-authentication) + - [Server broadcast](#server-broadcast) + - [Round-trip time](#round-trip-time) + - [Use the Node.js streams API](#use-the-nodejs-streams-api) + - [Other examples](#other-examples) +- [FAQ](#faq) + - [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client) + - [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections) + - [How to connect via a proxy?](#how-to-connect-via-a-proxy) +- [Changelog](#changelog) +- [License](#license) + +## Protocol support + +- **HyBi drafts 07-12** (Use the option `protocolVersion: 8`) +- **HyBi drafts 13-17** (Current default, alternatively option + `protocolVersion: 13`) + +## Installing + +``` +npm install ws +``` + +### Opt-in for performance + +[bufferutil][] is an optional module that can be installed alongside the ws +module: + +``` +npm install --save-optional bufferutil +``` + +This is a binary addon that improves the performance of certain operations such +as masking and unmasking the data payload of the WebSocket frames. Prebuilt +binaries are available for the most popular platforms, so you don't necessarily +need to have a C++ compiler installed on your machine. + +To force ws to not use bufferutil, use the +[`WS_NO_BUFFER_UTIL`](./doc/ws.md#ws_no_buffer_util) environment variable. This +can be useful to enhance security in systems where a user can put a package in +the package search path of an application of another user, due to how the +Node.js resolver algorithm works. + +#### Legacy opt-in for performance + +If you are running on an old version of Node.js (prior to v18.14.0), ws also +supports the [utf-8-validate][] module: + +``` +npm install --save-optional utf-8-validate +``` + +This contains a binary polyfill for [`buffer.isUtf8()`][]. + +To force ws not to use utf-8-validate, use the +[`WS_NO_UTF_8_VALIDATE`](./doc/ws.md#ws_no_utf_8_validate) environment variable. + +## API docs + +See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and +utility functions. + +## WebSocket compression + +ws supports the [permessage-deflate extension][permessage-deflate] which enables +the client and server to negotiate a compression algorithm and its parameters, +and then selectively apply it to the data payloads of each WebSocket message. + +The extension is disabled by default on the server and enabled by default on the +client. It adds a significant overhead in terms of performance and memory +consumption so we suggest to enable it only if it is really needed. + +Note that Node.js has a variety of issues with high-performance compression, +where increased concurrency, especially on Linux, can lead to [catastrophic +memory fragmentation][node-zlib-bug] and slow performance. If you intend to use +permessage-deflate in production, it is worthwhile to set up a test +representative of your workload and ensure Node.js/zlib will handle it with +acceptable performance and memory usage. + +Tuning of permessage-deflate can be done via the options defined below. You can +also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly +into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs]. + +See [the docs][ws-server-options] for more options. + +```js +import WebSocket, { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ + port: 8080, + perMessageDeflate: { + zlibDeflateOptions: { + // See zlib defaults. + chunkSize: 1024, + memLevel: 7, + level: 3 + }, + zlibInflateOptions: { + chunkSize: 10 * 1024 + }, + // Other options settable: + clientNoContextTakeover: true, // Defaults to negotiated value. + serverNoContextTakeover: true, // Defaults to negotiated value. + serverMaxWindowBits: 10, // Defaults to negotiated value. + // Below options specified as default values. + concurrencyLimit: 10, // Limits zlib concurrency for perf. + threshold: 1024 // Size (in bytes) below which messages + // should not be compressed if context takeover is disabled. + } +}); +``` + +The client will only use the extension if it is supported and enabled on the +server. To always disable the extension on the client, set the +`perMessageDeflate` option to `false`. + +```js +import WebSocket from 'ws'; + +const ws = new WebSocket('ws://www.host.com/path', { + perMessageDeflate: false +}); +``` + +## Usage examples + +### Sending and receiving text data + +```js +import WebSocket from 'ws'; + +const ws = new WebSocket('ws://www.host.com/path'); + +ws.on('error', console.error); + +ws.on('open', function open() { + ws.send('something'); +}); + +ws.on('message', function message(data) { + console.log('received: %s', data); +}); +``` + +### Sending binary data + +```js +import WebSocket from 'ws'; + +const ws = new WebSocket('ws://www.host.com/path'); + +ws.on('error', console.error); + +ws.on('open', function open() { + const array = new Float32Array(5); + + for (var i = 0; i < array.length; ++i) { + array[i] = i / 2; + } + + ws.send(array); +}); +``` + +### Simple server + +```js +import { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('error', console.error); + + ws.on('message', function message(data) { + console.log('received: %s', data); + }); + + ws.send('something'); +}); +``` + +### External HTTP/S server + +```js +import { createServer } from 'https'; +import { readFileSync } from 'fs'; +import { WebSocketServer } from 'ws'; + +const server = createServer({ + cert: readFileSync('/path/to/cert.pem'), + key: readFileSync('/path/to/key.pem') +}); +const wss = new WebSocketServer({ server }); + +wss.on('connection', function connection(ws) { + ws.on('error', console.error); + + ws.on('message', function message(data) { + console.log('received: %s', data); + }); + + ws.send('something'); +}); + +server.listen(8080); +``` + +### Multiple servers sharing a single HTTP/S server + +```js +import { createServer } from 'http'; +import { WebSocketServer } from 'ws'; + +const server = createServer(); +const wss1 = new WebSocketServer({ noServer: true }); +const wss2 = new WebSocketServer({ noServer: true }); + +wss1.on('connection', function connection(ws) { + ws.on('error', console.error); + + // ... +}); + +wss2.on('connection', function connection(ws) { + ws.on('error', console.error); + + // ... +}); + +server.on('upgrade', function upgrade(request, socket, head) { + const { pathname } = new URL(request.url, 'wss://base.url'); + + if (pathname === '/foo') { + wss1.handleUpgrade(request, socket, head, function done(ws) { + wss1.emit('connection', ws, request); + }); + } else if (pathname === '/bar') { + wss2.handleUpgrade(request, socket, head, function done(ws) { + wss2.emit('connection', ws, request); + }); + } else { + socket.destroy(); + } +}); + +server.listen(8080); +``` + +### Client authentication + +```js +import { createServer } from 'http'; +import { WebSocketServer } from 'ws'; + +function onSocketError(err) { + console.error(err); +} + +const server = createServer(); +const wss = new WebSocketServer({ noServer: true }); + +wss.on('connection', function connection(ws, request, client) { + ws.on('error', console.error); + + ws.on('message', function message(data) { + console.log(`Received message ${data} from user ${client}`); + }); +}); + +server.on('upgrade', function upgrade(request, socket, head) { + socket.on('error', onSocketError); + + // This function is not defined on purpose. Implement it with your own logic. + authenticate(request, function next(err, client) { + if (err || !client) { + socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n'); + socket.destroy(); + return; + } + + socket.removeListener('error', onSocketError); + + wss.handleUpgrade(request, socket, head, function done(ws) { + wss.emit('connection', ws, request, client); + }); + }); +}); + +server.listen(8080); +``` + +Also see the provided [example][session-parse-example] using `express-session`. + +### Server broadcast + +A client WebSocket broadcasting to all connected WebSocket clients, including +itself. + +```js +import WebSocket, { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('error', console.error); + + ws.on('message', function message(data, isBinary) { + wss.clients.forEach(function each(client) { + if (client.readyState === WebSocket.OPEN) { + client.send(data, { binary: isBinary }); + } + }); + }); +}); +``` + +A client WebSocket broadcasting to every other connected WebSocket clients, +excluding itself. + +```js +import WebSocket, { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('error', console.error); + + ws.on('message', function message(data, isBinary) { + wss.clients.forEach(function each(client) { + if (client !== ws && client.readyState === WebSocket.OPEN) { + client.send(data, { binary: isBinary }); + } + }); + }); +}); +``` + +### Round-trip time + +```js +import WebSocket from 'ws'; + +const ws = new WebSocket('wss://websocket-echo.com/'); + +ws.on('error', console.error); + +ws.on('open', function open() { + console.log('connected'); + ws.send(Date.now()); +}); + +ws.on('close', function close() { + console.log('disconnected'); +}); + +ws.on('message', function message(data) { + console.log(`Round-trip time: ${Date.now() - data} ms`); + + setTimeout(function timeout() { + ws.send(Date.now()); + }, 500); +}); +``` + +### Use the Node.js streams API + +```js +import WebSocket, { createWebSocketStream } from 'ws'; + +const ws = new WebSocket('wss://websocket-echo.com/'); + +const duplex = createWebSocketStream(ws, { encoding: 'utf8' }); + +duplex.on('error', console.error); + +duplex.pipe(process.stdout); +process.stdin.pipe(duplex); +``` + +### Other examples + +For a full example with a browser client communicating with a ws server, see the +examples folder. + +Otherwise, see the test cases. + +## FAQ + +### How to get the IP address of the client? + +The remote IP address can be obtained from the raw socket. + +```js +import { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws, req) { + const ip = req.socket.remoteAddress; + + ws.on('error', console.error); +}); +``` + +When the server runs behind a proxy like NGINX, the de-facto standard is to use +the `X-Forwarded-For` header. + +```js +wss.on('connection', function connection(ws, req) { + const ip = req.headers['x-forwarded-for'].split(',')[0].trim(); + + ws.on('error', console.error); +}); +``` + +### How to detect and close broken connections? + +Sometimes, the link between the server and the client can be interrupted in a +way that keeps both the server and the client unaware of the broken state of the +connection (e.g. when pulling the cord). + +In these cases, ping messages can be used as a means to verify that the remote +endpoint is still responsive. + +```js +import { WebSocketServer } from 'ws'; + +function heartbeat() { + this.isAlive = true; +} + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.isAlive = true; + ws.on('error', console.error); + ws.on('pong', heartbeat); +}); + +const interval = setInterval(function ping() { + wss.clients.forEach(function each(ws) { + if (ws.isAlive === false) return ws.terminate(); + + ws.isAlive = false; + ws.ping(); + }); +}, 30000); + +wss.on('close', function close() { + clearInterval(interval); +}); +``` + +Pong messages are automatically sent in response to ping messages as required by +the spec. + +Just like the server example above, your clients might as well lose connection +without knowing it. You might want to add a ping listener on your clients to +prevent that. A simple implementation would be: + +```js +import WebSocket from 'ws'; + +function heartbeat() { + clearTimeout(this.pingTimeout); + + // Use `WebSocket#terminate()`, which immediately destroys the connection, + // instead of `WebSocket#close()`, which waits for the close timer. + // Delay should be equal to the interval at which your server + // sends out pings plus a conservative assumption of the latency. + this.pingTimeout = setTimeout(() => { + this.terminate(); + }, 30000 + 1000); +} + +const client = new WebSocket('wss://websocket-echo.com/'); + +client.on('error', console.error); +client.on('open', heartbeat); +client.on('ping', heartbeat); +client.on('close', function clear() { + clearTimeout(this.pingTimeout); +}); +``` + +### How to connect via a proxy? + +Use a custom `http.Agent` implementation like [https-proxy-agent][] or +[socks-proxy-agent][]. + +## Changelog + +We're using the GitHub [releases][changelog] for changelog entries. + +## License + +[MIT](LICENSE) + +[`buffer.isutf8()`]: https://nodejs.org/api/buffer.html#bufferisutf8input +[bufferutil]: https://github.com/websockets/bufferutil +[changelog]: https://github.com/websockets/ws/releases +[client-report]: http://websockets.github.io/ws/autobahn/clients/ +[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent +[node-zlib-bug]: https://github.com/nodejs/node/issues/8871 +[node-zlib-deflaterawdocs]: + https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options +[permessage-deflate]: https://tools.ietf.org/html/rfc7692 +[server-report]: http://websockets.github.io/ws/autobahn/servers/ +[session-parse-example]: ./examples/express-session-parse +[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent +[utf-8-validate]: https://github.com/websockets/utf-8-validate +[ws-server-options]: ./doc/ws.md#new-websocketserveroptions-callback diff --git a/tools/websockets-debugger-test/node_modules/ws/browser.js b/tools/websockets-debugger-test/node_modules/ws/browser.js new file mode 100644 index 0000000..ca4f628 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/browser.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = function () { + throw new Error( + 'ws does not work in the browser. Browser clients must use the native ' + + 'WebSocket object' + ); +}; diff --git a/tools/websockets-debugger-test/node_modules/ws/index.js b/tools/websockets-debugger-test/node_modules/ws/index.js new file mode 100644 index 0000000..41edb3b --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/index.js @@ -0,0 +1,13 @@ +'use strict'; + +const WebSocket = require('./lib/websocket'); + +WebSocket.createWebSocketStream = require('./lib/stream'); +WebSocket.Server = require('./lib/websocket-server'); +WebSocket.Receiver = require('./lib/receiver'); +WebSocket.Sender = require('./lib/sender'); + +WebSocket.WebSocket = WebSocket; +WebSocket.WebSocketServer = WebSocket.Server; + +module.exports = WebSocket; diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/buffer-util.js b/tools/websockets-debugger-test/node_modules/ws/lib/buffer-util.js new file mode 100644 index 0000000..f7536e2 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/buffer-util.js @@ -0,0 +1,131 @@ +'use strict'; + +const { EMPTY_BUFFER } = require('./constants'); + +const FastBuffer = Buffer[Symbol.species]; + +/** + * Merges an array of buffers into a new buffer. + * + * @param {Buffer[]} list The array of buffers to concat + * @param {Number} totalLength The total length of buffers in the list + * @return {Buffer} The resulting buffer + * @public + */ +function concat(list, totalLength) { + if (list.length === 0) return EMPTY_BUFFER; + if (list.length === 1) return list[0]; + + const target = Buffer.allocUnsafe(totalLength); + let offset = 0; + + for (let i = 0; i < list.length; i++) { + const buf = list[i]; + target.set(buf, offset); + offset += buf.length; + } + + if (offset < totalLength) { + return new FastBuffer(target.buffer, target.byteOffset, offset); + } + + return target; +} + +/** + * Masks a buffer using the given mask. + * + * @param {Buffer} source The buffer to mask + * @param {Buffer} mask The mask to use + * @param {Buffer} output The buffer where to store the result + * @param {Number} offset The offset at which to start writing + * @param {Number} length The number of bytes to mask. + * @public + */ +function _mask(source, mask, output, offset, length) { + for (let i = 0; i < length; i++) { + output[offset + i] = source[i] ^ mask[i & 3]; + } +} + +/** + * Unmasks a buffer using the given mask. + * + * @param {Buffer} buffer The buffer to unmask + * @param {Buffer} mask The mask to use + * @public + */ +function _unmask(buffer, mask) { + for (let i = 0; i < buffer.length; i++) { + buffer[i] ^= mask[i & 3]; + } +} + +/** + * Converts a buffer to an `ArrayBuffer`. + * + * @param {Buffer} buf The buffer to convert + * @return {ArrayBuffer} Converted buffer + * @public + */ +function toArrayBuffer(buf) { + if (buf.length === buf.buffer.byteLength) { + return buf.buffer; + } + + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length); +} + +/** + * Converts `data` to a `Buffer`. + * + * @param {*} data The data to convert + * @return {Buffer} The buffer + * @throws {TypeError} + * @public + */ +function toBuffer(data) { + toBuffer.readOnly = true; + + if (Buffer.isBuffer(data)) return data; + + let buf; + + if (data instanceof ArrayBuffer) { + buf = new FastBuffer(data); + } else if (ArrayBuffer.isView(data)) { + buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength); + } else { + buf = Buffer.from(data); + toBuffer.readOnly = false; + } + + return buf; +} + +module.exports = { + concat, + mask: _mask, + toArrayBuffer, + toBuffer, + unmask: _unmask +}; + +/* istanbul ignore else */ +if (!process.env.WS_NO_BUFFER_UTIL) { + try { + const bufferUtil = require('bufferutil'); + + module.exports.mask = function (source, mask, output, offset, length) { + if (length < 48) _mask(source, mask, output, offset, length); + else bufferUtil.mask(source, mask, output, offset, length); + }; + + module.exports.unmask = function (buffer, mask) { + if (buffer.length < 32) _unmask(buffer, mask); + else bufferUtil.unmask(buffer, mask); + }; + } catch (e) { + // Continue regardless of the error. + } +} diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/constants.js b/tools/websockets-debugger-test/node_modules/ws/lib/constants.js new file mode 100644 index 0000000..74214d4 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/constants.js @@ -0,0 +1,18 @@ +'use strict'; + +const BINARY_TYPES = ['nodebuffer', 'arraybuffer', 'fragments']; +const hasBlob = typeof Blob !== 'undefined'; + +if (hasBlob) BINARY_TYPES.push('blob'); + +module.exports = { + BINARY_TYPES, + EMPTY_BUFFER: Buffer.alloc(0), + GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', + hasBlob, + kForOnEventAttribute: Symbol('kIsForOnEventAttribute'), + kListener: Symbol('kListener'), + kStatusCode: Symbol('status-code'), + kWebSocket: Symbol('websocket'), + NOOP: () => {} +}; diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/event-target.js b/tools/websockets-debugger-test/node_modules/ws/lib/event-target.js new file mode 100644 index 0000000..fea4cbc --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/event-target.js @@ -0,0 +1,292 @@ +'use strict'; + +const { kForOnEventAttribute, kListener } = require('./constants'); + +const kCode = Symbol('kCode'); +const kData = Symbol('kData'); +const kError = Symbol('kError'); +const kMessage = Symbol('kMessage'); +const kReason = Symbol('kReason'); +const kTarget = Symbol('kTarget'); +const kType = Symbol('kType'); +const kWasClean = Symbol('kWasClean'); + +/** + * Class representing an event. + */ +class Event { + /** + * Create a new `Event`. + * + * @param {String} type The name of the event + * @throws {TypeError} If the `type` argument is not specified + */ + constructor(type) { + this[kTarget] = null; + this[kType] = type; + } + + /** + * @type {*} + */ + get target() { + return this[kTarget]; + } + + /** + * @type {String} + */ + get type() { + return this[kType]; + } +} + +Object.defineProperty(Event.prototype, 'target', { enumerable: true }); +Object.defineProperty(Event.prototype, 'type', { enumerable: true }); + +/** + * Class representing a close event. + * + * @extends Event + */ +class CloseEvent extends Event { + /** + * Create a new `CloseEvent`. + * + * @param {String} type The name of the event + * @param {Object} [options] A dictionary object that allows for setting + * attributes via object members of the same name + * @param {Number} [options.code=0] The status code explaining why the + * connection was closed + * @param {String} [options.reason=''] A human-readable string explaining why + * the connection was closed + * @param {Boolean} [options.wasClean=false] Indicates whether or not the + * connection was cleanly closed + */ + constructor(type, options = {}) { + super(type); + + this[kCode] = options.code === undefined ? 0 : options.code; + this[kReason] = options.reason === undefined ? '' : options.reason; + this[kWasClean] = options.wasClean === undefined ? false : options.wasClean; + } + + /** + * @type {Number} + */ + get code() { + return this[kCode]; + } + + /** + * @type {String} + */ + get reason() { + return this[kReason]; + } + + /** + * @type {Boolean} + */ + get wasClean() { + return this[kWasClean]; + } +} + +Object.defineProperty(CloseEvent.prototype, 'code', { enumerable: true }); +Object.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true }); +Object.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true }); + +/** + * Class representing an error event. + * + * @extends Event + */ +class ErrorEvent extends Event { + /** + * Create a new `ErrorEvent`. + * + * @param {String} type The name of the event + * @param {Object} [options] A dictionary object that allows for setting + * attributes via object members of the same name + * @param {*} [options.error=null] The error that generated this event + * @param {String} [options.message=''] The error message + */ + constructor(type, options = {}) { + super(type); + + this[kError] = options.error === undefined ? null : options.error; + this[kMessage] = options.message === undefined ? '' : options.message; + } + + /** + * @type {*} + */ + get error() { + return this[kError]; + } + + /** + * @type {String} + */ + get message() { + return this[kMessage]; + } +} + +Object.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true }); +Object.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true }); + +/** + * Class representing a message event. + * + * @extends Event + */ +class MessageEvent extends Event { + /** + * Create a new `MessageEvent`. + * + * @param {String} type The name of the event + * @param {Object} [options] A dictionary object that allows for setting + * attributes via object members of the same name + * @param {*} [options.data=null] The message content + */ + constructor(type, options = {}) { + super(type); + + this[kData] = options.data === undefined ? null : options.data; + } + + /** + * @type {*} + */ + get data() { + return this[kData]; + } +} + +Object.defineProperty(MessageEvent.prototype, 'data', { enumerable: true }); + +/** + * This provides methods for emulating the `EventTarget` interface. It's not + * meant to be used directly. + * + * @mixin + */ +const EventTarget = { + /** + * Register an event listener. + * + * @param {String} type A string representing the event type to listen for + * @param {(Function|Object)} handler The listener to add + * @param {Object} [options] An options object specifies characteristics about + * the event listener + * @param {Boolean} [options.once=false] A `Boolean` indicating that the + * listener should be invoked at most once after being added. If `true`, + * the listener would be automatically removed when invoked. + * @public + */ + addEventListener(type, handler, options = {}) { + for (const listener of this.listeners(type)) { + if ( + !options[kForOnEventAttribute] && + listener[kListener] === handler && + !listener[kForOnEventAttribute] + ) { + return; + } + } + + let wrapper; + + if (type === 'message') { + wrapper = function onMessage(data, isBinary) { + const event = new MessageEvent('message', { + data: isBinary ? data : data.toString() + }); + + event[kTarget] = this; + callListener(handler, this, event); + }; + } else if (type === 'close') { + wrapper = function onClose(code, message) { + const event = new CloseEvent('close', { + code, + reason: message.toString(), + wasClean: this._closeFrameReceived && this._closeFrameSent + }); + + event[kTarget] = this; + callListener(handler, this, event); + }; + } else if (type === 'error') { + wrapper = function onError(error) { + const event = new ErrorEvent('error', { + error, + message: error.message + }); + + event[kTarget] = this; + callListener(handler, this, event); + }; + } else if (type === 'open') { + wrapper = function onOpen() { + const event = new Event('open'); + + event[kTarget] = this; + callListener(handler, this, event); + }; + } else { + return; + } + + wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute]; + wrapper[kListener] = handler; + + if (options.once) { + this.once(type, wrapper); + } else { + this.on(type, wrapper); + } + }, + + /** + * Remove an event listener. + * + * @param {String} type A string representing the event type to remove + * @param {(Function|Object)} handler The listener to remove + * @public + */ + removeEventListener(type, handler) { + for (const listener of this.listeners(type)) { + if (listener[kListener] === handler && !listener[kForOnEventAttribute]) { + this.removeListener(type, listener); + break; + } + } + } +}; + +module.exports = { + CloseEvent, + ErrorEvent, + Event, + EventTarget, + MessageEvent +}; + +/** + * Call an event listener + * + * @param {(Function|Object)} listener The listener to call + * @param {*} thisArg The value to use as `this`` when calling the listener + * @param {Event} event The event to pass to the listener + * @private + */ +function callListener(listener, thisArg, event) { + if (typeof listener === 'object' && listener.handleEvent) { + listener.handleEvent.call(listener, event); + } else { + listener.call(thisArg, event); + } +} diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/extension.js b/tools/websockets-debugger-test/node_modules/ws/lib/extension.js new file mode 100644 index 0000000..3d7895c --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/extension.js @@ -0,0 +1,203 @@ +'use strict'; + +const { tokenChars } = require('./validation'); + +/** + * Adds an offer to the map of extension offers or a parameter to the map of + * parameters. + * + * @param {Object} dest The map of extension offers or parameters + * @param {String} name The extension or parameter name + * @param {(Object|Boolean|String)} elem The extension parameters or the + * parameter value + * @private + */ +function push(dest, name, elem) { + if (dest[name] === undefined) dest[name] = [elem]; + else dest[name].push(elem); +} + +/** + * Parses the `Sec-WebSocket-Extensions` header into an object. + * + * @param {String} header The field value of the header + * @return {Object} The parsed object + * @public + */ +function parse(header) { + const offers = Object.create(null); + let params = Object.create(null); + let mustUnescape = false; + let isEscaping = false; + let inQuotes = false; + let extensionName; + let paramName; + let start = -1; + let code = -1; + let end = -1; + let i = 0; + + for (; i < header.length; i++) { + code = header.charCodeAt(i); + + if (extensionName === undefined) { + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if ( + i !== 0 && + (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */ + ) { + if (end === -1 && start !== -1) end = i; + } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + const name = header.slice(start, end); + if (code === 0x2c) { + push(offers, name, params); + params = Object.create(null); + } else { + extensionName = name; + } + + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else if (paramName === undefined) { + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (code === 0x20 || code === 0x09) { + if (end === -1 && start !== -1) end = i; + } else if (code === 0x3b || code === 0x2c) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + push(params, header.slice(start, end), true); + if (code === 0x2c) { + push(offers, extensionName, params); + params = Object.create(null); + extensionName = undefined; + } + + start = end = -1; + } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) { + paramName = header.slice(start, i); + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else { + // + // The value of a quoted-string after unescaping must conform to the + // token ABNF, so only token characters are valid. + // Ref: https://tools.ietf.org/html/rfc6455#section-9.1 + // + if (isEscaping) { + if (tokenChars[code] !== 1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + if (start === -1) start = i; + else if (!mustUnescape) mustUnescape = true; + isEscaping = false; + } else if (inQuotes) { + if (tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (code === 0x22 /* '"' */ && start !== -1) { + inQuotes = false; + end = i; + } else if (code === 0x5c /* '\' */) { + isEscaping = true; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) { + inQuotes = true; + } else if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (start !== -1 && (code === 0x20 || code === 0x09)) { + if (end === -1) end = i; + } else if (code === 0x3b || code === 0x2c) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + let value = header.slice(start, end); + if (mustUnescape) { + value = value.replace(/\\/g, ''); + mustUnescape = false; + } + push(params, paramName, value); + if (code === 0x2c) { + push(offers, extensionName, params); + params = Object.create(null); + extensionName = undefined; + } + + paramName = undefined; + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } + } + + if (start === -1 || inQuotes || code === 0x20 || code === 0x09) { + throw new SyntaxError('Unexpected end of input'); + } + + if (end === -1) end = i; + const token = header.slice(start, end); + if (extensionName === undefined) { + push(offers, token, params); + } else { + if (paramName === undefined) { + push(params, token, true); + } else if (mustUnescape) { + push(params, paramName, token.replace(/\\/g, '')); + } else { + push(params, paramName, token); + } + push(offers, extensionName, params); + } + + return offers; +} + +/** + * Builds the `Sec-WebSocket-Extensions` header field value. + * + * @param {Object} extensions The map of extensions and parameters to format + * @return {String} A string representing the given object + * @public + */ +function format(extensions) { + return Object.keys(extensions) + .map((extension) => { + let configurations = extensions[extension]; + if (!Array.isArray(configurations)) configurations = [configurations]; + return configurations + .map((params) => { + return [extension] + .concat( + Object.keys(params).map((k) => { + let values = params[k]; + if (!Array.isArray(values)) values = [values]; + return values + .map((v) => (v === true ? k : `${k}=${v}`)) + .join('; '); + }) + ) + .join('; '); + }) + .join(', '); + }) + .join(', '); +} + +module.exports = { format, parse }; diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/limiter.js b/tools/websockets-debugger-test/node_modules/ws/lib/limiter.js new file mode 100644 index 0000000..3fd3578 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/limiter.js @@ -0,0 +1,55 @@ +'use strict'; + +const kDone = Symbol('kDone'); +const kRun = Symbol('kRun'); + +/** + * A very simple job queue with adjustable concurrency. Adapted from + * https://github.com/STRML/async-limiter + */ +class Limiter { + /** + * Creates a new `Limiter`. + * + * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed + * to run concurrently + */ + constructor(concurrency) { + this[kDone] = () => { + this.pending--; + this[kRun](); + }; + this.concurrency = concurrency || Infinity; + this.jobs = []; + this.pending = 0; + } + + /** + * Adds a job to the queue. + * + * @param {Function} job The job to run + * @public + */ + add(job) { + this.jobs.push(job); + this[kRun](); + } + + /** + * Removes a job from the queue and runs it if possible. + * + * @private + */ + [kRun]() { + if (this.pending === this.concurrency) return; + + if (this.jobs.length) { + const job = this.jobs.shift(); + + this.pending++; + job(this[kDone]); + } + } +} + +module.exports = Limiter; diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/permessage-deflate.js b/tools/websockets-debugger-test/node_modules/ws/lib/permessage-deflate.js new file mode 100644 index 0000000..77d918b --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/permessage-deflate.js @@ -0,0 +1,514 @@ +'use strict'; + +const zlib = require('zlib'); + +const bufferUtil = require('./buffer-util'); +const Limiter = require('./limiter'); +const { kStatusCode } = require('./constants'); + +const FastBuffer = Buffer[Symbol.species]; +const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]); +const kPerMessageDeflate = Symbol('permessage-deflate'); +const kTotalLength = Symbol('total-length'); +const kCallback = Symbol('callback'); +const kBuffers = Symbol('buffers'); +const kError = Symbol('error'); + +// +// We limit zlib concurrency, which prevents severe memory fragmentation +// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913 +// and https://github.com/websockets/ws/issues/1202 +// +// Intentionally global; it's the global thread pool that's an issue. +// +let zlibLimiter; + +/** + * permessage-deflate implementation. + */ +class PerMessageDeflate { + /** + * Creates a PerMessageDeflate instance. + * + * @param {Object} [options] Configuration options + * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support + * for, or request, a custom client window size + * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/ + * acknowledge disabling of client context takeover + * @param {Number} [options.concurrencyLimit=10] The number of concurrent + * calls to zlib + * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the + * use of a custom server window size + * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept + * disabling of server context takeover + * @param {Number} [options.threshold=1024] Size (in bytes) below which + * messages should not be compressed if context takeover is disabled + * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on + * deflate + * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on + * inflate + * @param {Boolean} [isServer=false] Create the instance in either server or + * client mode + * @param {Number} [maxPayload=0] The maximum allowed message length + */ + constructor(options, isServer, maxPayload) { + this._maxPayload = maxPayload | 0; + this._options = options || {}; + this._threshold = + this._options.threshold !== undefined ? this._options.threshold : 1024; + this._isServer = !!isServer; + this._deflate = null; + this._inflate = null; + + this.params = null; + + if (!zlibLimiter) { + const concurrency = + this._options.concurrencyLimit !== undefined + ? this._options.concurrencyLimit + : 10; + zlibLimiter = new Limiter(concurrency); + } + } + + /** + * @type {String} + */ + static get extensionName() { + return 'permessage-deflate'; + } + + /** + * Create an extension negotiation offer. + * + * @return {Object} Extension parameters + * @public + */ + offer() { + const params = {}; + + if (this._options.serverNoContextTakeover) { + params.server_no_context_takeover = true; + } + if (this._options.clientNoContextTakeover) { + params.client_no_context_takeover = true; + } + if (this._options.serverMaxWindowBits) { + params.server_max_window_bits = this._options.serverMaxWindowBits; + } + if (this._options.clientMaxWindowBits) { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } else if (this._options.clientMaxWindowBits == null) { + params.client_max_window_bits = true; + } + + return params; + } + + /** + * Accept an extension negotiation offer/response. + * + * @param {Array} configurations The extension negotiation offers/reponse + * @return {Object} Accepted configuration + * @public + */ + accept(configurations) { + configurations = this.normalizeParams(configurations); + + this.params = this._isServer + ? this.acceptAsServer(configurations) + : this.acceptAsClient(configurations); + + return this.params; + } + + /** + * Releases all resources used by the extension. + * + * @public + */ + cleanup() { + if (this._inflate) { + this._inflate.close(); + this._inflate = null; + } + + if (this._deflate) { + const callback = this._deflate[kCallback]; + + this._deflate.close(); + this._deflate = null; + + if (callback) { + callback( + new Error( + 'The deflate stream was closed while data was being processed' + ) + ); + } + } + } + + /** + * Accept an extension negotiation offer. + * + * @param {Array} offers The extension negotiation offers + * @return {Object} Accepted configuration + * @private + */ + acceptAsServer(offers) { + const opts = this._options; + const accepted = offers.find((params) => { + if ( + (opts.serverNoContextTakeover === false && + params.server_no_context_takeover) || + (params.server_max_window_bits && + (opts.serverMaxWindowBits === false || + (typeof opts.serverMaxWindowBits === 'number' && + opts.serverMaxWindowBits > params.server_max_window_bits))) || + (typeof opts.clientMaxWindowBits === 'number' && + !params.client_max_window_bits) + ) { + return false; + } + + return true; + }); + + if (!accepted) { + throw new Error('None of the extension offers can be accepted'); + } + + if (opts.serverNoContextTakeover) { + accepted.server_no_context_takeover = true; + } + if (opts.clientNoContextTakeover) { + accepted.client_no_context_takeover = true; + } + if (typeof opts.serverMaxWindowBits === 'number') { + accepted.server_max_window_bits = opts.serverMaxWindowBits; + } + if (typeof opts.clientMaxWindowBits === 'number') { + accepted.client_max_window_bits = opts.clientMaxWindowBits; + } else if ( + accepted.client_max_window_bits === true || + opts.clientMaxWindowBits === false + ) { + delete accepted.client_max_window_bits; + } + + return accepted; + } + + /** + * Accept the extension negotiation response. + * + * @param {Array} response The extension negotiation response + * @return {Object} Accepted configuration + * @private + */ + acceptAsClient(response) { + const params = response[0]; + + if ( + this._options.clientNoContextTakeover === false && + params.client_no_context_takeover + ) { + throw new Error('Unexpected parameter "client_no_context_takeover"'); + } + + if (!params.client_max_window_bits) { + if (typeof this._options.clientMaxWindowBits === 'number') { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } + } else if ( + this._options.clientMaxWindowBits === false || + (typeof this._options.clientMaxWindowBits === 'number' && + params.client_max_window_bits > this._options.clientMaxWindowBits) + ) { + throw new Error( + 'Unexpected or invalid parameter "client_max_window_bits"' + ); + } + + return params; + } + + /** + * Normalize parameters. + * + * @param {Array} configurations The extension negotiation offers/reponse + * @return {Array} The offers/response with normalized parameters + * @private + */ + normalizeParams(configurations) { + configurations.forEach((params) => { + Object.keys(params).forEach((key) => { + let value = params[key]; + + if (value.length > 1) { + throw new Error(`Parameter "${key}" must have only a single value`); + } + + value = value[0]; + + if (key === 'client_max_window_bits') { + if (value !== true) { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + value = num; + } else if (!this._isServer) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + } else if (key === 'server_max_window_bits') { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + value = num; + } else if ( + key === 'client_no_context_takeover' || + key === 'server_no_context_takeover' + ) { + if (value !== true) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + } else { + throw new Error(`Unknown parameter "${key}"`); + } + + params[key] = value; + }); + }); + + return configurations; + } + + /** + * Decompress data. Concurrency limited. + * + * @param {Buffer} data Compressed data + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @public + */ + decompress(data, fin, callback) { + zlibLimiter.add((done) => { + this._decompress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + + /** + * Compress data. Concurrency limited. + * + * @param {(Buffer|String)} data Data to compress + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @public + */ + compress(data, fin, callback) { + zlibLimiter.add((done) => { + this._compress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + + /** + * Decompress data. + * + * @param {Buffer} data Compressed data + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @private + */ + _decompress(data, fin, callback) { + const endpoint = this._isServer ? 'client' : 'server'; + + if (!this._inflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = + typeof this.params[key] !== 'number' + ? zlib.Z_DEFAULT_WINDOWBITS + : this.params[key]; + + this._inflate = zlib.createInflateRaw({ + ...this._options.zlibInflateOptions, + windowBits + }); + this._inflate[kPerMessageDeflate] = this; + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + this._inflate.on('error', inflateOnError); + this._inflate.on('data', inflateOnData); + } + + this._inflate[kCallback] = callback; + + this._inflate.write(data); + if (fin) this._inflate.write(TRAILER); + + this._inflate.flush(() => { + const err = this._inflate[kError]; + + if (err) { + this._inflate.close(); + this._inflate = null; + callback(err); + return; + } + + const data = bufferUtil.concat( + this._inflate[kBuffers], + this._inflate[kTotalLength] + ); + + if (this._inflate._readableState.endEmitted) { + this._inflate.close(); + this._inflate = null; + } else { + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + + if (fin && this.params[`${endpoint}_no_context_takeover`]) { + this._inflate.reset(); + } + } + + callback(null, data); + }); + } + + /** + * Compress data. + * + * @param {(Buffer|String)} data Data to compress + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @private + */ + _compress(data, fin, callback) { + const endpoint = this._isServer ? 'server' : 'client'; + + if (!this._deflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = + typeof this.params[key] !== 'number' + ? zlib.Z_DEFAULT_WINDOWBITS + : this.params[key]; + + this._deflate = zlib.createDeflateRaw({ + ...this._options.zlibDeflateOptions, + windowBits + }); + + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + + this._deflate.on('data', deflateOnData); + } + + this._deflate[kCallback] = callback; + + this._deflate.write(data); + this._deflate.flush(zlib.Z_SYNC_FLUSH, () => { + if (!this._deflate) { + // + // The deflate stream was closed while data was being processed. + // + return; + } + + let data = bufferUtil.concat( + this._deflate[kBuffers], + this._deflate[kTotalLength] + ); + + if (fin) { + data = new FastBuffer(data.buffer, data.byteOffset, data.length - 4); + } + + // + // Ensure that the callback will not be called again in + // `PerMessageDeflate#cleanup()`. + // + this._deflate[kCallback] = null; + + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + + if (fin && this.params[`${endpoint}_no_context_takeover`]) { + this._deflate.reset(); + } + + callback(null, data); + }); + } +} + +module.exports = PerMessageDeflate; + +/** + * The listener of the `zlib.DeflateRaw` stream `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function deflateOnData(chunk) { + this[kBuffers].push(chunk); + this[kTotalLength] += chunk.length; +} + +/** + * The listener of the `zlib.InflateRaw` stream `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function inflateOnData(chunk) { + this[kTotalLength] += chunk.length; + + if ( + this[kPerMessageDeflate]._maxPayload < 1 || + this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload + ) { + this[kBuffers].push(chunk); + return; + } + + this[kError] = new RangeError('Max payload size exceeded'); + this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'; + this[kError][kStatusCode] = 1009; + this.removeListener('data', inflateOnData); + this.reset(); +} + +/** + * The listener of the `zlib.InflateRaw` stream `'error'` event. + * + * @param {Error} err The emitted error + * @private + */ +function inflateOnError(err) { + // + // There is no need to call `Zlib#close()` as the handle is automatically + // closed when an error is emitted. + // + this[kPerMessageDeflate]._inflate = null; + err[kStatusCode] = 1007; + this[kCallback](err); +} diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/receiver.js b/tools/websockets-debugger-test/node_modules/ws/lib/receiver.js new file mode 100644 index 0000000..54d9b4f --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/receiver.js @@ -0,0 +1,706 @@ +'use strict'; + +const { Writable } = require('stream'); + +const PerMessageDeflate = require('./permessage-deflate'); +const { + BINARY_TYPES, + EMPTY_BUFFER, + kStatusCode, + kWebSocket +} = require('./constants'); +const { concat, toArrayBuffer, unmask } = require('./buffer-util'); +const { isValidStatusCode, isValidUTF8 } = require('./validation'); + +const FastBuffer = Buffer[Symbol.species]; + +const GET_INFO = 0; +const GET_PAYLOAD_LENGTH_16 = 1; +const GET_PAYLOAD_LENGTH_64 = 2; +const GET_MASK = 3; +const GET_DATA = 4; +const INFLATING = 5; +const DEFER_EVENT = 6; + +/** + * HyBi Receiver implementation. + * + * @extends Writable + */ +class Receiver extends Writable { + /** + * Creates a Receiver instance. + * + * @param {Object} [options] Options object + * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether + * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted + * multiple times in the same tick + * @param {String} [options.binaryType=nodebuffer] The type for binary data + * @param {Object} [options.extensions] An object containing the negotiated + * extensions + * @param {Boolean} [options.isServer=false] Specifies whether to operate in + * client or server mode + * @param {Number} [options.maxPayload=0] The maximum allowed message length + * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or + * not to skip UTF-8 validation for text and close messages + */ + constructor(options = {}) { + super(); + + this._allowSynchronousEvents = + options.allowSynchronousEvents !== undefined + ? options.allowSynchronousEvents + : true; + this._binaryType = options.binaryType || BINARY_TYPES[0]; + this._extensions = options.extensions || {}; + this._isServer = !!options.isServer; + this._maxPayload = options.maxPayload | 0; + this._skipUTF8Validation = !!options.skipUTF8Validation; + this[kWebSocket] = undefined; + + this._bufferedBytes = 0; + this._buffers = []; + + this._compressed = false; + this._payloadLength = 0; + this._mask = undefined; + this._fragmented = 0; + this._masked = false; + this._fin = false; + this._opcode = 0; + + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragments = []; + + this._errored = false; + this._loop = false; + this._state = GET_INFO; + } + + /** + * Implements `Writable.prototype._write()`. + * + * @param {Buffer} chunk The chunk of data to write + * @param {String} encoding The character encoding of `chunk` + * @param {Function} cb Callback + * @private + */ + _write(chunk, encoding, cb) { + if (this._opcode === 0x08 && this._state == GET_INFO) return cb(); + + this._bufferedBytes += chunk.length; + this._buffers.push(chunk); + this.startLoop(cb); + } + + /** + * Consumes `n` bytes from the buffered data. + * + * @param {Number} n The number of bytes to consume + * @return {Buffer} The consumed bytes + * @private + */ + consume(n) { + this._bufferedBytes -= n; + + if (n === this._buffers[0].length) return this._buffers.shift(); + + if (n < this._buffers[0].length) { + const buf = this._buffers[0]; + this._buffers[0] = new FastBuffer( + buf.buffer, + buf.byteOffset + n, + buf.length - n + ); + + return new FastBuffer(buf.buffer, buf.byteOffset, n); + } + + const dst = Buffer.allocUnsafe(n); + + do { + const buf = this._buffers[0]; + const offset = dst.length - n; + + if (n >= buf.length) { + dst.set(this._buffers.shift(), offset); + } else { + dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset); + this._buffers[0] = new FastBuffer( + buf.buffer, + buf.byteOffset + n, + buf.length - n + ); + } + + n -= buf.length; + } while (n > 0); + + return dst; + } + + /** + * Starts the parsing loop. + * + * @param {Function} cb Callback + * @private + */ + startLoop(cb) { + this._loop = true; + + do { + switch (this._state) { + case GET_INFO: + this.getInfo(cb); + break; + case GET_PAYLOAD_LENGTH_16: + this.getPayloadLength16(cb); + break; + case GET_PAYLOAD_LENGTH_64: + this.getPayloadLength64(cb); + break; + case GET_MASK: + this.getMask(); + break; + case GET_DATA: + this.getData(cb); + break; + case INFLATING: + case DEFER_EVENT: + this._loop = false; + return; + } + } while (this._loop); + + if (!this._errored) cb(); + } + + /** + * Reads the first two bytes of a frame. + * + * @param {Function} cb Callback + * @private + */ + getInfo(cb) { + if (this._bufferedBytes < 2) { + this._loop = false; + return; + } + + const buf = this.consume(2); + + if ((buf[0] & 0x30) !== 0x00) { + const error = this.createError( + RangeError, + 'RSV2 and RSV3 must be clear', + true, + 1002, + 'WS_ERR_UNEXPECTED_RSV_2_3' + ); + + cb(error); + return; + } + + const compressed = (buf[0] & 0x40) === 0x40; + + if (compressed && !this._extensions[PerMessageDeflate.extensionName]) { + const error = this.createError( + RangeError, + 'RSV1 must be clear', + true, + 1002, + 'WS_ERR_UNEXPECTED_RSV_1' + ); + + cb(error); + return; + } + + this._fin = (buf[0] & 0x80) === 0x80; + this._opcode = buf[0] & 0x0f; + this._payloadLength = buf[1] & 0x7f; + + if (this._opcode === 0x00) { + if (compressed) { + const error = this.createError( + RangeError, + 'RSV1 must be clear', + true, + 1002, + 'WS_ERR_UNEXPECTED_RSV_1' + ); + + cb(error); + return; + } + + if (!this._fragmented) { + const error = this.createError( + RangeError, + 'invalid opcode 0', + true, + 1002, + 'WS_ERR_INVALID_OPCODE' + ); + + cb(error); + return; + } + + this._opcode = this._fragmented; + } else if (this._opcode === 0x01 || this._opcode === 0x02) { + if (this._fragmented) { + const error = this.createError( + RangeError, + `invalid opcode ${this._opcode}`, + true, + 1002, + 'WS_ERR_INVALID_OPCODE' + ); + + cb(error); + return; + } + + this._compressed = compressed; + } else if (this._opcode > 0x07 && this._opcode < 0x0b) { + if (!this._fin) { + const error = this.createError( + RangeError, + 'FIN must be set', + true, + 1002, + 'WS_ERR_EXPECTED_FIN' + ); + + cb(error); + return; + } + + if (compressed) { + const error = this.createError( + RangeError, + 'RSV1 must be clear', + true, + 1002, + 'WS_ERR_UNEXPECTED_RSV_1' + ); + + cb(error); + return; + } + + if ( + this._payloadLength > 0x7d || + (this._opcode === 0x08 && this._payloadLength === 1) + ) { + const error = this.createError( + RangeError, + `invalid payload length ${this._payloadLength}`, + true, + 1002, + 'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH' + ); + + cb(error); + return; + } + } else { + const error = this.createError( + RangeError, + `invalid opcode ${this._opcode}`, + true, + 1002, + 'WS_ERR_INVALID_OPCODE' + ); + + cb(error); + return; + } + + if (!this._fin && !this._fragmented) this._fragmented = this._opcode; + this._masked = (buf[1] & 0x80) === 0x80; + + if (this._isServer) { + if (!this._masked) { + const error = this.createError( + RangeError, + 'MASK must be set', + true, + 1002, + 'WS_ERR_EXPECTED_MASK' + ); + + cb(error); + return; + } + } else if (this._masked) { + const error = this.createError( + RangeError, + 'MASK must be clear', + true, + 1002, + 'WS_ERR_UNEXPECTED_MASK' + ); + + cb(error); + return; + } + + if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16; + else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64; + else this.haveLength(cb); + } + + /** + * Gets extended payload length (7+16). + * + * @param {Function} cb Callback + * @private + */ + getPayloadLength16(cb) { + if (this._bufferedBytes < 2) { + this._loop = false; + return; + } + + this._payloadLength = this.consume(2).readUInt16BE(0); + this.haveLength(cb); + } + + /** + * Gets extended payload length (7+64). + * + * @param {Function} cb Callback + * @private + */ + getPayloadLength64(cb) { + if (this._bufferedBytes < 8) { + this._loop = false; + return; + } + + const buf = this.consume(8); + const num = buf.readUInt32BE(0); + + // + // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned + // if payload length is greater than this number. + // + if (num > Math.pow(2, 53 - 32) - 1) { + const error = this.createError( + RangeError, + 'Unsupported WebSocket frame: payload length > 2^53 - 1', + false, + 1009, + 'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH' + ); + + cb(error); + return; + } + + this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4); + this.haveLength(cb); + } + + /** + * Payload length has been read. + * + * @param {Function} cb Callback + * @private + */ + haveLength(cb) { + if (this._payloadLength && this._opcode < 0x08) { + this._totalPayloadLength += this._payloadLength; + if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) { + const error = this.createError( + RangeError, + 'Max payload size exceeded', + false, + 1009, + 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH' + ); + + cb(error); + return; + } + } + + if (this._masked) this._state = GET_MASK; + else this._state = GET_DATA; + } + + /** + * Reads mask bytes. + * + * @private + */ + getMask() { + if (this._bufferedBytes < 4) { + this._loop = false; + return; + } + + this._mask = this.consume(4); + this._state = GET_DATA; + } + + /** + * Reads data bytes. + * + * @param {Function} cb Callback + * @private + */ + getData(cb) { + let data = EMPTY_BUFFER; + + if (this._payloadLength) { + if (this._bufferedBytes < this._payloadLength) { + this._loop = false; + return; + } + + data = this.consume(this._payloadLength); + + if ( + this._masked && + (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0 + ) { + unmask(data, this._mask); + } + } + + if (this._opcode > 0x07) { + this.controlMessage(data, cb); + return; + } + + if (this._compressed) { + this._state = INFLATING; + this.decompress(data, cb); + return; + } + + if (data.length) { + // + // This message is not compressed so its length is the sum of the payload + // length of all fragments. + // + this._messageLength = this._totalPayloadLength; + this._fragments.push(data); + } + + this.dataMessage(cb); + } + + /** + * Decompresses data. + * + * @param {Buffer} data Compressed data + * @param {Function} cb Callback + * @private + */ + decompress(data, cb) { + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + + perMessageDeflate.decompress(data, this._fin, (err, buf) => { + if (err) return cb(err); + + if (buf.length) { + this._messageLength += buf.length; + if (this._messageLength > this._maxPayload && this._maxPayload > 0) { + const error = this.createError( + RangeError, + 'Max payload size exceeded', + false, + 1009, + 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH' + ); + + cb(error); + return; + } + + this._fragments.push(buf); + } + + this.dataMessage(cb); + if (this._state === GET_INFO) this.startLoop(cb); + }); + } + + /** + * Handles a data message. + * + * @param {Function} cb Callback + * @private + */ + dataMessage(cb) { + if (!this._fin) { + this._state = GET_INFO; + return; + } + + const messageLength = this._messageLength; + const fragments = this._fragments; + + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragmented = 0; + this._fragments = []; + + if (this._opcode === 2) { + let data; + + if (this._binaryType === 'nodebuffer') { + data = concat(fragments, messageLength); + } else if (this._binaryType === 'arraybuffer') { + data = toArrayBuffer(concat(fragments, messageLength)); + } else if (this._binaryType === 'blob') { + data = new Blob(fragments); + } else { + data = fragments; + } + + if (this._allowSynchronousEvents) { + this.emit('message', data, true); + this._state = GET_INFO; + } else { + this._state = DEFER_EVENT; + setImmediate(() => { + this.emit('message', data, true); + this._state = GET_INFO; + this.startLoop(cb); + }); + } + } else { + const buf = concat(fragments, messageLength); + + if (!this._skipUTF8Validation && !isValidUTF8(buf)) { + const error = this.createError( + Error, + 'invalid UTF-8 sequence', + true, + 1007, + 'WS_ERR_INVALID_UTF8' + ); + + cb(error); + return; + } + + if (this._state === INFLATING || this._allowSynchronousEvents) { + this.emit('message', buf, false); + this._state = GET_INFO; + } else { + this._state = DEFER_EVENT; + setImmediate(() => { + this.emit('message', buf, false); + this._state = GET_INFO; + this.startLoop(cb); + }); + } + } + } + + /** + * Handles a control message. + * + * @param {Buffer} data Data to handle + * @return {(Error|RangeError|undefined)} A possible error + * @private + */ + controlMessage(data, cb) { + if (this._opcode === 0x08) { + if (data.length === 0) { + this._loop = false; + this.emit('conclude', 1005, EMPTY_BUFFER); + this.end(); + } else { + const code = data.readUInt16BE(0); + + if (!isValidStatusCode(code)) { + const error = this.createError( + RangeError, + `invalid status code ${code}`, + true, + 1002, + 'WS_ERR_INVALID_CLOSE_CODE' + ); + + cb(error); + return; + } + + const buf = new FastBuffer( + data.buffer, + data.byteOffset + 2, + data.length - 2 + ); + + if (!this._skipUTF8Validation && !isValidUTF8(buf)) { + const error = this.createError( + Error, + 'invalid UTF-8 sequence', + true, + 1007, + 'WS_ERR_INVALID_UTF8' + ); + + cb(error); + return; + } + + this._loop = false; + this.emit('conclude', code, buf); + this.end(); + } + + this._state = GET_INFO; + return; + } + + if (this._allowSynchronousEvents) { + this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data); + this._state = GET_INFO; + } else { + this._state = DEFER_EVENT; + setImmediate(() => { + this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data); + this._state = GET_INFO; + this.startLoop(cb); + }); + } + } + + /** + * Builds an error object. + * + * @param {function(new:Error|RangeError)} ErrorCtor The error constructor + * @param {String} message The error message + * @param {Boolean} prefix Specifies whether or not to add a default prefix to + * `message` + * @param {Number} statusCode The status code + * @param {String} errorCode The exposed error code + * @return {(Error|RangeError)} The error + * @private + */ + createError(ErrorCtor, message, prefix, statusCode, errorCode) { + this._loop = false; + this._errored = true; + + const err = new ErrorCtor( + prefix ? `Invalid WebSocket frame: ${message}` : message + ); + + Error.captureStackTrace(err, this.createError); + err.code = errorCode; + err[kStatusCode] = statusCode; + return err; + } +} + +module.exports = Receiver; diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/sender.js b/tools/websockets-debugger-test/node_modules/ws/lib/sender.js new file mode 100644 index 0000000..ee16cea --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/sender.js @@ -0,0 +1,602 @@ +/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex" }] */ + +'use strict'; + +const { Duplex } = require('stream'); +const { randomFillSync } = require('crypto'); + +const PerMessageDeflate = require('./permessage-deflate'); +const { EMPTY_BUFFER, kWebSocket, NOOP } = require('./constants'); +const { isBlob, isValidStatusCode } = require('./validation'); +const { mask: applyMask, toBuffer } = require('./buffer-util'); + +const kByteLength = Symbol('kByteLength'); +const maskBuffer = Buffer.alloc(4); +const RANDOM_POOL_SIZE = 8 * 1024; +let randomPool; +let randomPoolPointer = RANDOM_POOL_SIZE; + +const DEFAULT = 0; +const DEFLATING = 1; +const GET_BLOB_DATA = 2; + +/** + * HyBi Sender implementation. + */ +class Sender { + /** + * Creates a Sender instance. + * + * @param {Duplex} socket The connection socket + * @param {Object} [extensions] An object containing the negotiated extensions + * @param {Function} [generateMask] The function used to generate the masking + * key + */ + constructor(socket, extensions, generateMask) { + this._extensions = extensions || {}; + + if (generateMask) { + this._generateMask = generateMask; + this._maskBuffer = Buffer.alloc(4); + } + + this._socket = socket; + + this._firstFragment = true; + this._compress = false; + + this._bufferedBytes = 0; + this._queue = []; + this._state = DEFAULT; + this.onerror = NOOP; + this[kWebSocket] = undefined; + } + + /** + * Frames a piece of data according to the HyBi WebSocket protocol. + * + * @param {(Buffer|String)} data The data to frame + * @param {Object} options Options object + * @param {Boolean} [options.fin=false] Specifies whether or not to set the + * FIN bit + * @param {Function} [options.generateMask] The function used to generate the + * masking key + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Buffer} [options.maskBuffer] The buffer used to store the masking + * key + * @param {Number} options.opcode The opcode + * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be + * modified + * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the + * RSV1 bit + * @return {(Buffer|String)[]} The framed data + * @public + */ + static frame(data, options) { + let mask; + let merge = false; + let offset = 2; + let skipMasking = false; + + if (options.mask) { + mask = options.maskBuffer || maskBuffer; + + if (options.generateMask) { + options.generateMask(mask); + } else { + if (randomPoolPointer === RANDOM_POOL_SIZE) { + /* istanbul ignore else */ + if (randomPool === undefined) { + // + // This is lazily initialized because server-sent frames must not + // be masked so it may never be used. + // + randomPool = Buffer.alloc(RANDOM_POOL_SIZE); + } + + randomFillSync(randomPool, 0, RANDOM_POOL_SIZE); + randomPoolPointer = 0; + } + + mask[0] = randomPool[randomPoolPointer++]; + mask[1] = randomPool[randomPoolPointer++]; + mask[2] = randomPool[randomPoolPointer++]; + mask[3] = randomPool[randomPoolPointer++]; + } + + skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0; + offset = 6; + } + + let dataLength; + + if (typeof data === 'string') { + if ( + (!options.mask || skipMasking) && + options[kByteLength] !== undefined + ) { + dataLength = options[kByteLength]; + } else { + data = Buffer.from(data); + dataLength = data.length; + } + } else { + dataLength = data.length; + merge = options.mask && options.readOnly && !skipMasking; + } + + let payloadLength = dataLength; + + if (dataLength >= 65536) { + offset += 8; + payloadLength = 127; + } else if (dataLength > 125) { + offset += 2; + payloadLength = 126; + } + + const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset); + + target[0] = options.fin ? options.opcode | 0x80 : options.opcode; + if (options.rsv1) target[0] |= 0x40; + + target[1] = payloadLength; + + if (payloadLength === 126) { + target.writeUInt16BE(dataLength, 2); + } else if (payloadLength === 127) { + target[2] = target[3] = 0; + target.writeUIntBE(dataLength, 4, 6); + } + + if (!options.mask) return [target, data]; + + target[1] |= 0x80; + target[offset - 4] = mask[0]; + target[offset - 3] = mask[1]; + target[offset - 2] = mask[2]; + target[offset - 1] = mask[3]; + + if (skipMasking) return [target, data]; + + if (merge) { + applyMask(data, mask, target, offset, dataLength); + return [target]; + } + + applyMask(data, mask, data, 0, dataLength); + return [target, data]; + } + + /** + * Sends a close message to the other peer. + * + * @param {Number} [code] The status code component of the body + * @param {(String|Buffer)} [data] The message component of the body + * @param {Boolean} [mask=false] Specifies whether or not to mask the message + * @param {Function} [cb] Callback + * @public + */ + close(code, data, mask, cb) { + let buf; + + if (code === undefined) { + buf = EMPTY_BUFFER; + } else if (typeof code !== 'number' || !isValidStatusCode(code)) { + throw new TypeError('First argument must be a valid error code number'); + } else if (data === undefined || !data.length) { + buf = Buffer.allocUnsafe(2); + buf.writeUInt16BE(code, 0); + } else { + const length = Buffer.byteLength(data); + + if (length > 123) { + throw new RangeError('The message must not be greater than 123 bytes'); + } + + buf = Buffer.allocUnsafe(2 + length); + buf.writeUInt16BE(code, 0); + + if (typeof data === 'string') { + buf.write(data, 2); + } else { + buf.set(data, 2); + } + } + + const options = { + [kByteLength]: buf.length, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 0x08, + readOnly: false, + rsv1: false + }; + + if (this._state !== DEFAULT) { + this.enqueue([this.dispatch, buf, false, options, cb]); + } else { + this.sendFrame(Sender.frame(buf, options), cb); + } + } + + /** + * Sends a ping message to the other peer. + * + * @param {*} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback + * @public + */ + ping(data, mask, cb) { + let byteLength; + let readOnly; + + if (typeof data === 'string') { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else if (isBlob(data)) { + byteLength = data.size; + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; + } + + if (byteLength > 125) { + throw new RangeError('The data size must not be greater than 125 bytes'); + } + + const options = { + [kByteLength]: byteLength, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 0x09, + readOnly, + rsv1: false + }; + + if (isBlob(data)) { + if (this._state !== DEFAULT) { + this.enqueue([this.getBlobData, data, false, options, cb]); + } else { + this.getBlobData(data, false, options, cb); + } + } else if (this._state !== DEFAULT) { + this.enqueue([this.dispatch, data, false, options, cb]); + } else { + this.sendFrame(Sender.frame(data, options), cb); + } + } + + /** + * Sends a pong message to the other peer. + * + * @param {*} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback + * @public + */ + pong(data, mask, cb) { + let byteLength; + let readOnly; + + if (typeof data === 'string') { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else if (isBlob(data)) { + byteLength = data.size; + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; + } + + if (byteLength > 125) { + throw new RangeError('The data size must not be greater than 125 bytes'); + } + + const options = { + [kByteLength]: byteLength, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 0x0a, + readOnly, + rsv1: false + }; + + if (isBlob(data)) { + if (this._state !== DEFAULT) { + this.enqueue([this.getBlobData, data, false, options, cb]); + } else { + this.getBlobData(data, false, options, cb); + } + } else if (this._state !== DEFAULT) { + this.enqueue([this.dispatch, data, false, options, cb]); + } else { + this.sendFrame(Sender.frame(data, options), cb); + } + } + + /** + * Sends a data message to the other peer. + * + * @param {*} data The message to send + * @param {Object} options Options object + * @param {Boolean} [options.binary=false] Specifies whether `data` is binary + * or text + * @param {Boolean} [options.compress=false] Specifies whether or not to + * compress `data` + * @param {Boolean} [options.fin=false] Specifies whether the fragment is the + * last one + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Function} [cb] Callback + * @public + */ + send(data, options, cb) { + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + let opcode = options.binary ? 2 : 1; + let rsv1 = options.compress; + + let byteLength; + let readOnly; + + if (typeof data === 'string') { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else if (isBlob(data)) { + byteLength = data.size; + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; + } + + if (this._firstFragment) { + this._firstFragment = false; + if ( + rsv1 && + perMessageDeflate && + perMessageDeflate.params[ + perMessageDeflate._isServer + ? 'server_no_context_takeover' + : 'client_no_context_takeover' + ] + ) { + rsv1 = byteLength >= perMessageDeflate._threshold; + } + this._compress = rsv1; + } else { + rsv1 = false; + opcode = 0; + } + + if (options.fin) this._firstFragment = true; + + const opts = { + [kByteLength]: byteLength, + fin: options.fin, + generateMask: this._generateMask, + mask: options.mask, + maskBuffer: this._maskBuffer, + opcode, + readOnly, + rsv1 + }; + + if (isBlob(data)) { + if (this._state !== DEFAULT) { + this.enqueue([this.getBlobData, data, this._compress, opts, cb]); + } else { + this.getBlobData(data, this._compress, opts, cb); + } + } else if (this._state !== DEFAULT) { + this.enqueue([this.dispatch, data, this._compress, opts, cb]); + } else { + this.dispatch(data, this._compress, opts, cb); + } + } + + /** + * Gets the contents of a blob as binary data. + * + * @param {Blob} blob The blob + * @param {Boolean} [compress=false] Specifies whether or not to compress + * the data + * @param {Object} options Options object + * @param {Boolean} [options.fin=false] Specifies whether or not to set the + * FIN bit + * @param {Function} [options.generateMask] The function used to generate the + * masking key + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Buffer} [options.maskBuffer] The buffer used to store the masking + * key + * @param {Number} options.opcode The opcode + * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be + * modified + * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the + * RSV1 bit + * @param {Function} [cb] Callback + * @private + */ + getBlobData(blob, compress, options, cb) { + this._bufferedBytes += options[kByteLength]; + this._state = GET_BLOB_DATA; + + blob + .arrayBuffer() + .then((arrayBuffer) => { + if (this._socket.destroyed) { + const err = new Error( + 'The socket was closed while the blob was being read' + ); + + // + // `callCallbacks` is called in the next tick to ensure that errors + // that might be thrown in the callbacks behave like errors thrown + // outside the promise chain. + // + process.nextTick(callCallbacks, this, err, cb); + return; + } + + this._bufferedBytes -= options[kByteLength]; + const data = toBuffer(arrayBuffer); + + if (!compress) { + this._state = DEFAULT; + this.sendFrame(Sender.frame(data, options), cb); + this.dequeue(); + } else { + this.dispatch(data, compress, options, cb); + } + }) + .catch((err) => { + // + // `onError` is called in the next tick for the same reason that + // `callCallbacks` above is. + // + process.nextTick(onError, this, err, cb); + }); + } + + /** + * Dispatches a message. + * + * @param {(Buffer|String)} data The message to send + * @param {Boolean} [compress=false] Specifies whether or not to compress + * `data` + * @param {Object} options Options object + * @param {Boolean} [options.fin=false] Specifies whether or not to set the + * FIN bit + * @param {Function} [options.generateMask] The function used to generate the + * masking key + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Buffer} [options.maskBuffer] The buffer used to store the masking + * key + * @param {Number} options.opcode The opcode + * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be + * modified + * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the + * RSV1 bit + * @param {Function} [cb] Callback + * @private + */ + dispatch(data, compress, options, cb) { + if (!compress) { + this.sendFrame(Sender.frame(data, options), cb); + return; + } + + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + + this._bufferedBytes += options[kByteLength]; + this._state = DEFLATING; + perMessageDeflate.compress(data, options.fin, (_, buf) => { + if (this._socket.destroyed) { + const err = new Error( + 'The socket was closed while data was being compressed' + ); + + callCallbacks(this, err, cb); + return; + } + + this._bufferedBytes -= options[kByteLength]; + this._state = DEFAULT; + options.readOnly = false; + this.sendFrame(Sender.frame(buf, options), cb); + this.dequeue(); + }); + } + + /** + * Executes queued send operations. + * + * @private + */ + dequeue() { + while (this._state === DEFAULT && this._queue.length) { + const params = this._queue.shift(); + + this._bufferedBytes -= params[3][kByteLength]; + Reflect.apply(params[0], this, params.slice(1)); + } + } + + /** + * Enqueues a send operation. + * + * @param {Array} params Send operation parameters. + * @private + */ + enqueue(params) { + this._bufferedBytes += params[3][kByteLength]; + this._queue.push(params); + } + + /** + * Sends a frame. + * + * @param {Buffer[]} list The frame to send + * @param {Function} [cb] Callback + * @private + */ + sendFrame(list, cb) { + if (list.length === 2) { + this._socket.cork(); + this._socket.write(list[0]); + this._socket.write(list[1], cb); + this._socket.uncork(); + } else { + this._socket.write(list[0], cb); + } + } +} + +module.exports = Sender; + +/** + * Calls queued callbacks with an error. + * + * @param {Sender} sender The `Sender` instance + * @param {Error} err The error to call the callbacks with + * @param {Function} [cb] The first callback + * @private + */ +function callCallbacks(sender, err, cb) { + if (typeof cb === 'function') cb(err); + + for (let i = 0; i < sender._queue.length; i++) { + const params = sender._queue[i]; + const callback = params[params.length - 1]; + + if (typeof callback === 'function') callback(err); + } +} + +/** + * Handles a `Sender` error. + * + * @param {Sender} sender The `Sender` instance + * @param {Error} err The error + * @param {Function} [cb] The first pending callback + * @private + */ +function onError(sender, err, cb) { + callCallbacks(sender, err, cb); + sender.onerror(err); +} diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/stream.js b/tools/websockets-debugger-test/node_modules/ws/lib/stream.js new file mode 100644 index 0000000..230734b --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/stream.js @@ -0,0 +1,159 @@ +'use strict'; + +const { Duplex } = require('stream'); + +/** + * Emits the `'close'` event on a stream. + * + * @param {Duplex} stream The stream. + * @private + */ +function emitClose(stream) { + stream.emit('close'); +} + +/** + * The listener of the `'end'` event. + * + * @private + */ +function duplexOnEnd() { + if (!this.destroyed && this._writableState.finished) { + this.destroy(); + } +} + +/** + * The listener of the `'error'` event. + * + * @param {Error} err The error + * @private + */ +function duplexOnError(err) { + this.removeListener('error', duplexOnError); + this.destroy(); + if (this.listenerCount('error') === 0) { + // Do not suppress the throwing behavior. + this.emit('error', err); + } +} + +/** + * Wraps a `WebSocket` in a duplex stream. + * + * @param {WebSocket} ws The `WebSocket` to wrap + * @param {Object} [options] The options for the `Duplex` constructor + * @return {Duplex} The duplex stream + * @public + */ +function createWebSocketStream(ws, options) { + let terminateOnDestroy = true; + + const duplex = new Duplex({ + ...options, + autoDestroy: false, + emitClose: false, + objectMode: false, + writableObjectMode: false + }); + + ws.on('message', function message(msg, isBinary) { + const data = + !isBinary && duplex._readableState.objectMode ? msg.toString() : msg; + + if (!duplex.push(data)) ws.pause(); + }); + + ws.once('error', function error(err) { + if (duplex.destroyed) return; + + // Prevent `ws.terminate()` from being called by `duplex._destroy()`. + // + // - If the `'error'` event is emitted before the `'open'` event, then + // `ws.terminate()` is a noop as no socket is assigned. + // - Otherwise, the error is re-emitted by the listener of the `'error'` + // event of the `Receiver` object. The listener already closes the + // connection by calling `ws.close()`. This allows a close frame to be + // sent to the other peer. If `ws.terminate()` is called right after this, + // then the close frame might not be sent. + terminateOnDestroy = false; + duplex.destroy(err); + }); + + ws.once('close', function close() { + if (duplex.destroyed) return; + + duplex.push(null); + }); + + duplex._destroy = function (err, callback) { + if (ws.readyState === ws.CLOSED) { + callback(err); + process.nextTick(emitClose, duplex); + return; + } + + let called = false; + + ws.once('error', function error(err) { + called = true; + callback(err); + }); + + ws.once('close', function close() { + if (!called) callback(err); + process.nextTick(emitClose, duplex); + }); + + if (terminateOnDestroy) ws.terminate(); + }; + + duplex._final = function (callback) { + if (ws.readyState === ws.CONNECTING) { + ws.once('open', function open() { + duplex._final(callback); + }); + return; + } + + // If the value of the `_socket` property is `null` it means that `ws` is a + // client websocket and the handshake failed. In fact, when this happens, a + // socket is never assigned to the websocket. Wait for the `'error'` event + // that will be emitted by the websocket. + if (ws._socket === null) return; + + if (ws._socket._writableState.finished) { + callback(); + if (duplex._readableState.endEmitted) duplex.destroy(); + } else { + ws._socket.once('finish', function finish() { + // `duplex` is not destroyed here because the `'end'` event will be + // emitted on `duplex` after this `'finish'` event. The EOF signaling + // `null` chunk is, in fact, pushed when the websocket emits `'close'`. + callback(); + }); + ws.close(); + } + }; + + duplex._read = function () { + if (ws.isPaused) ws.resume(); + }; + + duplex._write = function (chunk, encoding, callback) { + if (ws.readyState === ws.CONNECTING) { + ws.once('open', function open() { + duplex._write(chunk, encoding, callback); + }); + return; + } + + ws.send(chunk, callback); + }; + + duplex.on('end', duplexOnEnd); + duplex.on('error', duplexOnError); + return duplex; +} + +module.exports = createWebSocketStream; diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/subprotocol.js b/tools/websockets-debugger-test/node_modules/ws/lib/subprotocol.js new file mode 100644 index 0000000..d4381e8 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/subprotocol.js @@ -0,0 +1,62 @@ +'use strict'; + +const { tokenChars } = require('./validation'); + +/** + * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names. + * + * @param {String} header The field value of the header + * @return {Set} The subprotocol names + * @public + */ +function parse(header) { + const protocols = new Set(); + let start = -1; + let end = -1; + let i = 0; + + for (i; i < header.length; i++) { + const code = header.charCodeAt(i); + + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if ( + i !== 0 && + (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */ + ) { + if (end === -1 && start !== -1) end = i; + } else if (code === 0x2c /* ',' */) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + + const protocol = header.slice(start, end); + + if (protocols.has(protocol)) { + throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`); + } + + protocols.add(protocol); + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } + + if (start === -1 || end !== -1) { + throw new SyntaxError('Unexpected end of input'); + } + + const protocol = header.slice(start, i); + + if (protocols.has(protocol)) { + throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`); + } + + protocols.add(protocol); + return protocols; +} + +module.exports = { parse }; diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/validation.js b/tools/websockets-debugger-test/node_modules/ws/lib/validation.js new file mode 100644 index 0000000..4a2e68d --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/validation.js @@ -0,0 +1,152 @@ +'use strict'; + +const { isUtf8 } = require('buffer'); + +const { hasBlob } = require('./constants'); + +// +// Allowed token characters: +// +// '!', '#', '$', '%', '&', ''', '*', '+', '-', +// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~' +// +// tokenChars[32] === 0 // ' ' +// tokenChars[33] === 1 // '!' +// tokenChars[34] === 0 // '"' +// ... +// +// prettier-ignore +const tokenChars = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31 + 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127 +]; + +/** + * Checks if a status code is allowed in a close frame. + * + * @param {Number} code The status code + * @return {Boolean} `true` if the status code is valid, else `false` + * @public + */ +function isValidStatusCode(code) { + return ( + (code >= 1000 && + code <= 1014 && + code !== 1004 && + code !== 1005 && + code !== 1006) || + (code >= 3000 && code <= 4999) + ); +} + +/** + * Checks if a given buffer contains only correct UTF-8. + * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by + * Markus Kuhn. + * + * @param {Buffer} buf The buffer to check + * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false` + * @public + */ +function _isValidUTF8(buf) { + const len = buf.length; + let i = 0; + + while (i < len) { + if ((buf[i] & 0x80) === 0) { + // 0xxxxxxx + i++; + } else if ((buf[i] & 0xe0) === 0xc0) { + // 110xxxxx 10xxxxxx + if ( + i + 1 === len || + (buf[i + 1] & 0xc0) !== 0x80 || + (buf[i] & 0xfe) === 0xc0 // Overlong + ) { + return false; + } + + i += 2; + } else if ((buf[i] & 0xf0) === 0xe0) { + // 1110xxxx 10xxxxxx 10xxxxxx + if ( + i + 2 >= len || + (buf[i + 1] & 0xc0) !== 0x80 || + (buf[i + 2] & 0xc0) !== 0x80 || + (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong + (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF) + ) { + return false; + } + + i += 3; + } else if ((buf[i] & 0xf8) === 0xf0) { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + if ( + i + 3 >= len || + (buf[i + 1] & 0xc0) !== 0x80 || + (buf[i + 2] & 0xc0) !== 0x80 || + (buf[i + 3] & 0xc0) !== 0x80 || + (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong + (buf[i] === 0xf4 && buf[i + 1] > 0x8f) || + buf[i] > 0xf4 // > U+10FFFF + ) { + return false; + } + + i += 4; + } else { + return false; + } + } + + return true; +} + +/** + * Determines whether a value is a `Blob`. + * + * @param {*} value The value to be tested + * @return {Boolean} `true` if `value` is a `Blob`, else `false` + * @private + */ +function isBlob(value) { + return ( + hasBlob && + typeof value === 'object' && + typeof value.arrayBuffer === 'function' && + typeof value.type === 'string' && + typeof value.stream === 'function' && + (value[Symbol.toStringTag] === 'Blob' || + value[Symbol.toStringTag] === 'File') + ); +} + +module.exports = { + isBlob, + isValidStatusCode, + isValidUTF8: _isValidUTF8, + tokenChars +}; + +if (isUtf8) { + module.exports.isValidUTF8 = function (buf) { + return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf); + }; +} /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) { + try { + const isValidUTF8 = require('utf-8-validate'); + + module.exports.isValidUTF8 = function (buf) { + return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf); + }; + } catch (e) { + // Continue regardless of the error. + } +} diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/websocket-server.js b/tools/websockets-debugger-test/node_modules/ws/lib/websocket-server.js new file mode 100644 index 0000000..67b52ff --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/websocket-server.js @@ -0,0 +1,540 @@ +/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex$", "caughtErrors": "none" }] */ + +'use strict'; + +const EventEmitter = require('events'); +const http = require('http'); +const { Duplex } = require('stream'); +const { createHash } = require('crypto'); + +const extension = require('./extension'); +const PerMessageDeflate = require('./permessage-deflate'); +const subprotocol = require('./subprotocol'); +const WebSocket = require('./websocket'); +const { GUID, kWebSocket } = require('./constants'); + +const keyRegex = /^[+/0-9A-Za-z]{22}==$/; + +const RUNNING = 0; +const CLOSING = 1; +const CLOSED = 2; + +/** + * Class representing a WebSocket server. + * + * @extends EventEmitter + */ +class WebSocketServer extends EventEmitter { + /** + * Create a `WebSocketServer` instance. + * + * @param {Object} options Configuration options + * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether + * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted + * multiple times in the same tick + * @param {Boolean} [options.autoPong=true] Specifies whether or not to + * automatically send a pong in response to a ping + * @param {Number} [options.backlog=511] The maximum length of the queue of + * pending connections + * @param {Boolean} [options.clientTracking=true] Specifies whether or not to + * track clients + * @param {Function} [options.handleProtocols] A hook to handle protocols + * @param {String} [options.host] The hostname where to bind the server + * @param {Number} [options.maxPayload=104857600] The maximum allowed message + * size + * @param {Boolean} [options.noServer=false] Enable no server mode + * @param {String} [options.path] Accept only connections matching this path + * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable + * permessage-deflate + * @param {Number} [options.port] The port where to bind the server + * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S + * server to use + * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or + * not to skip UTF-8 validation for text and close messages + * @param {Function} [options.verifyClient] A hook to reject connections + * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket` + * class to use. It must be the `WebSocket` class or class that extends it + * @param {Function} [callback] A listener for the `listening` event + */ + constructor(options, callback) { + super(); + + options = { + allowSynchronousEvents: true, + autoPong: true, + maxPayload: 100 * 1024 * 1024, + skipUTF8Validation: false, + perMessageDeflate: false, + handleProtocols: null, + clientTracking: true, + verifyClient: null, + noServer: false, + backlog: null, // use default (511 as implemented in net.js) + server: null, + host: null, + path: null, + port: null, + WebSocket, + ...options + }; + + if ( + (options.port == null && !options.server && !options.noServer) || + (options.port != null && (options.server || options.noServer)) || + (options.server && options.noServer) + ) { + throw new TypeError( + 'One and only one of the "port", "server", or "noServer" options ' + + 'must be specified' + ); + } + + if (options.port != null) { + this._server = http.createServer((req, res) => { + const body = http.STATUS_CODES[426]; + + res.writeHead(426, { + 'Content-Length': body.length, + 'Content-Type': 'text/plain' + }); + res.end(body); + }); + this._server.listen( + options.port, + options.host, + options.backlog, + callback + ); + } else if (options.server) { + this._server = options.server; + } + + if (this._server) { + const emitConnection = this.emit.bind(this, 'connection'); + + this._removeListeners = addListeners(this._server, { + listening: this.emit.bind(this, 'listening'), + error: this.emit.bind(this, 'error'), + upgrade: (req, socket, head) => { + this.handleUpgrade(req, socket, head, emitConnection); + } + }); + } + + if (options.perMessageDeflate === true) options.perMessageDeflate = {}; + if (options.clientTracking) { + this.clients = new Set(); + this._shouldEmitClose = false; + } + + this.options = options; + this._state = RUNNING; + } + + /** + * Returns the bound address, the address family name, and port of the server + * as reported by the operating system if listening on an IP socket. + * If the server is listening on a pipe or UNIX domain socket, the name is + * returned as a string. + * + * @return {(Object|String|null)} The address of the server + * @public + */ + address() { + if (this.options.noServer) { + throw new Error('The server is operating in "noServer" mode'); + } + + if (!this._server) return null; + return this._server.address(); + } + + /** + * Stop the server from accepting new connections and emit the `'close'` event + * when all existing connections are closed. + * + * @param {Function} [cb] A one-time listener for the `'close'` event + * @public + */ + close(cb) { + if (this._state === CLOSED) { + if (cb) { + this.once('close', () => { + cb(new Error('The server is not running')); + }); + } + + process.nextTick(emitClose, this); + return; + } + + if (cb) this.once('close', cb); + + if (this._state === CLOSING) return; + this._state = CLOSING; + + if (this.options.noServer || this.options.server) { + if (this._server) { + this._removeListeners(); + this._removeListeners = this._server = null; + } + + if (this.clients) { + if (!this.clients.size) { + process.nextTick(emitClose, this); + } else { + this._shouldEmitClose = true; + } + } else { + process.nextTick(emitClose, this); + } + } else { + const server = this._server; + + this._removeListeners(); + this._removeListeners = this._server = null; + + // + // The HTTP/S server was created internally. Close it, and rely on its + // `'close'` event. + // + server.close(() => { + emitClose(this); + }); + } + } + + /** + * See if a given request should be handled by this server instance. + * + * @param {http.IncomingMessage} req Request object to inspect + * @return {Boolean} `true` if the request is valid, else `false` + * @public + */ + shouldHandle(req) { + if (this.options.path) { + const index = req.url.indexOf('?'); + const pathname = index !== -1 ? req.url.slice(0, index) : req.url; + + if (pathname !== this.options.path) return false; + } + + return true; + } + + /** + * Handle a HTTP Upgrade request. + * + * @param {http.IncomingMessage} req The request object + * @param {Duplex} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Function} cb Callback + * @public + */ + handleUpgrade(req, socket, head, cb) { + socket.on('error', socketOnError); + + const key = req.headers['sec-websocket-key']; + const upgrade = req.headers.upgrade; + const version = +req.headers['sec-websocket-version']; + + if (req.method !== 'GET') { + const message = 'Invalid HTTP method'; + abortHandshakeOrEmitwsClientError(this, req, socket, 405, message); + return; + } + + if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') { + const message = 'Invalid Upgrade header'; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + + if (key === undefined || !keyRegex.test(key)) { + const message = 'Missing or invalid Sec-WebSocket-Key header'; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + + if (version !== 8 && version !== 13) { + const message = 'Missing or invalid Sec-WebSocket-Version header'; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + + if (!this.shouldHandle(req)) { + abortHandshake(socket, 400); + return; + } + + const secWebSocketProtocol = req.headers['sec-websocket-protocol']; + let protocols = new Set(); + + if (secWebSocketProtocol !== undefined) { + try { + protocols = subprotocol.parse(secWebSocketProtocol); + } catch (err) { + const message = 'Invalid Sec-WebSocket-Protocol header'; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + } + + const secWebSocketExtensions = req.headers['sec-websocket-extensions']; + const extensions = {}; + + if ( + this.options.perMessageDeflate && + secWebSocketExtensions !== undefined + ) { + const perMessageDeflate = new PerMessageDeflate( + this.options.perMessageDeflate, + true, + this.options.maxPayload + ); + + try { + const offers = extension.parse(secWebSocketExtensions); + + if (offers[PerMessageDeflate.extensionName]) { + perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]); + extensions[PerMessageDeflate.extensionName] = perMessageDeflate; + } + } catch (err) { + const message = + 'Invalid or unacceptable Sec-WebSocket-Extensions header'; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + } + + // + // Optionally call external client verification handler. + // + if (this.options.verifyClient) { + const info = { + origin: + req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`], + secure: !!(req.socket.authorized || req.socket.encrypted), + req + }; + + if (this.options.verifyClient.length === 2) { + this.options.verifyClient(info, (verified, code, message, headers) => { + if (!verified) { + return abortHandshake(socket, code || 401, message, headers); + } + + this.completeUpgrade( + extensions, + key, + protocols, + req, + socket, + head, + cb + ); + }); + return; + } + + if (!this.options.verifyClient(info)) return abortHandshake(socket, 401); + } + + this.completeUpgrade(extensions, key, protocols, req, socket, head, cb); + } + + /** + * Upgrade the connection to WebSocket. + * + * @param {Object} extensions The accepted extensions + * @param {String} key The value of the `Sec-WebSocket-Key` header + * @param {Set} protocols The subprotocols + * @param {http.IncomingMessage} req The request object + * @param {Duplex} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Function} cb Callback + * @throws {Error} If called more than once with the same socket + * @private + */ + completeUpgrade(extensions, key, protocols, req, socket, head, cb) { + // + // Destroy the socket if the client has already sent a FIN packet. + // + if (!socket.readable || !socket.writable) return socket.destroy(); + + if (socket[kWebSocket]) { + throw new Error( + 'server.handleUpgrade() was called more than once with the same ' + + 'socket, possibly due to a misconfiguration' + ); + } + + if (this._state > RUNNING) return abortHandshake(socket, 503); + + const digest = createHash('sha1') + .update(key + GUID) + .digest('base64'); + + const headers = [ + 'HTTP/1.1 101 Switching Protocols', + 'Upgrade: websocket', + 'Connection: Upgrade', + `Sec-WebSocket-Accept: ${digest}` + ]; + + const ws = new this.options.WebSocket(null, undefined, this.options); + + if (protocols.size) { + // + // Optionally call external protocol selection handler. + // + const protocol = this.options.handleProtocols + ? this.options.handleProtocols(protocols, req) + : protocols.values().next().value; + + if (protocol) { + headers.push(`Sec-WebSocket-Protocol: ${protocol}`); + ws._protocol = protocol; + } + } + + if (extensions[PerMessageDeflate.extensionName]) { + const params = extensions[PerMessageDeflate.extensionName].params; + const value = extension.format({ + [PerMessageDeflate.extensionName]: [params] + }); + headers.push(`Sec-WebSocket-Extensions: ${value}`); + ws._extensions = extensions; + } + + // + // Allow external modification/inspection of handshake headers. + // + this.emit('headers', headers, req); + + socket.write(headers.concat('\r\n').join('\r\n')); + socket.removeListener('error', socketOnError); + + ws.setSocket(socket, head, { + allowSynchronousEvents: this.options.allowSynchronousEvents, + maxPayload: this.options.maxPayload, + skipUTF8Validation: this.options.skipUTF8Validation + }); + + if (this.clients) { + this.clients.add(ws); + ws.on('close', () => { + this.clients.delete(ws); + + if (this._shouldEmitClose && !this.clients.size) { + process.nextTick(emitClose, this); + } + }); + } + + cb(ws, req); + } +} + +module.exports = WebSocketServer; + +/** + * Add event listeners on an `EventEmitter` using a map of + * pairs. + * + * @param {EventEmitter} server The event emitter + * @param {Object.} map The listeners to add + * @return {Function} A function that will remove the added listeners when + * called + * @private + */ +function addListeners(server, map) { + for (const event of Object.keys(map)) server.on(event, map[event]); + + return function removeListeners() { + for (const event of Object.keys(map)) { + server.removeListener(event, map[event]); + } + }; +} + +/** + * Emit a `'close'` event on an `EventEmitter`. + * + * @param {EventEmitter} server The event emitter + * @private + */ +function emitClose(server) { + server._state = CLOSED; + server.emit('close'); +} + +/** + * Handle socket errors. + * + * @private + */ +function socketOnError() { + this.destroy(); +} + +/** + * Close the connection when preconditions are not fulfilled. + * + * @param {Duplex} socket The socket of the upgrade request + * @param {Number} code The HTTP response status code + * @param {String} [message] The HTTP response body + * @param {Object} [headers] Additional HTTP response headers + * @private + */ +function abortHandshake(socket, code, message, headers) { + // + // The socket is writable unless the user destroyed or ended it before calling + // `server.handleUpgrade()` or in the `verifyClient` function, which is a user + // error. Handling this does not make much sense as the worst that can happen + // is that some of the data written by the user might be discarded due to the + // call to `socket.end()` below, which triggers an `'error'` event that in + // turn causes the socket to be destroyed. + // + message = message || http.STATUS_CODES[code]; + headers = { + Connection: 'close', + 'Content-Type': 'text/html', + 'Content-Length': Buffer.byteLength(message), + ...headers + }; + + socket.once('finish', socket.destroy); + + socket.end( + `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` + + Object.keys(headers) + .map((h) => `${h}: ${headers[h]}`) + .join('\r\n') + + '\r\n\r\n' + + message + ); +} + +/** + * Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least + * one listener for it, otherwise call `abortHandshake()`. + * + * @param {WebSocketServer} server The WebSocket server + * @param {http.IncomingMessage} req The request object + * @param {Duplex} socket The socket of the upgrade request + * @param {Number} code The HTTP response status code + * @param {String} message The HTTP response body + * @private + */ +function abortHandshakeOrEmitwsClientError(server, req, socket, code, message) { + if (server.listenerCount('wsClientError')) { + const err = new Error(message); + Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError); + + server.emit('wsClientError', err, socket, req); + } else { + abortHandshake(socket, code, message); + } +} diff --git a/tools/websockets-debugger-test/node_modules/ws/lib/websocket.js b/tools/websockets-debugger-test/node_modules/ws/lib/websocket.js new file mode 100644 index 0000000..7fb4029 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/lib/websocket.js @@ -0,0 +1,1388 @@ +/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$", "caughtErrors": "none" }] */ + +'use strict'; + +const EventEmitter = require('events'); +const https = require('https'); +const http = require('http'); +const net = require('net'); +const tls = require('tls'); +const { randomBytes, createHash } = require('crypto'); +const { Duplex, Readable } = require('stream'); +const { URL } = require('url'); + +const PerMessageDeflate = require('./permessage-deflate'); +const Receiver = require('./receiver'); +const Sender = require('./sender'); +const { isBlob } = require('./validation'); + +const { + BINARY_TYPES, + EMPTY_BUFFER, + GUID, + kForOnEventAttribute, + kListener, + kStatusCode, + kWebSocket, + NOOP +} = require('./constants'); +const { + EventTarget: { addEventListener, removeEventListener } +} = require('./event-target'); +const { format, parse } = require('./extension'); +const { toBuffer } = require('./buffer-util'); + +const closeTimeout = 30 * 1000; +const kAborted = Symbol('kAborted'); +const protocolVersions = [8, 13]; +const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']; +const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/; + +/** + * Class representing a WebSocket. + * + * @extends EventEmitter + */ +class WebSocket extends EventEmitter { + /** + * Create a new `WebSocket`. + * + * @param {(String|URL)} address The URL to which to connect + * @param {(String|String[])} [protocols] The subprotocols + * @param {Object} [options] Connection options + */ + constructor(address, protocols, options) { + super(); + + this._binaryType = BINARY_TYPES[0]; + this._closeCode = 1006; + this._closeFrameReceived = false; + this._closeFrameSent = false; + this._closeMessage = EMPTY_BUFFER; + this._closeTimer = null; + this._errorEmitted = false; + this._extensions = {}; + this._paused = false; + this._protocol = ''; + this._readyState = WebSocket.CONNECTING; + this._receiver = null; + this._sender = null; + this._socket = null; + + if (address !== null) { + this._bufferedAmount = 0; + this._isServer = false; + this._redirects = 0; + + if (protocols === undefined) { + protocols = []; + } else if (!Array.isArray(protocols)) { + if (typeof protocols === 'object' && protocols !== null) { + options = protocols; + protocols = []; + } else { + protocols = [protocols]; + } + } + + initAsClient(this, address, protocols, options); + } else { + this._autoPong = options.autoPong; + this._isServer = true; + } + } + + /** + * For historical reasons, the custom "nodebuffer" type is used by the default + * instead of "blob". + * + * @type {String} + */ + get binaryType() { + return this._binaryType; + } + + set binaryType(type) { + if (!BINARY_TYPES.includes(type)) return; + + this._binaryType = type; + + // + // Allow to change `binaryType` on the fly. + // + if (this._receiver) this._receiver._binaryType = type; + } + + /** + * @type {Number} + */ + get bufferedAmount() { + if (!this._socket) return this._bufferedAmount; + + return this._socket._writableState.length + this._sender._bufferedBytes; + } + + /** + * @type {String} + */ + get extensions() { + return Object.keys(this._extensions).join(); + } + + /** + * @type {Boolean} + */ + get isPaused() { + return this._paused; + } + + /** + * @type {Function} + */ + /* istanbul ignore next */ + get onclose() { + return null; + } + + /** + * @type {Function} + */ + /* istanbul ignore next */ + get onerror() { + return null; + } + + /** + * @type {Function} + */ + /* istanbul ignore next */ + get onopen() { + return null; + } + + /** + * @type {Function} + */ + /* istanbul ignore next */ + get onmessage() { + return null; + } + + /** + * @type {String} + */ + get protocol() { + return this._protocol; + } + + /** + * @type {Number} + */ + get readyState() { + return this._readyState; + } + + /** + * @type {String} + */ + get url() { + return this._url; + } + + /** + * Set up the socket and the internal resources. + * + * @param {Duplex} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Object} options Options object + * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether + * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted + * multiple times in the same tick + * @param {Function} [options.generateMask] The function used to generate the + * masking key + * @param {Number} [options.maxPayload=0] The maximum allowed message size + * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or + * not to skip UTF-8 validation for text and close messages + * @private + */ + setSocket(socket, head, options) { + const receiver = new Receiver({ + allowSynchronousEvents: options.allowSynchronousEvents, + binaryType: this.binaryType, + extensions: this._extensions, + isServer: this._isServer, + maxPayload: options.maxPayload, + skipUTF8Validation: options.skipUTF8Validation + }); + + const sender = new Sender(socket, this._extensions, options.generateMask); + + this._receiver = receiver; + this._sender = sender; + this._socket = socket; + + receiver[kWebSocket] = this; + sender[kWebSocket] = this; + socket[kWebSocket] = this; + + receiver.on('conclude', receiverOnConclude); + receiver.on('drain', receiverOnDrain); + receiver.on('error', receiverOnError); + receiver.on('message', receiverOnMessage); + receiver.on('ping', receiverOnPing); + receiver.on('pong', receiverOnPong); + + sender.onerror = senderOnError; + + // + // These methods may not be available if `socket` is just a `Duplex`. + // + if (socket.setTimeout) socket.setTimeout(0); + if (socket.setNoDelay) socket.setNoDelay(); + + if (head.length > 0) socket.unshift(head); + + socket.on('close', socketOnClose); + socket.on('data', socketOnData); + socket.on('end', socketOnEnd); + socket.on('error', socketOnError); + + this._readyState = WebSocket.OPEN; + this.emit('open'); + } + + /** + * Emit the `'close'` event. + * + * @private + */ + emitClose() { + if (!this._socket) { + this._readyState = WebSocket.CLOSED; + this.emit('close', this._closeCode, this._closeMessage); + return; + } + + if (this._extensions[PerMessageDeflate.extensionName]) { + this._extensions[PerMessageDeflate.extensionName].cleanup(); + } + + this._receiver.removeAllListeners(); + this._readyState = WebSocket.CLOSED; + this.emit('close', this._closeCode, this._closeMessage); + } + + /** + * Start a closing handshake. + * + * +----------+ +-----------+ +----------+ + * - - -|ws.close()|-->|close frame|-->|ws.close()|- - - + * | +----------+ +-----------+ +----------+ | + * +----------+ +-----------+ | + * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING + * +----------+ +-----------+ | + * | | | +---+ | + * +------------------------+-->|fin| - - - - + * | +---+ | +---+ + * - - - - -|fin|<---------------------+ + * +---+ + * + * @param {Number} [code] Status code explaining why the connection is closing + * @param {(String|Buffer)} [data] The reason why the connection is + * closing + * @public + */ + close(code, data) { + if (this.readyState === WebSocket.CLOSED) return; + if (this.readyState === WebSocket.CONNECTING) { + const msg = 'WebSocket was closed before the connection was established'; + abortHandshake(this, this._req, msg); + return; + } + + if (this.readyState === WebSocket.CLOSING) { + if ( + this._closeFrameSent && + (this._closeFrameReceived || this._receiver._writableState.errorEmitted) + ) { + this._socket.end(); + } + + return; + } + + this._readyState = WebSocket.CLOSING; + this._sender.close(code, data, !this._isServer, (err) => { + // + // This error is handled by the `'error'` listener on the socket. We only + // want to know if the close frame has been sent here. + // + if (err) return; + + this._closeFrameSent = true; + + if ( + this._closeFrameReceived || + this._receiver._writableState.errorEmitted + ) { + this._socket.end(); + } + }); + + setCloseTimer(this); + } + + /** + * Pause the socket. + * + * @public + */ + pause() { + if ( + this.readyState === WebSocket.CONNECTING || + this.readyState === WebSocket.CLOSED + ) { + return; + } + + this._paused = true; + this._socket.pause(); + } + + /** + * Send a ping. + * + * @param {*} [data] The data to send + * @param {Boolean} [mask] Indicates whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when the ping is sent + * @public + */ + ping(data, mask, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); + } + + if (typeof data === 'function') { + cb = data; + data = mask = undefined; + } else if (typeof mask === 'function') { + cb = mask; + mask = undefined; + } + + if (typeof data === 'number') data = data.toString(); + + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + + if (mask === undefined) mask = !this._isServer; + this._sender.ping(data || EMPTY_BUFFER, mask, cb); + } + + /** + * Send a pong. + * + * @param {*} [data] The data to send + * @param {Boolean} [mask] Indicates whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when the pong is sent + * @public + */ + pong(data, mask, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); + } + + if (typeof data === 'function') { + cb = data; + data = mask = undefined; + } else if (typeof mask === 'function') { + cb = mask; + mask = undefined; + } + + if (typeof data === 'number') data = data.toString(); + + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + + if (mask === undefined) mask = !this._isServer; + this._sender.pong(data || EMPTY_BUFFER, mask, cb); + } + + /** + * Resume the socket. + * + * @public + */ + resume() { + if ( + this.readyState === WebSocket.CONNECTING || + this.readyState === WebSocket.CLOSED + ) { + return; + } + + this._paused = false; + if (!this._receiver._writableState.needDrain) this._socket.resume(); + } + + /** + * Send a data message. + * + * @param {*} data The message to send + * @param {Object} [options] Options object + * @param {Boolean} [options.binary] Specifies whether `data` is binary or + * text + * @param {Boolean} [options.compress] Specifies whether or not to compress + * `data` + * @param {Boolean} [options.fin=true] Specifies whether the fragment is the + * last one + * @param {Boolean} [options.mask] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when data is written out + * @public + */ + send(data, options, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); + } + + if (typeof options === 'function') { + cb = options; + options = {}; + } + + if (typeof data === 'number') data = data.toString(); + + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + + const opts = { + binary: typeof data !== 'string', + mask: !this._isServer, + compress: true, + fin: true, + ...options + }; + + if (!this._extensions[PerMessageDeflate.extensionName]) { + opts.compress = false; + } + + this._sender.send(data || EMPTY_BUFFER, opts, cb); + } + + /** + * Forcibly close the connection. + * + * @public + */ + terminate() { + if (this.readyState === WebSocket.CLOSED) return; + if (this.readyState === WebSocket.CONNECTING) { + const msg = 'WebSocket was closed before the connection was established'; + abortHandshake(this, this._req, msg); + return; + } + + if (this._socket) { + this._readyState = WebSocket.CLOSING; + this._socket.destroy(); + } + } +} + +/** + * @constant {Number} CONNECTING + * @memberof WebSocket + */ +Object.defineProperty(WebSocket, 'CONNECTING', { + enumerable: true, + value: readyStates.indexOf('CONNECTING') +}); + +/** + * @constant {Number} CONNECTING + * @memberof WebSocket.prototype + */ +Object.defineProperty(WebSocket.prototype, 'CONNECTING', { + enumerable: true, + value: readyStates.indexOf('CONNECTING') +}); + +/** + * @constant {Number} OPEN + * @memberof WebSocket + */ +Object.defineProperty(WebSocket, 'OPEN', { + enumerable: true, + value: readyStates.indexOf('OPEN') +}); + +/** + * @constant {Number} OPEN + * @memberof WebSocket.prototype + */ +Object.defineProperty(WebSocket.prototype, 'OPEN', { + enumerable: true, + value: readyStates.indexOf('OPEN') +}); + +/** + * @constant {Number} CLOSING + * @memberof WebSocket + */ +Object.defineProperty(WebSocket, 'CLOSING', { + enumerable: true, + value: readyStates.indexOf('CLOSING') +}); + +/** + * @constant {Number} CLOSING + * @memberof WebSocket.prototype + */ +Object.defineProperty(WebSocket.prototype, 'CLOSING', { + enumerable: true, + value: readyStates.indexOf('CLOSING') +}); + +/** + * @constant {Number} CLOSED + * @memberof WebSocket + */ +Object.defineProperty(WebSocket, 'CLOSED', { + enumerable: true, + value: readyStates.indexOf('CLOSED') +}); + +/** + * @constant {Number} CLOSED + * @memberof WebSocket.prototype + */ +Object.defineProperty(WebSocket.prototype, 'CLOSED', { + enumerable: true, + value: readyStates.indexOf('CLOSED') +}); + +[ + 'binaryType', + 'bufferedAmount', + 'extensions', + 'isPaused', + 'protocol', + 'readyState', + 'url' +].forEach((property) => { + Object.defineProperty(WebSocket.prototype, property, { enumerable: true }); +}); + +// +// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes. +// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface +// +['open', 'error', 'close', 'message'].forEach((method) => { + Object.defineProperty(WebSocket.prototype, `on${method}`, { + enumerable: true, + get() { + for (const listener of this.listeners(method)) { + if (listener[kForOnEventAttribute]) return listener[kListener]; + } + + return null; + }, + set(handler) { + for (const listener of this.listeners(method)) { + if (listener[kForOnEventAttribute]) { + this.removeListener(method, listener); + break; + } + } + + if (typeof handler !== 'function') return; + + this.addEventListener(method, handler, { + [kForOnEventAttribute]: true + }); + } + }); +}); + +WebSocket.prototype.addEventListener = addEventListener; +WebSocket.prototype.removeEventListener = removeEventListener; + +module.exports = WebSocket; + +/** + * Initialize a WebSocket client. + * + * @param {WebSocket} websocket The client to initialize + * @param {(String|URL)} address The URL to which to connect + * @param {Array} protocols The subprotocols + * @param {Object} [options] Connection options + * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any + * of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple + * times in the same tick + * @param {Boolean} [options.autoPong=true] Specifies whether or not to + * automatically send a pong in response to a ping + * @param {Function} [options.finishRequest] A function which can be used to + * customize the headers of each http request before it is sent + * @param {Boolean} [options.followRedirects=false] Whether or not to follow + * redirects + * @param {Function} [options.generateMask] The function used to generate the + * masking key + * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the + * handshake request + * @param {Number} [options.maxPayload=104857600] The maximum allowed message + * size + * @param {Number} [options.maxRedirects=10] The maximum number of redirects + * allowed + * @param {String} [options.origin] Value of the `Origin` or + * `Sec-WebSocket-Origin` header + * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable + * permessage-deflate + * @param {Number} [options.protocolVersion=13] Value of the + * `Sec-WebSocket-Version` header + * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or + * not to skip UTF-8 validation for text and close messages + * @private + */ +function initAsClient(websocket, address, protocols, options) { + const opts = { + allowSynchronousEvents: true, + autoPong: true, + protocolVersion: protocolVersions[1], + maxPayload: 100 * 1024 * 1024, + skipUTF8Validation: false, + perMessageDeflate: true, + followRedirects: false, + maxRedirects: 10, + ...options, + socketPath: undefined, + hostname: undefined, + protocol: undefined, + timeout: undefined, + method: 'GET', + host: undefined, + path: undefined, + port: undefined + }; + + websocket._autoPong = opts.autoPong; + + if (!protocolVersions.includes(opts.protocolVersion)) { + throw new RangeError( + `Unsupported protocol version: ${opts.protocolVersion} ` + + `(supported versions: ${protocolVersions.join(', ')})` + ); + } + + let parsedUrl; + + if (address instanceof URL) { + parsedUrl = address; + } else { + try { + parsedUrl = new URL(address); + } catch (e) { + throw new SyntaxError(`Invalid URL: ${address}`); + } + } + + if (parsedUrl.protocol === 'http:') { + parsedUrl.protocol = 'ws:'; + } else if (parsedUrl.protocol === 'https:') { + parsedUrl.protocol = 'wss:'; + } + + websocket._url = parsedUrl.href; + + const isSecure = parsedUrl.protocol === 'wss:'; + const isIpcUrl = parsedUrl.protocol === 'ws+unix:'; + let invalidUrlMessage; + + if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) { + invalidUrlMessage = + 'The URL\'s protocol must be one of "ws:", "wss:", ' + + '"http:", "https", or "ws+unix:"'; + } else if (isIpcUrl && !parsedUrl.pathname) { + invalidUrlMessage = "The URL's pathname is empty"; + } else if (parsedUrl.hash) { + invalidUrlMessage = 'The URL contains a fragment identifier'; + } + + if (invalidUrlMessage) { + const err = new SyntaxError(invalidUrlMessage); + + if (websocket._redirects === 0) { + throw err; + } else { + emitErrorAndClose(websocket, err); + return; + } + } + + const defaultPort = isSecure ? 443 : 80; + const key = randomBytes(16).toString('base64'); + const request = isSecure ? https.request : http.request; + const protocolSet = new Set(); + let perMessageDeflate; + + opts.createConnection = + opts.createConnection || (isSecure ? tlsConnect : netConnect); + opts.defaultPort = opts.defaultPort || defaultPort; + opts.port = parsedUrl.port || defaultPort; + opts.host = parsedUrl.hostname.startsWith('[') + ? parsedUrl.hostname.slice(1, -1) + : parsedUrl.hostname; + opts.headers = { + ...opts.headers, + 'Sec-WebSocket-Version': opts.protocolVersion, + 'Sec-WebSocket-Key': key, + Connection: 'Upgrade', + Upgrade: 'websocket' + }; + opts.path = parsedUrl.pathname + parsedUrl.search; + opts.timeout = opts.handshakeTimeout; + + if (opts.perMessageDeflate) { + perMessageDeflate = new PerMessageDeflate( + opts.perMessageDeflate !== true ? opts.perMessageDeflate : {}, + false, + opts.maxPayload + ); + opts.headers['Sec-WebSocket-Extensions'] = format({ + [PerMessageDeflate.extensionName]: perMessageDeflate.offer() + }); + } + if (protocols.length) { + for (const protocol of protocols) { + if ( + typeof protocol !== 'string' || + !subprotocolRegex.test(protocol) || + protocolSet.has(protocol) + ) { + throw new SyntaxError( + 'An invalid or duplicated subprotocol was specified' + ); + } + + protocolSet.add(protocol); + } + + opts.headers['Sec-WebSocket-Protocol'] = protocols.join(','); + } + if (opts.origin) { + if (opts.protocolVersion < 13) { + opts.headers['Sec-WebSocket-Origin'] = opts.origin; + } else { + opts.headers.Origin = opts.origin; + } + } + if (parsedUrl.username || parsedUrl.password) { + opts.auth = `${parsedUrl.username}:${parsedUrl.password}`; + } + + if (isIpcUrl) { + const parts = opts.path.split(':'); + + opts.socketPath = parts[0]; + opts.path = parts[1]; + } + + let req; + + if (opts.followRedirects) { + if (websocket._redirects === 0) { + websocket._originalIpc = isIpcUrl; + websocket._originalSecure = isSecure; + websocket._originalHostOrSocketPath = isIpcUrl + ? opts.socketPath + : parsedUrl.host; + + const headers = options && options.headers; + + // + // Shallow copy the user provided options so that headers can be changed + // without mutating the original object. + // + options = { ...options, headers: {} }; + + if (headers) { + for (const [key, value] of Object.entries(headers)) { + options.headers[key.toLowerCase()] = value; + } + } + } else if (websocket.listenerCount('redirect') === 0) { + const isSameHost = isIpcUrl + ? websocket._originalIpc + ? opts.socketPath === websocket._originalHostOrSocketPath + : false + : websocket._originalIpc + ? false + : parsedUrl.host === websocket._originalHostOrSocketPath; + + if (!isSameHost || (websocket._originalSecure && !isSecure)) { + // + // Match curl 7.77.0 behavior and drop the following headers. These + // headers are also dropped when following a redirect to a subdomain. + // + delete opts.headers.authorization; + delete opts.headers.cookie; + + if (!isSameHost) delete opts.headers.host; + + opts.auth = undefined; + } + } + + // + // Match curl 7.77.0 behavior and make the first `Authorization` header win. + // If the `Authorization` header is set, then there is nothing to do as it + // will take precedence. + // + if (opts.auth && !options.headers.authorization) { + options.headers.authorization = + 'Basic ' + Buffer.from(opts.auth).toString('base64'); + } + + req = websocket._req = request(opts); + + if (websocket._redirects) { + // + // Unlike what is done for the `'upgrade'` event, no early exit is + // triggered here if the user calls `websocket.close()` or + // `websocket.terminate()` from a listener of the `'redirect'` event. This + // is because the user can also call `request.destroy()` with an error + // before calling `websocket.close()` or `websocket.terminate()` and this + // would result in an error being emitted on the `request` object with no + // `'error'` event listeners attached. + // + websocket.emit('redirect', websocket.url, req); + } + } else { + req = websocket._req = request(opts); + } + + if (opts.timeout) { + req.on('timeout', () => { + abortHandshake(websocket, req, 'Opening handshake has timed out'); + }); + } + + req.on('error', (err) => { + if (req === null || req[kAborted]) return; + + req = websocket._req = null; + emitErrorAndClose(websocket, err); + }); + + req.on('response', (res) => { + const location = res.headers.location; + const statusCode = res.statusCode; + + if ( + location && + opts.followRedirects && + statusCode >= 300 && + statusCode < 400 + ) { + if (++websocket._redirects > opts.maxRedirects) { + abortHandshake(websocket, req, 'Maximum redirects exceeded'); + return; + } + + req.abort(); + + let addr; + + try { + addr = new URL(location, address); + } catch (e) { + const err = new SyntaxError(`Invalid URL: ${location}`); + emitErrorAndClose(websocket, err); + return; + } + + initAsClient(websocket, addr, protocols, options); + } else if (!websocket.emit('unexpected-response', req, res)) { + abortHandshake( + websocket, + req, + `Unexpected server response: ${res.statusCode}` + ); + } + }); + + req.on('upgrade', (res, socket, head) => { + websocket.emit('upgrade', res); + + // + // The user may have closed the connection from a listener of the + // `'upgrade'` event. + // + if (websocket.readyState !== WebSocket.CONNECTING) return; + + req = websocket._req = null; + + const upgrade = res.headers.upgrade; + + if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') { + abortHandshake(websocket, socket, 'Invalid Upgrade header'); + return; + } + + const digest = createHash('sha1') + .update(key + GUID) + .digest('base64'); + + if (res.headers['sec-websocket-accept'] !== digest) { + abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header'); + return; + } + + const serverProt = res.headers['sec-websocket-protocol']; + let protError; + + if (serverProt !== undefined) { + if (!protocolSet.size) { + protError = 'Server sent a subprotocol but none was requested'; + } else if (!protocolSet.has(serverProt)) { + protError = 'Server sent an invalid subprotocol'; + } + } else if (protocolSet.size) { + protError = 'Server sent no subprotocol'; + } + + if (protError) { + abortHandshake(websocket, socket, protError); + return; + } + + if (serverProt) websocket._protocol = serverProt; + + const secWebSocketExtensions = res.headers['sec-websocket-extensions']; + + if (secWebSocketExtensions !== undefined) { + if (!perMessageDeflate) { + const message = + 'Server sent a Sec-WebSocket-Extensions header but no extension ' + + 'was requested'; + abortHandshake(websocket, socket, message); + return; + } + + let extensions; + + try { + extensions = parse(secWebSocketExtensions); + } catch (err) { + const message = 'Invalid Sec-WebSocket-Extensions header'; + abortHandshake(websocket, socket, message); + return; + } + + const extensionNames = Object.keys(extensions); + + if ( + extensionNames.length !== 1 || + extensionNames[0] !== PerMessageDeflate.extensionName + ) { + const message = 'Server indicated an extension that was not requested'; + abortHandshake(websocket, socket, message); + return; + } + + try { + perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]); + } catch (err) { + const message = 'Invalid Sec-WebSocket-Extensions header'; + abortHandshake(websocket, socket, message); + return; + } + + websocket._extensions[PerMessageDeflate.extensionName] = + perMessageDeflate; + } + + websocket.setSocket(socket, head, { + allowSynchronousEvents: opts.allowSynchronousEvents, + generateMask: opts.generateMask, + maxPayload: opts.maxPayload, + skipUTF8Validation: opts.skipUTF8Validation + }); + }); + + if (opts.finishRequest) { + opts.finishRequest(req, websocket); + } else { + req.end(); + } +} + +/** + * Emit the `'error'` and `'close'` events. + * + * @param {WebSocket} websocket The WebSocket instance + * @param {Error} The error to emit + * @private + */ +function emitErrorAndClose(websocket, err) { + websocket._readyState = WebSocket.CLOSING; + // + // The following assignment is practically useless and is done only for + // consistency. + // + websocket._errorEmitted = true; + websocket.emit('error', err); + websocket.emitClose(); +} + +/** + * Create a `net.Socket` and initiate a connection. + * + * @param {Object} options Connection options + * @return {net.Socket} The newly created socket used to start the connection + * @private + */ +function netConnect(options) { + options.path = options.socketPath; + return net.connect(options); +} + +/** + * Create a `tls.TLSSocket` and initiate a connection. + * + * @param {Object} options Connection options + * @return {tls.TLSSocket} The newly created socket used to start the connection + * @private + */ +function tlsConnect(options) { + options.path = undefined; + + if (!options.servername && options.servername !== '') { + options.servername = net.isIP(options.host) ? '' : options.host; + } + + return tls.connect(options); +} + +/** + * Abort the handshake and emit an error. + * + * @param {WebSocket} websocket The WebSocket instance + * @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to + * abort or the socket to destroy + * @param {String} message The error message + * @private + */ +function abortHandshake(websocket, stream, message) { + websocket._readyState = WebSocket.CLOSING; + + const err = new Error(message); + Error.captureStackTrace(err, abortHandshake); + + if (stream.setHeader) { + stream[kAborted] = true; + stream.abort(); + + if (stream.socket && !stream.socket.destroyed) { + // + // On Node.js >= 14.3.0 `request.abort()` does not destroy the socket if + // called after the request completed. See + // https://github.com/websockets/ws/issues/1869. + // + stream.socket.destroy(); + } + + process.nextTick(emitErrorAndClose, websocket, err); + } else { + stream.destroy(err); + stream.once('error', websocket.emit.bind(websocket, 'error')); + stream.once('close', websocket.emitClose.bind(websocket)); + } +} + +/** + * Handle cases where the `ping()`, `pong()`, or `send()` methods are called + * when the `readyState` attribute is `CLOSING` or `CLOSED`. + * + * @param {WebSocket} websocket The WebSocket instance + * @param {*} [data] The data to send + * @param {Function} [cb] Callback + * @private + */ +function sendAfterClose(websocket, data, cb) { + if (data) { + const length = isBlob(data) ? data.size : toBuffer(data).length; + + // + // The `_bufferedAmount` property is used only when the peer is a client and + // the opening handshake fails. Under these circumstances, in fact, the + // `setSocket()` method is not called, so the `_socket` and `_sender` + // properties are set to `null`. + // + if (websocket._socket) websocket._sender._bufferedBytes += length; + else websocket._bufferedAmount += length; + } + + if (cb) { + const err = new Error( + `WebSocket is not open: readyState ${websocket.readyState} ` + + `(${readyStates[websocket.readyState]})` + ); + process.nextTick(cb, err); + } +} + +/** + * The listener of the `Receiver` `'conclude'` event. + * + * @param {Number} code The status code + * @param {Buffer} reason The reason for closing + * @private + */ +function receiverOnConclude(code, reason) { + const websocket = this[kWebSocket]; + + websocket._closeFrameReceived = true; + websocket._closeMessage = reason; + websocket._closeCode = code; + + if (websocket._socket[kWebSocket] === undefined) return; + + websocket._socket.removeListener('data', socketOnData); + process.nextTick(resume, websocket._socket); + + if (code === 1005) websocket.close(); + else websocket.close(code, reason); +} + +/** + * The listener of the `Receiver` `'drain'` event. + * + * @private + */ +function receiverOnDrain() { + const websocket = this[kWebSocket]; + + if (!websocket.isPaused) websocket._socket.resume(); +} + +/** + * The listener of the `Receiver` `'error'` event. + * + * @param {(RangeError|Error)} err The emitted error + * @private + */ +function receiverOnError(err) { + const websocket = this[kWebSocket]; + + if (websocket._socket[kWebSocket] !== undefined) { + websocket._socket.removeListener('data', socketOnData); + + // + // On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See + // https://github.com/websockets/ws/issues/1940. + // + process.nextTick(resume, websocket._socket); + + websocket.close(err[kStatusCode]); + } + + if (!websocket._errorEmitted) { + websocket._errorEmitted = true; + websocket.emit('error', err); + } +} + +/** + * The listener of the `Receiver` `'finish'` event. + * + * @private + */ +function receiverOnFinish() { + this[kWebSocket].emitClose(); +} + +/** + * The listener of the `Receiver` `'message'` event. + * + * @param {Buffer|ArrayBuffer|Buffer[])} data The message + * @param {Boolean} isBinary Specifies whether the message is binary or not + * @private + */ +function receiverOnMessage(data, isBinary) { + this[kWebSocket].emit('message', data, isBinary); +} + +/** + * The listener of the `Receiver` `'ping'` event. + * + * @param {Buffer} data The data included in the ping frame + * @private + */ +function receiverOnPing(data) { + const websocket = this[kWebSocket]; + + if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP); + websocket.emit('ping', data); +} + +/** + * The listener of the `Receiver` `'pong'` event. + * + * @param {Buffer} data The data included in the pong frame + * @private + */ +function receiverOnPong(data) { + this[kWebSocket].emit('pong', data); +} + +/** + * Resume a readable stream + * + * @param {Readable} stream The readable stream + * @private + */ +function resume(stream) { + stream.resume(); +} + +/** + * The `Sender` error event handler. + * + * @param {Error} The error + * @private + */ +function senderOnError(err) { + const websocket = this[kWebSocket]; + + if (websocket.readyState === WebSocket.CLOSED) return; + if (websocket.readyState === WebSocket.OPEN) { + websocket._readyState = WebSocket.CLOSING; + setCloseTimer(websocket); + } + + // + // `socket.end()` is used instead of `socket.destroy()` to allow the other + // peer to finish sending queued data. There is no need to set a timer here + // because `CLOSING` means that it is already set or not needed. + // + this._socket.end(); + + if (!websocket._errorEmitted) { + websocket._errorEmitted = true; + websocket.emit('error', err); + } +} + +/** + * Set a timer to destroy the underlying raw socket of a WebSocket. + * + * @param {WebSocket} websocket The WebSocket instance + * @private + */ +function setCloseTimer(websocket) { + websocket._closeTimer = setTimeout( + websocket._socket.destroy.bind(websocket._socket), + closeTimeout + ); +} + +/** + * The listener of the socket `'close'` event. + * + * @private + */ +function socketOnClose() { + const websocket = this[kWebSocket]; + + this.removeListener('close', socketOnClose); + this.removeListener('data', socketOnData); + this.removeListener('end', socketOnEnd); + + websocket._readyState = WebSocket.CLOSING; + + let chunk; + + // + // The close frame might not have been received or the `'end'` event emitted, + // for example, if the socket was destroyed due to an error. Ensure that the + // `receiver` stream is closed after writing any remaining buffered data to + // it. If the readable side of the socket is in flowing mode then there is no + // buffered data as everything has been already written and `readable.read()` + // will return `null`. If instead, the socket is paused, any possible buffered + // data will be read as a single chunk. + // + if ( + !this._readableState.endEmitted && + !websocket._closeFrameReceived && + !websocket._receiver._writableState.errorEmitted && + (chunk = websocket._socket.read()) !== null + ) { + websocket._receiver.write(chunk); + } + + websocket._receiver.end(); + + this[kWebSocket] = undefined; + + clearTimeout(websocket._closeTimer); + + if ( + websocket._receiver._writableState.finished || + websocket._receiver._writableState.errorEmitted + ) { + websocket.emitClose(); + } else { + websocket._receiver.on('error', receiverOnFinish); + websocket._receiver.on('finish', receiverOnFinish); + } +} + +/** + * The listener of the socket `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function socketOnData(chunk) { + if (!this[kWebSocket]._receiver.write(chunk)) { + this.pause(); + } +} + +/** + * The listener of the socket `'end'` event. + * + * @private + */ +function socketOnEnd() { + const websocket = this[kWebSocket]; + + websocket._readyState = WebSocket.CLOSING; + websocket._receiver.end(); + this.end(); +} + +/** + * The listener of the socket `'error'` event. + * + * @private + */ +function socketOnError() { + const websocket = this[kWebSocket]; + + this.removeListener('error', socketOnError); + this.on('error', NOOP); + + if (websocket) { + websocket._readyState = WebSocket.CLOSING; + this.destroy(); + } +} diff --git a/tools/websockets-debugger-test/node_modules/ws/package.json b/tools/websockets-debugger-test/node_modules/ws/package.json new file mode 100644 index 0000000..4f7155d --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/package.json @@ -0,0 +1,69 @@ +{ + "name": "ws", + "version": "8.18.0", + "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js", + "keywords": [ + "HyBi", + "Push", + "RFC-6455", + "WebSocket", + "WebSockets", + "real-time" + ], + "homepage": "https://github.com/websockets/ws", + "bugs": "https://github.com/websockets/ws/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/websockets/ws.git" + }, + "author": "Einar Otto Stangvik (http://2x.io)", + "license": "MIT", + "main": "index.js", + "exports": { + ".": { + "browser": "./browser.js", + "import": "./wrapper.mjs", + "require": "./index.js" + }, + "./package.json": "./package.json" + }, + "browser": "browser.js", + "engines": { + "node": ">=10.0.0" + }, + "files": [ + "browser.js", + "index.js", + "lib/*.js", + "wrapper.mjs" + ], + "scripts": { + "test": "nyc --reporter=lcov --reporter=text mocha --throw-deprecation test/*.test.js", + "integration": "mocha --throw-deprecation test/*.integration.js", + "lint": "eslint . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yaml,yml}\"" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + }, + "devDependencies": { + "benchmark": "^2.1.4", + "bufferutil": "^4.0.1", + "eslint": "^9.0.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "globals": "^15.0.0", + "mocha": "^8.4.0", + "nyc": "^15.0.0", + "prettier": "^3.0.0", + "utf-8-validate": "^6.0.0" + } +} diff --git a/tools/websockets-debugger-test/node_modules/ws/wrapper.mjs b/tools/websockets-debugger-test/node_modules/ws/wrapper.mjs new file mode 100644 index 0000000..7245ad1 --- /dev/null +++ b/tools/websockets-debugger-test/node_modules/ws/wrapper.mjs @@ -0,0 +1,8 @@ +import createWebSocketStream from './lib/stream.js'; +import Receiver from './lib/receiver.js'; +import Sender from './lib/sender.js'; +import WebSocket from './lib/websocket.js'; +import WebSocketServer from './lib/websocket-server.js'; + +export { createWebSocketStream, Receiver, Sender, WebSocket, WebSocketServer }; +export default WebSocket; diff --git a/tools/websockets-debugger-test/package-lock.json b/tools/websockets-debugger-test/package-lock.json new file mode 100644 index 0000000..e07cd29 --- /dev/null +++ b/tools/websockets-debugger-test/package-lock.json @@ -0,0 +1,37 @@ +{ + "name": "websockets-debugger-test", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "websockets-debugger-test", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "ws": "^8.18.0" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/tools/websockets-debugger-test/package.json b/tools/websockets-debugger-test/package.json new file mode 100644 index 0000000..27183bc --- /dev/null +++ b/tools/websockets-debugger-test/package.json @@ -0,0 +1,15 @@ +{ + "name": "websockets-debugger-test", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "ws": "^8.18.0" + } +}