diff --git a/source/Card.cpp b/source/Card.cpp index 4dab1192..67d2e832 100644 --- a/source/Card.cpp +++ b/source/Card.cpp @@ -161,6 +161,8 @@ std::string Card::GetCardName(const SS_CARDTYPE cardType) return Uthernet2::GetSnapshotCardName(); case CT_MegaAudio: return MockingboardCard::GetSnapshotCardNameMegaAudio(); + case CT_SDMusic: + return MockingboardCard::GetSnapshotCardNameSDMusic(); default: return "Unknown"; } @@ -236,6 +238,10 @@ SS_CARDTYPE Card::GetCardType(const std::string & card) { return CT_MegaAudio; } + else if (card == MockingboardCard::GetSnapshotCardNameSDMusic()) + { + return CT_SDMusic; + } else { throw std::runtime_error("Slots: Unknown card: " + card); // todo: don't throw - just ignore & continue diff --git a/source/Card.h b/source/Card.h index d64320c9..4fce8614 100644 --- a/source/Card.h +++ b/source/Card.h @@ -26,6 +26,7 @@ enum SS_CARDTYPE CT_VidHD, CT_Uthernet2, CT_MegaAudio, // Soundcard + CT_SDMusic, // Soundcard }; enum SLOTS { SLOT0=0, SLOT1, SLOT2, SLOT3, SLOT4, SLOT5, SLOT6, SLOT7, NUM_SLOTS, SLOT_AUX, GAME_IO_CONNECTOR }; diff --git a/source/CardManager.cpp b/source/CardManager.cpp index f4af3e47..a1986e39 100644 --- a/source/CardManager.cpp +++ b/source/CardManager.cpp @@ -67,6 +67,7 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type) break; case CT_MockingboardC: case CT_MegaAudio: + case CT_SDMusic: m_slot[slot] = new MockingboardCard(slot, type); break; case CT_GenericPrinter: diff --git a/source/CmdLine.cpp b/source/CmdLine.cpp index 9a7f3d0d..a9d2ba35 100644 --- a/source/CmdLine.cpp +++ b/source/CmdLine.cpp @@ -176,7 +176,15 @@ bool ProcessCmdLine(LPSTR lpCmdLine) if (strcmp(lpCmdLine, "hdc") == 0) g_cmdLine.slotInsert[slot] = CT_GenericHDD; if (strcmp(lpCmdLine, "megaaudio") == 0) + { g_cmdLine.slotInsert[slot] = CT_MegaAudio; + g_cmdLine.supportExtraMBCardTypes = true; + } + if (strcmp(lpCmdLine, "sdmusic") == 0) + { + g_cmdLine.slotInsert[slot] = CT_SDMusic; + g_cmdLine.supportExtraMBCardTypes = true; + } if (strcmp(lpCmdLine, "parallel") == 0) { if (slot == SLOT1) @@ -599,6 +607,12 @@ bool ProcessCmdLine(LPSTR lpCmdLine) lpNextArg = GetNextArg(lpNextArg); g_cmdLine.wavFileMockingboard = lpCmdLine; } + else if (strcmp(lpCmdLine, "-mb-audit") == 0) // enable selection of additional sound cards, eg. for mb-audit + { + lpCmdLine = GetCurrArg(lpNextArg); + lpNextArg = GetNextArg(lpNextArg); + g_cmdLine.supportExtraMBCardTypes = true; + } else if (strcmp(lpCmdLine, "-no-disk2-stepper-defer") == 0) // a debug switch (likely to be removed in a future version) { g_cmdLine.noDisk2StepperDefer = true; diff --git a/source/CmdLine.h b/source/CmdLine.h index b5cf2b66..98b4b2d0 100644 --- a/source/CmdLine.h +++ b/source/CmdLine.h @@ -32,6 +32,7 @@ struct CmdLine snesMaxAltControllerType[1] = false; supportDCD = false; enableDumpToRealPrinter = false; + supportExtraMBCardTypes = false; noDisk2StepperDefer = false; szSnapshotName = NULL; szScreenshotFilename = NULL; @@ -74,6 +75,7 @@ struct CmdLine bool snesMaxAltControllerType[2]; bool supportDCD; bool enableDumpToRealPrinter; + bool supportExtraMBCardTypes; bool noDisk2StepperDefer; // debug SS_CARDTYPE slotInsert[NUM_SLOTS]; SlotInfo slotInfo[NUM_SLOTS]; diff --git a/source/Configuration/PageSound.cpp b/source/Configuration/PageSound.cpp index 46f41b6c..39f71633 100644 --- a/source/Configuration/PageSound.cpp +++ b/source/Configuration/PageSound.cpp @@ -44,7 +44,7 @@ const char CPageSound::m_soundCardChoices[] = "Mockingboard\0" "SAM\0" "Empty\0"; -// Don't reveal MegaAudio card unless it's been specified from the command line. +// Don't reveal MegaAudio/SD Music cards unless it's been specified from the command line. // The reasons being are that: // . this card is purely for regression testing against mb-audit // . it's confusing to offer this to the end user @@ -52,7 +52,8 @@ const char CPageSound::m_soundCardChoicesEx[] = "Mockingboard\0" "Phasor\0" "SAM\0" "Empty\0" - "MEGA Audio\0"; + "MEGA Audio\0" + "SD Music\0"; const char CPageSound::m_soundCardChoice_Unavailable[] = "Unavailable\0\0"; // doubly-null terminate @@ -116,6 +117,7 @@ INT_PTR CPageSound::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPAR case SC_SAM: newCard = CT_SAM; break; case SC_EMPTY: newCard = CT_Empty; break; case SC_MEGAAUDIO: newCard = CT_MegaAudio; break; + case SC_SDMUSIC: newCard = CT_SDMusic; break; default: _ASSERT(0); break; } @@ -178,6 +180,7 @@ CPageSound::SOUNDCARDCHOICE CPageSound::CardTypeToComboItem(SS_CARDTYPE card) case CT_SAM: return SC_SAM; case CT_Empty: return SC_EMPTY; case CT_MegaAudio: return SC_MEGAAUDIO; + case CT_SDMusic: return SC_SDMUSIC; default: _ASSERT(0); return SC_EMPTY; } } @@ -190,31 +193,28 @@ void CPageSound::InitOptions(HWND hWnd) bool isSlot4SoundCard = slot4 == CT_MockingboardC || slot4 == CT_Phasor || slot4 == CT_SAM || slot4 == CT_Empty; bool isSlot5SoundCard = slot5 == CT_MockingboardC || slot5 == CT_Phasor || slot5 == CT_SAM || slot5 == CT_Empty; - bool isSlot4SoundCardEx = slot4 == CT_MegaAudio; - bool isSlot5SoundCardEx = slot5 == CT_MegaAudio; + bool isSlotXSoundCardEx = GetCardMgr().GetMockingboardCardMgr().GetEnableExtraCardTypes(); - if (isSlot4SoundCardEx || isSlot5SoundCardEx) - { - isSlot4SoundCardEx = isSlot5SoundCardEx = true; // if MegaAudio is visible in either, then make it available in both menus + if (isSlotXSoundCardEx) isSlot4SoundCard = isSlot5SoundCard = false; - } if (isSlot4SoundCard) m_PropertySheetHelper.FillComboBox(hWnd, IDC_SOUNDCARD_SLOT4, m_soundCardChoices, (int)CardTypeToComboItem(slot4)); - else if (isSlot4SoundCardEx) + else if (isSlotXSoundCardEx) m_PropertySheetHelper.FillComboBox(hWnd, IDC_SOUNDCARD_SLOT4, m_soundCardChoicesEx, (int)CardTypeToComboItem(slot4)); else m_PropertySheetHelper.FillComboBox(hWnd, IDC_SOUNDCARD_SLOT4, m_soundCardChoice_Unavailable, 0); if (isSlot5SoundCard) m_PropertySheetHelper.FillComboBox(hWnd, IDC_SOUNDCARD_SLOT5, m_soundCardChoices, (int)CardTypeToComboItem(slot5)); - else if (isSlot5SoundCardEx) + else if (isSlotXSoundCardEx) m_PropertySheetHelper.FillComboBox(hWnd, IDC_SOUNDCARD_SLOT5, m_soundCardChoicesEx, (int)CardTypeToComboItem(slot5)); else m_PropertySheetHelper.FillComboBox(hWnd, IDC_SOUNDCARD_SLOT5, m_soundCardChoice_Unavailable, 0); bool enableMBVolume = slot4 == CT_MockingboardC || slot5 == CT_MockingboardC || slot4 == CT_Phasor || slot5 == CT_Phasor - || slot4 == CT_MegaAudio || slot5 == CT_MegaAudio; + || slot4 == CT_MegaAudio || slot5 == CT_MegaAudio + || slot4 == CT_SDMusic || slot5 == CT_SDMusic; EnableWindow(GetDlgItem(hWnd, IDC_MB_VOLUME), enableMBVolume ? TRUE : FALSE); } diff --git a/source/Configuration/PageSound.h b/source/Configuration/PageSound.h index 53a8bc5c..6c6bf1df 100644 --- a/source/Configuration/PageSound.h +++ b/source/Configuration/PageSound.h @@ -28,7 +28,7 @@ protected: virtual void DlgCANCEL(HWND hWnd){} private: - enum SOUNDCARDCHOICE { SC_MOCKINGBOARD = 0, SC_PHASOR, SC_SAM, SC_EMPTY, SC_MEGAAUDIO }; + enum SOUNDCARDCHOICE { SC_MOCKINGBOARD = 0, SC_PHASOR, SC_SAM, SC_EMPTY, SC_MEGAAUDIO, SC_SDMUSIC }; void InitOptions(HWND hWnd); SOUNDCARDCHOICE CardTypeToComboItem(SS_CARDTYPE card); diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index 33a1c022..e5f4ef49 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -202,11 +202,11 @@ void MockingboardCard::Get6522IrqDescription(std::string& desc) // EG, to do a "AY1 LATCH", then write 6522 ORB with b4:3=%01, b2:0=%111 // -void MockingboardCard::WriteToORB(BYTE subunit) +void MockingboardCard::WriteToORB(BYTE subunit, BYTE subunitForAY/*=0*/) { BYTE value = m_MBSubUnit[subunit].sy6522.Read(SY6522::rORB); - if ((QueryType() == CT_MockingboardC || QueryType() == CT_Phasor) && // Not CT_MegaAudio + if ((QueryType() == CT_MockingboardC || QueryType() == CT_Phasor) && // Not CT_MegaAudio/CT_SDMusic subunit == 0 && // SC01 only at $Cn00 (not $Cn80) m_MBSubUnit[subunit].sy6522.Read(SY6522::rPCR) == 0xB0) { @@ -246,7 +246,10 @@ void MockingboardCard::WriteToORB(BYTE subunit) } else { - AY8910_Write(subunit, AY8913_DEVICE_A, value); + if (QueryType() == CT_SDMusic) + AY8910_Write(subunitForAY, AY8913_DEVICE_A, value); + else + AY8910_Write(subunit, AY8913_DEVICE_A, value); } #endif } @@ -257,7 +260,7 @@ void MockingboardCard::AY8910_Write(BYTE subunit, BYTE ay, BYTE value) { m_regAccessedFlag = true; MB_SUBUNIT* pMB = &m_MBSubUnit[subunit]; - SY6522& r6522 = pMB->sy6522; + SY6522& r6522 = (QueryType() != CT_SDMusic) ? pMB->sy6522 : m_MBSubUnit[0].sy6522; if ((value & 4) == 0) { @@ -647,8 +650,7 @@ BYTE MockingboardCard::IOReadInternal(WORD PC, WORD nAddr, BYTE bWrite, BYTE nVa #endif // NB. Mockingboard: SSI263.bit7 not readable (TODO: check this with real h/w) - const BYTE offset = nAddr & 0xff; - const BYTE subunit = (offset < SY6522B_Offset) ? SY6522_DEVICE_A : SY6522_DEVICE_B; + const BYTE subunit = QueryType() == CT_SDMusic ? SY6522_DEVICE_A : !(nAddr & 0x80) ? SY6522_DEVICE_A : SY6522_DEVICE_B; const BYTE reg = nAddr & 0xf; return m_MBSubUnit[subunit].sy6522.Read(reg); } @@ -748,15 +750,25 @@ BYTE MockingboardCard::IOWriteInternal(WORD PC, WORD nAddr, BYTE bWrite, BYTE nV return 0; } - const BYTE offset = nAddr & 0xff; - const BYTE subunit = (offset < SY6522B_Offset) ? SY6522_DEVICE_A : SY6522_DEVICE_B; - const BYTE reg = nAddr & 0xf; - m_MBSubUnit[subunit].sy6522.Write(reg, nValue); - if (reg == SY6522::rORB) - WriteToORB(subunit); + if (QueryType() == CT_SDMusic) + { + const BYTE subunit = SY6522_DEVICE_A; // Only one 6522 + const BYTE reg = nAddr & 0xf; + m_MBSubUnit[subunit].sy6522.Write(reg, nValue); + if (reg == SY6522::rORB) + WriteToORB(subunit, !(nAddr & 0x80) ? SY6522_DEVICE_A : SY6522_DEVICE_B); + } + else + { + const BYTE subunit = !(nAddr & 0x80) ? SY6522_DEVICE_A : SY6522_DEVICE_B; + const BYTE reg = nAddr & 0xf; + m_MBSubUnit[subunit].sy6522.Write(reg, nValue); + if (reg == SY6522::rORB) + WriteToORB(subunit); + } #if !DBG_MB_SS_CARD - if (QueryType() == CT_MockingboardC || QueryType() == CT_Phasor) // Not CT_MegaAudio + if (QueryType() == CT_MockingboardC || QueryType() == CT_Phasor) // Not CT_MegaAudio/CT_SDMusic { if (nAddr & 0x40) m_MBSubUnit[1].ssi263.Write(nAddr & 0x7, nValue); // 2nd 6522 is used for 1st speech chip @@ -1164,6 +1176,12 @@ std::string MockingboardCard::GetSnapshotCardNameMegaAudio(void) return name; } +std::string MockingboardCard::GetSnapshotCardNameSDMusic(void) +{ + static const std::string name("SD Music"); + return name; +} + void MockingboardCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper) { if (QueryType() == CT_Phasor) @@ -1174,6 +1192,8 @@ void MockingboardCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper) std::string cardName = GetSnapshotCardName(); if (QueryType() == CT_MegaAudio) cardName = GetSnapshotCardNameMegaAudio(); + else if (QueryType() == CT_SDMusic) + cardName = GetSnapshotCardNameSDMusic(); YamlSaveHelper::Slot slot(yamlSaveHelper, cardName, m_slot, kUNIT_VERSION); diff --git a/source/Mockingboard.h b/source/Mockingboard.h index 23aa1ca0..ac6a26e9 100644 --- a/source/Mockingboard.h +++ b/source/Mockingboard.h @@ -69,6 +69,7 @@ public: static std::string GetSnapshotCardName(void); static std::string GetSnapshotCardNamePhasor(void); static std::string GetSnapshotCardNameMegaAudio(void); + static std::string GetSnapshotCardNameSDMusic(void); private: enum MockingboardUnitState_e { AY_NOP0, AY_NOP1, AY_INACTIVE, AY_READ, AY_NOP4, AY_NOP5, AY_WRITE, AY_LATCH }; @@ -101,7 +102,7 @@ private: } }; - void WriteToORB(BYTE subunit); + void WriteToORB(BYTE subunit, BYTE subunitForAY=0); void AY8910_Write(BYTE subunit, BYTE ay, BYTE value); void UpdateIFRandIRQ(MB_SUBUNIT* pMB, BYTE clr_mask, BYTE set_mask); diff --git a/source/MockingboardCardManager.cpp b/source/MockingboardCardManager.cpp index 7c4741a0..e2e8e899 100644 --- a/source/MockingboardCardManager.cpp +++ b/source/MockingboardCardManager.cpp @@ -42,7 +42,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA bool MockingboardCardManager::IsMockingboard(UINT slot) { SS_CARDTYPE type = GetCardMgr().QuerySlot(slot); - return type == CT_MockingboardC || type == CT_Phasor || type == CT_MegaAudio; + return type == CT_MockingboardC || type == CT_Phasor || type == CT_MegaAudio || type == CT_SDMusic; } void MockingboardCardManager::ReinitializeClock(void) diff --git a/source/MockingboardCardManager.h b/source/MockingboardCardManager.h index 8e6e7681..0b373698 100644 --- a/source/MockingboardCardManager.h +++ b/source/MockingboardCardManager.h @@ -13,6 +13,7 @@ public: m_cyclesThisAudioFrame = 0; m_userVolume = 0; m_outputToRiff = false; + m_enableExtraCardTypes = false; // NB. Cmd line has already been processed LogFileOutput("MBCardMgr::ctor() g_bDisableDirectSound=%d, g_bDisableDirectSoundMockingboard=%d\n", g_bDisableDirectSound, g_bDisableDirectSoundMockingboard); @@ -31,6 +32,8 @@ public: DWORD GetVolume(void); void SetVolume(DWORD volume, DWORD volumeMax); void OutputToRiff(void) { m_outputToRiff = true; } + void SetEnableExtraCardTypes(bool enable) { m_enableExtraCardTypes = enable; } + bool GetEnableExtraCardTypes(void) { return m_enableExtraCardTypes; } void Destroy(void); void Reset(const bool powerCycle) @@ -66,4 +69,5 @@ private: UINT m_cyclesThisAudioFrame; DWORD m_userVolume; // GUI's slide volume bool m_outputToRiff; + bool m_enableExtraCardTypes; }; diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp index 77589c8f..c228e599 100644 --- a/source/Windows/AppleWin.cpp +++ b/source/Windows/AppleWin.cpp @@ -866,6 +866,9 @@ static void RepeatInitialization(void) if (g_cmdLine.bRemoveNoSlotClock) MemRemoveNoSlotClock(); + if (g_cmdLine.supportExtraMBCardTypes) + GetCardMgr().GetMockingboardCardMgr().SetEnableExtraCardTypes(true); + if (g_cmdLine.noDisk2StepperDefer) GetCardMgr().GetDisk2CardMgr().SetStepperDefer(false);