From 5c8e86356b6983ba8ea24dbc84a188e052c504a4 Mon Sep 17 00:00:00 2001 From: Michel de Bree Date: Mon, 27 May 2024 19:51:36 +0200 Subject: [PATCH] Switch for ASID/RESID output (#180) * Switch for ASID/RESID output * Removed obsolete comment * Fix parentheses style * Formatter config --- .clang-format | 7 +-- .gitignore | 1 + Makefile | 3 +- .../runtime/editor/keys/keyhook_setup.cpp | 1 + .../runtime/editor/screens/screen_edit.cpp | 27 +++++++++++- .../runtime/editor/screens/screen_edit.h | 1 + .../screens/statusbar/status_bar_edit.cpp | 20 ++++++++- .../screens/statusbar/status_bar_edit.h | 8 +++- .../source/runtime/emulation/asid/asid.cpp | 12 ++++-- .../source/runtime/emulation/asid/asid.h | 5 ++- .../runtime/execution/executionhandler.cpp | 43 ++++++++++++++++--- .../runtime/execution/executionhandler.h | 12 +++++- 12 files changed, 120 insertions(+), 20 deletions(-) diff --git a/.clang-format b/.clang-format index 2dcae007..b34ee789 100644 --- a/.clang-format +++ b/.clang-format @@ -2,7 +2,8 @@ # https://clang.llvm.org/docs/ClangFormatStyleOptions.html Language: Cpp # BasedOnStyle: WebKit -AccessModifierOffset: -2 +IndentAccessModifiers: false +AccessModifierOffset: -4 AlignAfterOpenBracket: DontAlign AlignConsecutiveMacros: false AlignConsecutiveAssignments: false @@ -36,7 +37,7 @@ BraceWrapping: AfterStruct: true AfterUnion: true AfterExternBlock: true - BeforeCatch: false + BeforeCatch: true BeforeElse: true BeforeLambdaBody: true IndentBraces: false @@ -111,7 +112,7 @@ SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: true +SpaceAfterTemplateKeyword: false SpaceBeforeAssignmentOperators: true SpaceBeforeCpp11BracedList: true SpaceBeforeCtorInitializerColon: true diff --git a/.gitignore b/.gitignore index 9c254ba5..b33bca0f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ artifacts xcuserdata .ccls-cache /SIDFactoryII/x64/Debug +compile_commands.json diff --git a/Makefile b/Makefile index e992aaf4..8fceac11 100644 --- a/Makefile +++ b/Makefile @@ -126,7 +126,8 @@ clean: .PHONY: run run: $(EXE) - cd $(ARTIFACTS_FOLDER) && ./$(APP_NAME) + cd $(ARTIFACTS_FOLDER) && ./$(APP_NAME) "../SIDFactoryII/music/Laxity/Laxity - Farfisa.sf2" + .PHONY: debug debug: $(EXE) diff --git a/SIDFactoryII/source/runtime/editor/keys/keyhook_setup.cpp b/SIDFactoryII/source/runtime/editor/keys/keyhook_setup.cpp index 391d2b6c..fc06318e 100644 --- a/SIDFactoryII/source/runtime/editor/keys/keyhook_setup.cpp +++ b/SIDFactoryII/source/runtime/editor/keys/keyhook_setup.cpp @@ -82,6 +82,7 @@ namespace Editor definitions.push_back({ "Key.ScreenEdit.ToggleMuteChannel1", {{ SDLK_1, Keyboard::Control }} }); definitions.push_back({ "Key.ScreenEdit.ToggleMuteChannel2", {{ SDLK_2, Keyboard::Control }} }); definitions.push_back({ "Key.ScreenEdit.ToggleMuteChannel3", {{ SDLK_3, Keyboard::Control }} }); + definitions.push_back({ "Key.ScreenEdit.ToggleOutputDevice", {{ SDLK_o, Keyboard::Alt }} }); definitions.push_back({ "Key.ScreenEdit.SetMarker", {{ SDLK_m, Keyboard::Control }} }); definitions.push_back({ "Key.ScreenEdit.GotoMarker", {{ SDLK_g, Keyboard::Control }} }); definitions.push_back({ "Key.ScreenEdit.QuickSave", {{ SDLK_s, Keyboard::Control }} }); diff --git a/SIDFactoryII/source/runtime/editor/screens/screen_edit.cpp b/SIDFactoryII/source/runtime/editor/screens/screen_edit.cpp index ef9bf547..79bf61c3 100644 --- a/SIDFactoryII/source/runtime/editor/screens/screen_edit.cpp +++ b/SIDFactoryII/source/runtime/editor/screens/screen_edit.cpp @@ -206,6 +206,11 @@ namespace Editor DoToggleSIDModelAndRegion(KeyboardUtils::IsModifierExclusivelyDown(inKeyboardModifiers, Keyboard::Control)); }; + auto mouse_button_output_device = [&](Foundation::Mouse::Button inMouseButton, int inKeyboardModifiers) + { + DoToggleOutputDevice(); + }; + auto mouse_button_context_highlight = [&](Foundation::Mouse::Button inMouseButton, int inKeyboardModifiers) { DoToggleContextHighlight(); @@ -226,7 +231,8 @@ namespace Editor ? std::to_string(selected_song_index + 1) : song_name; - m_StatusBar = std::make_unique(m_MainTextField, m_EditState, m_DriverState, m_DriverInfo->GetAuxilaryDataCollection(), mouse_button_octave, mouse_button_flat_sharp, mouse_button_sid_model, mouse_button_context_highlight, mouse_button_follow_play); + m_StatusBar = std::make_unique(m_MainTextField, m_EditState, m_DriverState, m_DriverInfo->GetAuxilaryDataCollection(), *m_ExecutionHandler, + mouse_button_octave, mouse_button_flat_sharp, mouse_button_sid_model, mouse_button_output_device, mouse_button_context_highlight, mouse_button_follow_play); m_StatusBar->SetText(m_ActivationMessage.length() > 0 ? m_ActivationMessage : " SID Factory II [Selected song: " + song_selection_text + "]", 2500, false); m_ActivationMessage = ""; @@ -594,6 +600,19 @@ namespace Editor } } + void ScreenEdit::DoToggleOutputDevice() + { + ExecutionHandler::OutputDevice device = m_ExecutionHandler->GetOutputDevice(); + + if (device == ExecutionHandler::OutputDevice::RESID) { + device = ExecutionHandler::OutputDevice::ASID; + } + else { + device = ExecutionHandler::OutputDevice::RESID; + } + m_ExecutionHandler->SetOutputDevice(device); + } + void ScreenEdit::DoClearAllMuteState() { @@ -1963,6 +1982,12 @@ namespace Editor return true; } }); + m_KeyHooks.push_back( { "Key.ScreenEdit.ToggleOutputDevice", m_KeyHookStore, [&]() + { + DoToggleOutputDevice(); + return true; + }}); + m_KeyHooks.push_back({ "Key.ScreenEdit.SetMarker", m_KeyHookStore, [&]() { const int selected_marker = m_PlayMarkerListComponent->GetSelectionIndex(); diff --git a/SIDFactoryII/source/runtime/editor/screens/screen_edit.h b/SIDFactoryII/source/runtime/editor/screens/screen_edit.h index 14782c58..f88e9e4e 100644 --- a/SIDFactoryII/source/runtime/editor/screens/screen_edit.h +++ b/SIDFactoryII/source/runtime/editor/screens/screen_edit.h @@ -116,6 +116,7 @@ namespace Editor void DoPlayFromSelectedMarker(); void DoStop(); void DoToggleMute(unsigned int inChannel); + void DoToggleOutputDevice(); void DoClearAllMuteState(); void DoRestoreMuteState(); void DoMoveToEventPositionOfSelectedMarker(); diff --git a/SIDFactoryII/source/runtime/editor/screens/statusbar/status_bar_edit.cpp b/SIDFactoryII/source/runtime/editor/screens/statusbar/status_bar_edit.cpp index 52afb44a..3b9948b2 100644 --- a/SIDFactoryII/source/runtime/editor/screens/statusbar/status_bar_edit.cpp +++ b/SIDFactoryII/source/runtime/editor/screens/statusbar/status_bar_edit.cpp @@ -1,7 +1,9 @@ #include "status_bar_edit.h" #include "foundation/graphics/textfield.h" #include "foundation/graphics/color.h" +#include "runtime/execution/executionhandler.h" #include "utils/usercolors.h" +#include using namespace Utility; using namespace Foundation; @@ -14,9 +16,11 @@ namespace Editor const EditState& inEditState, const DriverState& inDriverState, const AuxilaryDataCollection& inAuxilaryDataCollection, + const Emulation::ExecutionHandler& inExecutionHandler, std::function inOctaveMousePressCallback, std::function inSharpFlatMousePressCallback, std::function inSIDMousePressCallback, + std::function inOutputDevicePressCallback, std::function inContextHighlightMousePressCallback, std::function inFollowPlayerMousePressCallback ) @@ -24,18 +28,21 @@ namespace Editor , m_EditState(inEditState) , m_DriverState(inDriverState) , m_AuxilaryDataPlayMarkers(inAuxilaryDataCollection) + , m_ExecutionHandler(inExecutionHandler) { m_TextSectionOctave = std::make_shared(12, inOctaveMousePressCallback); m_TextSectionSharpFlat = std::make_shared(15, inSharpFlatMousePressCallback); m_TextSectionSID = std::make_shared(19, inSIDMousePressCallback); m_TextSectionContextHighlight = std::make_shared(18, inContextHighlightMousePressCallback); m_TextSectionFollowPlay = std::make_shared(15, inFollowPlayerMousePressCallback); + m_TextSectionOutputDevice = std::make_shared(17, inOutputDevicePressCallback); m_TextSectionList.push_back(m_TextSectionOctave); m_TextSectionList.push_back(m_TextSectionSharpFlat); m_TextSectionList.push_back(m_TextSectionSID); m_TextSectionList.push_back(m_TextSectionContextHighlight); m_TextSectionList.push_back(m_TextSectionFollowPlay); + m_TextSectionList.push_back(m_TextSectionOutputDevice); } @@ -43,8 +50,7 @@ namespace Editor { } - - + void StatusBarEdit::UpdateInternal(int inDeltaTick, bool inNeedUpdate) { if (m_CachedEditState != m_EditState || inNeedUpdate) @@ -78,6 +84,16 @@ namespace Editor m_NeedRefresh = true; } + const Emulation::ExecutionHandler::OutputDevice outputDevice = m_ExecutionHandler.GetOutputDevice(); + + if (outputDevice != m_CachedOutputDevice || inNeedUpdate) + { + std::string output_device_string = (outputDevice == Emulation::ExecutionHandler::OutputDevice::ASID ? "ASID" : "RESID"); + m_TextSectionOutputDevice->SetText("Output: " + output_device_string); + m_CachedOutputDevice = outputDevice; + m_NeedRefresh = true; + } + const AuxilaryDataEditingPreferences::NotationMode notation_mode = editor_preferences.GetNotationMode(); if (notation_mode != m_CachedNotationMode || inNeedUpdate) { diff --git a/SIDFactoryII/source/runtime/editor/screens/statusbar/status_bar_edit.h b/SIDFactoryII/source/runtime/editor/screens/statusbar/status_bar_edit.h index be2681be..c3022458 100644 --- a/SIDFactoryII/source/runtime/editor/screens/statusbar/status_bar_edit.h +++ b/SIDFactoryII/source/runtime/editor/screens/statusbar/status_bar_edit.h @@ -8,6 +8,7 @@ #include "runtime/editor/auxilarydata/auxilary_data_hardware_preferences.h" #include "runtime/editor/screens/statusbar/status_bar.h" #include "runtime/editor/driver/driver_state.h" +#include "runtime/execution/executionhandler.h" #include #include @@ -27,9 +28,11 @@ namespace Editor const EditState& inEditState, const DriverState& inDriverState, const AuxilaryDataCollection& inAuxilaryDataCollection, + const Emulation::ExecutionHandler& inExecutionHandler, std::function inOctaveMousePressCallback, std::function inSharpFlatMousePressCallback, std::function inSIDMousePressCallback, + std::function inOuputDevicePressCallback, std::function inContextHighlightMousePressCallback, std::function inFollowPlayerMousePressCallback ); @@ -48,10 +51,12 @@ namespace Editor std::shared_ptr m_TextSectionSID; std::shared_ptr m_TextSectionContextHighlight; std::shared_ptr m_TextSectionFollowPlay; + std::shared_ptr m_TextSectionOutputDevice; const EditState& m_EditState; const AuxilaryDataCollection& m_AuxilaryDataPlayMarkers; const DriverState& m_DriverState; + const Emulation::ExecutionHandler& m_ExecutionHandler; EditState m_CachedEditState; DriverState m_CachedDriverState; @@ -59,5 +64,6 @@ namespace Editor AuxilaryDataEditingPreferences::NotationMode m_CachedNotationMode; AuxilaryDataHardwarePreferences::SIDModel m_CachedSIDModel; AuxilaryDataHardwarePreferences::Region m_CachedRegion; + Emulation::ExecutionHandler::OutputDevice m_CachedOutputDevice; }; -} \ No newline at end of file +} diff --git a/SIDFactoryII/source/runtime/emulation/asid/asid.cpp b/SIDFactoryII/source/runtime/emulation/asid/asid.cpp index e34d73d6..686a6f02 100644 --- a/SIDFactoryII/source/runtime/emulation/asid/asid.cpp +++ b/SIDFactoryII/source/runtime/emulation/asid/asid.cpp @@ -20,6 +20,12 @@ namespace Emulation } } + + bool ASid::isPortOpen() + { + return m_RtMidiOut->isPortOpen(); + } + void ASid::SetMuted(bool inMuted) { if(inMuted == m_Muted) @@ -30,17 +36,17 @@ namespace Emulation m_Muted = inMuted; } - + void ASid::SendSIDRegisterWriteOrderAndCycleInfo(std::vector inSIDWriteInfoList) { #define WRITE_ORDER_UNUSED 0xff - + struct write_order { unsigned char ucIndex; unsigned char ucCycles; }; - + // Physical out buffer, including protocol overhead unsigned char ASidOutBuffer[ASID_NUM_REGS*2+4]; diff --git a/SIDFactoryII/source/runtime/emulation/asid/asid.h b/SIDFactoryII/source/runtime/emulation/asid/asid.h index bf734bb9..a3ff485e 100644 --- a/SIDFactoryII/source/runtime/emulation/asid/asid.h +++ b/SIDFactoryII/source/runtime/emulation/asid/asid.h @@ -14,8 +14,9 @@ namespace Emulation public: ASid(RtMidiOut* inRtMidiOut); + bool isPortOpen(); void SetMuted(bool inMuted); - + void SendSIDRegisterWriteOrderAndCycleInfo(std::vector inSIDWriteInfoList); void WriteToSIDRegister(unsigned char inSidReg, unsigned char inData); void SendToDevice(); @@ -26,7 +27,7 @@ namespace Emulation bool m_Muted = false; RtMidiOut* m_RtMidiOut = nullptr; - + // Physical out buffer, including protocol overhead unsigned char m_ASIDOutBuffer[ASID_NUM_REGS + 12]; diff --git a/SIDFactoryII/source/runtime/execution/executionhandler.cpp b/SIDFactoryII/source/runtime/execution/executionhandler.cpp index 9e83ea1b..1684894f 100644 --- a/SIDFactoryII/source/runtime/execution/executionhandler.cpp +++ b/SIDFactoryII/source/runtime/execution/executionhandler.cpp @@ -1,5 +1,6 @@ #include "executionhandler.h" +#include "libraries/residfp/siddefs-fp.h" #include "runtime/emulation/cpuframecapture.h" #include "runtime/emulation/cpumos6510.h" #include "runtime/emulation/sid/sidproxy.h" @@ -49,7 +50,8 @@ namespace Emulation , m_SampleBufferWriteCursor(0) , m_CPUFrameCounter(0) , m_UpdateEnabled(false) - , m_ErrorState(false) + , m_ErrorState(false) + , m_OutputDevice(OutputDevice::RESID) { m_CyclesPerFrame = EMULATION_CYCLES_PER_FRAME_PAL; @@ -142,6 +144,29 @@ namespace Emulation FeedPCM(inBuffer, inByteCount); } + void ExecutionHandler::SetOutputDevice(const OutputDevice device) + { + + if (m_OutputDevice == device) + return; + + // if MIDI port is not open, do not switch to ASID + if (!m_ASID->isPortOpen()) + return; + + m_OutputDevice = device; + + // mute/unmute ASID depending on its selection + m_ASID->SetMuted(m_OutputDevice != OutputDevice::ASID); + + Utility::Logging::instance().Info("OutputDevice set to %s", m_OutputDevice == ExecutionHandler::OutputDevice::ASID ? "ASID" : "RESID"); + } + + const ExecutionHandler::OutputDevice ExecutionHandler::GetOutputDevice() const + { + return m_OutputDevice; + } + void ExecutionHandler::FeedPCM(void* inBuffer, unsigned int inByteCount) { m_FeedCount++; @@ -173,9 +198,16 @@ namespace Emulation for (unsigned int i = 0; i < uiSamplesToCopy; ++i) { - const float fSample = static_cast(pSource[i + m_SampleBufferReadCursor]) * m_OutputGain; - const float fClampedSample = fmin(sampleCeiling, fmax(fSample, sampleFloor)); - pTarget[i] = static_cast(fClampedSample); + if (m_OutputDevice == ExecutionHandler::OutputDevice::RESID) + { + const float fSample = static_cast(pSource[i + m_SampleBufferReadCursor]) * m_OutputGain; + const float fClampedSample = fmin(sampleCeiling, fmax(fSample, sampleFloor)); + pTarget[i] = static_cast(fClampedSample); + } + else + { + pTarget[i] = 0; + } } // Forward the read cursor @@ -391,7 +423,6 @@ namespace Emulation } } - void ExecutionHandler::CaptureNewFrame() { FOUNDATION_ASSERT(m_CPU != nullptr); @@ -519,7 +550,7 @@ namespace Emulation m_SIDProxy->Write((unsigned char)(capture.m_usReg & 0xff), capture.m_ucVal); nCycle += deltaCycles; - if(m_ASID != nullptr) + if(m_OutputDevice == ExecutionHandler::OutputDevice::ASID && m_ASID != nullptr) m_ASID->WriteToSIDRegister(static_cast(capture.m_usReg & 0xff), capture.m_ucVal); } diff --git a/SIDFactoryII/source/runtime/execution/executionhandler.h b/SIDFactoryII/source/runtime/execution/executionhandler.h index 1e0cda89..2b4646d6 100644 --- a/SIDFactoryII/source/runtime/execution/executionhandler.h +++ b/SIDFactoryII/source/runtime/execution/executionhandler.h @@ -106,7 +106,16 @@ namespace Emulation // SID Write order info void TellSIDWriteOrderInfo(std::vector SIDWriteInfoList); - + + enum class OutputDevice: int + { + RESID, + ASID + }; + + void SetOutputDevice(const OutputDevice device); + const OutputDevice GetOutputDevice() const; + private: enum class ActionType : int { @@ -183,6 +192,7 @@ namespace Emulation unsigned int m_SampleBufferSize; short* m_SampleBuffer; float m_OutputGain; + OutputDevice m_OutputDevice; }; }