diff --git a/src/gba/GBA.cpp b/src/gba/GBA.cpp index e1d1a0c7..a07a1d22 100644 --- a/src/gba/GBA.cpp +++ b/src/gba/GBA.cpp @@ -3442,7 +3442,7 @@ void CPULoop(int ticks) cpuTotalTicks = 0; // shuffle2: what's the purpose? - if(gba_link_enabled) + if(GetLinkMode() != LINK_DISCONNECTED) cpuNextEvent = 1; cpuBreakLoop = false; @@ -3890,10 +3890,10 @@ void CPULoop(int ticks) ticks -= clockTicks; - if (gba_joybus_enabled) + if(GetLinkMode() == LINK_GAMECUBE_DOLPHIN) JoyBusUpdate(clockTicks); - if (gba_link_enabled) + if(GetLinkMode() != LINK_DISCONNECTED) LinkUpdate(clockTicks); cpuNextEvent = CPUUpdateTicks(); @@ -3911,7 +3911,7 @@ void CPULoop(int ticks) } // shuffle2: what's the purpose? - if(gba_link_enabled) + if(GetLinkMode() != LINK_DISCONNECTED) cpuNextEvent = 1; if(IF && (IME & 1) && armIrqEnable) { diff --git a/src/gba/GBALink.cpp b/src/gba/GBALink.cpp index 4f650fe0..2caa5c5c 100644 --- a/src/gba/GBALink.cpp +++ b/src/gba/GBALink.cpp @@ -22,12 +22,6 @@ const char *MakeInstanceFilename(const char *Input) #ifndef NO_LINK -// Joybus -bool gba_joybus_enabled = false; - -// If disabled, gba core won't call any (non-joybus) link functions -bool gba_link_enabled = false; - #define LOCAL_LINK_NAME "VBA link memory" #define IP_LINK_PORT 5738 @@ -153,6 +147,12 @@ int WaitForSingleObject(sem_t *s, int t) #define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value) +static LinkMode gba_link_mode = LINK_DISCONNECTED; + +LinkMode GetLinkMode() { + return gba_link_mode; +} + int linktime = 0; GBASockClient* dol = NULL; @@ -188,7 +188,6 @@ lclient lc; bool oncewait = false, after = false; // RFU crap (except for numtransfers note...should probably check that out) -bool rfu_enabled = false; u8 rfu_cmd, rfu_qsend, rfu_qrecv; int rfu_state, rfu_polarity, rfu_counter, rfu_masterq; // numtransfers seems to be used interchangeably with linkmem->numtransfers @@ -237,14 +236,14 @@ void StartLink(u16 value) if (ioMem == NULL) return; - if (rfu_enabled) { + if (GetLinkMode() == LINK_RFU_IPC) { UPDATE_REG(COMM_SIOCNT, StartRFU(value)); return; } switch (GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]))) { case MULTIPLAYER: { - bool start = (value & 0x80) && !linkid && !transfer && gba_link_enabled; + bool start = (value & 0x80) && !linkid && !transfer && GetLinkMode() != LINK_DISCONNECTED; u16 si = value & 4; // clear start, seqno, si (RO on slave, start = pulse on master) value &= 0xff4b; @@ -256,7 +255,7 @@ void StartLink(u16 value) value |= READ16LE(&ioMem[COMM_SIOCNT]) & 4; } if (start) { - if (lanlink.active) + if (GetLinkMode() == LINK_CABLE_SOCKET) { if (lanlink.connected) { @@ -362,13 +361,13 @@ void StartGPLink(u16 value) break; case GP: - if (rfu_enabled) + if (GetLinkMode() == LINK_RFU_IPC) rfu_state = RFU_INIT; break; } } -void JoyBusConnect() +static void JoyBusConnect() { delete dol; dol = NULL; @@ -376,7 +375,7 @@ void JoyBusConnect() dol = new GBASockClient(joybusHostAddr); } -void JoyBusShutdown() +static void JoyBusShutdown() { delete dol; dol = NULL; @@ -450,7 +449,7 @@ void LinkUpdate(int ticks) linktime += ticks; - if (rfu_enabled) + if (GetLinkMode() == LINK_RFU_IPC) { rfu_transfer_end -= ticks; if (transfer && rfu_transfer_end <= 0) @@ -466,7 +465,7 @@ void LinkUpdate(int ticks) return; } - if (lanlink.active) + if (GetLinkMode() == LINK_CABLE_SOCKET) { if (lanlink.connected) { @@ -961,8 +960,18 @@ u16 StartRFU(u16 value) // Probably from here down needs to be replaced with SFML goodness :) // tjm: what SFML goodness? SFML for network, yes, but not for IPC -bool InitLink() +bool InitLink(LinkMode mode) { + // Do nothing if we are already connected + if (GetLinkMode() != LINK_DISCONNECTED) { + systemMessage(0, N_("Error, link already connected")); + return false; + } + + if (mode == LINK_GAMECUBE_DOLPHIN) { + JoyBusConnect(); + } + linkid = 0; #if (defined __WIN32__ || defined _WIN32) @@ -1075,6 +1084,10 @@ bool InitLink() } for(i=0;i<4;i++) linkdata[i] = 0xffff; + + // No errors, save the link mode + gba_link_mode = mode; + return true; } @@ -1094,6 +1107,14 @@ static void ReInitLink() } void CloseLink(void){ + if (GetLinkMode() == LINK_DISCONNECTED) { + return; // Nothing to do + } + + if (GetLinkMode() == LINK_GAMECUBE_DOLPHIN) { + JoyBusShutdown(); + } + if(lanlink.connected){ if(linkid){ char outbuffer[4]; @@ -1152,6 +1173,9 @@ void CloseLink(void){ munmap(linkmem, sizeof(LINKDATA)); close(mmf); #endif + + gba_link_mode = LINK_DISCONNECTED; + return; } diff --git a/src/gba/GBALink.h b/src/gba/GBALink.h index c2d7024f..b72789ca 100644 --- a/src/gba/GBALink.h +++ b/src/gba/GBALink.h @@ -3,6 +3,38 @@ #pragma once +/** + * Link modes to be passed to InitLink + */ +enum LinkMode +{ + LINK_DISCONNECTED, + LINK_CABLE_IPC, + LINK_CABLE_SOCKET, + LINK_RFU_IPC, + LINK_GAMECUBE_DOLPHIN +}; + +/** + * Initialize GBA linking + * + * @param mode Device to emulate, plugged to the GBA link port. + * @return success + */ +extern bool InitLink(LinkMode mode); + +/** + * Get the currently enabled link mode + * + * @return link mode + */ +extern LinkMode GetLinkMode(); + +/** + * Set the current link mode to LINK_DISCONNECTED + */ +extern void CloseLink(); + // register definitions; these are always present #define UNSUPPORTED -1 @@ -141,26 +173,17 @@ typedef struct { bool terminate; bool connected; bool speed; - bool active; } LANLINKDATA; -extern bool gba_joybus_enabled; -extern bool gba_link_enabled; - extern sf::IPAddress joybusHostAddr; -extern void JoyBusConnect(); -extern void JoyBusShutdown(); extern void JoyBusUpdate(int ticks); -extern bool InitLink(); -extern void CloseLink(); extern void StartLink(u16); extern void StartGPLink(u16); extern void LinkUpdate(int); extern void CleanLocalLink(); extern LANLINKDATA lanlink; extern int vbaid; -extern bool rfu_enabled; extern int linktimeout; extern lclient lc; extern lserver ls; @@ -169,9 +192,6 @@ extern int linkid; #else // stubs to keep #ifdef's out of mainline -const bool gba_joybus_enabled = false; -const bool gba_link_enabled = false; - inline void JoyBusConnect() { } inline void JoyBusShutdown() { } inline void JoyBusUpdate(int) { } diff --git a/src/wx/cmdevents.cpp b/src/wx/cmdevents.cpp index 90fe5896..e75d6665 100644 --- a/src/wx/cmdevents.cpp +++ b/src/wx/cmdevents.cpp @@ -1159,16 +1159,18 @@ EVT_HANDLER(JoypadAutofireR, "Autofire R (toggle)") EVT_HANDLER_MASK(LanLink, "Start LAN link", CMDEN_LINK_ANY) { #ifndef NO_LINK - if(lanlink.connected) { - // while we could deactivate the command when connected, it is more - // user-friendly to display a message indidcating why - wxLogError(_("LAN link is already active. Disable link mode to disconnect.")); - return; + LinkMode mode = GetLinkMode(); + + if (mode == LINK_CABLE_SOCKET) { + // while we could deactivate the command when connected, it is more + // user-friendly to display a message indidcating why + wxLogError(_("LAN link is already active. Disable link mode to disconnect.")); + return; } - if(rfu_enabled) { - // see above comment - wxLogError(_("RFU is currently only supported in local mode.")); - return; + if (mode == LINK_RFU_IPC || mode == LINK_GAMECUBE_DOLPHIN) { + // see above comment + wxLogError(_("RFU and Joybus are only supported in local mode.")); + return; } wxDialog *dlg = GetXRCDialog("NetLink"); ShowModal(dlg); @@ -2118,33 +2120,29 @@ EVT_HANDLER(JoypadConfigure, "Joypad options...") EVT_HANDLER(LinkConfigure, "Link options...") { #ifndef NO_LINK - bool jb = gba_joybus_enabled; wxString jh = gopts.joybus_host; wxDialog *dlg = GetXRCDialog("LinkConfig"); - if(ShowModal(dlg) != wxID_OK) - return; + if (ShowModal(dlg) != wxID_OK) + return; update_opts(); - if(jb != gba_joybus_enabled) { - if(gba_joybus_enabled) - JoyBusConnect(); - else - JoyBusShutdown(); - } else if(jh != gopts.joybus_host) { - joybusHostAddr = std::string(gopts.joybus_host.mb_str()); - JoyBusConnect(); + + LinkMode oldLinkMode = GetLinkMode(); + LinkMode newLinkMode = getOptionsLinkMode(); + bool dolphinHostChanged = jh != gopts.joybus_host; + + if (newLinkMode != oldLinkMode || dolphinHostChanged) { + joybusHostAddr = std::string(gopts.joybus_host.mb_str()); + CloseLink(); + InitLink(newLinkMode); } - if(gba_link_enabled != did_link_init) { - if(gba_link_enabled) { - if((did_link_init = InitLink())) - cmd_enable |= CMDEN_LINK_ANY; - } else { - did_link_init = false; - CloseLink(); - lanlink.active = false; - cmd_enable &= ~CMDEN_LINK_ANY; - } - enable_menus(); + + cmd_enable &= ~CMDEN_LINK_ANY; + + if (GetLinkMode() != LINK_DISCONNECTED) { + cmd_enable |= CMDEN_LINK_ANY; } + + enable_menus(); #endif } diff --git a/src/wx/guiinit.cpp b/src/wx/guiinit.cpp index b61594fe..d3b841cd 100644 --- a/src/wx/guiinit.cpp +++ b/src/wx/guiinit.cpp @@ -67,6 +67,9 @@ public: return; update_opts(); // save fast flag and client host + // Close any previous link + CloseLink(); + wxString connmsg, pmsg; wxMutex lock; @@ -206,7 +209,10 @@ public: if(lanlink.connected) { pmsg.Replace(wxT("\n"), wxT(" ")); systemScreenMessage(pmsg); - lanlink.active = true; + + // Init link + InitLink(LINK_CABLE_SOCKET); + ev.Skip(); // all OK } } @@ -2227,7 +2233,7 @@ bool MainFrame::InitMore(void) // so just set individual flags here cmd_enable = CMDEN_NGDB_ANY | CMDEN_NREC_ANY; update_state_ts(true); - enable_menus(); + // set pointers for checkable menu items // and set initial checked status if(checkable_mi.size()) { @@ -3072,14 +3078,14 @@ bool MainFrame::InitMore(void) #ifndef NO_LINK LoadXRCDialog("LinkConfig"); { - getcbbe("Joybus", gba_joybus_enabled); + getcbbe("Joybus", gopts.gba_joybus_enabled); getlab("JoybusHostLab"); addbe(lab); gettc("JoybusHost", gopts.joybus_host); tc->SetValidator(IPHostValidator(&gopts.joybus_host)); addbe(tc); - getcbbe("Link", gba_link_enabled); - getcbb("RFU", rfu_enabled); + getcbbe("Link", gopts.gba_link_enabled); + getcbb("RFU", gopts.rfu_enabled); addbe(cb); getlab("LinkTimeoutLab"); addbe(lab); @@ -3205,23 +3211,31 @@ bool MainFrame::InitMore(void) panel->ShowFullScreen(true); #ifndef NO_LINK - if(gba_joybus_enabled) { - bool isv = !gopts.joybus_host.empty(); - if(isv) { - joybusHostAddr = std::string(gopts.joybus_host.mb_str()); - isv = joybusHostAddr.IsValid(); - } - if(!isv) { - wxLogError(_("JoyBus host invalid; disabling")); - gba_joybus_enabled = false; - } else - JoyBusConnect(); - } - if(gba_link_enabled) - if((did_link_init = InitLink())) - cmd_enable |= CMDEN_LINK_ANY; + LinkMode linkMode = getOptionsLinkMode(); + if (linkMode == LINK_GAMECUBE_DOLPHIN) { + bool isv = !gopts.joybus_host.empty(); + if(isv) { + joybusHostAddr = std::string(gopts.joybus_host.mb_str()); + isv = joybusHostAddr.IsValid(); + } + + if(!isv) { + wxLogError(_("JoyBus host invalid; disabling")); + gopts.gba_joybus_enabled = false; + } else { + linkMode = LINK_DISCONNECTED; + } + } + + InitLink(linkMode); + + if (GetLinkMode() != LINK_DISCONNECTED) + cmd_enable |= CMDEN_LINK_ANY; #endif + + enable_menus(); + panel->SetFrameTitle(); // All OK; activate idle loop diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index e4b1b113..33f5a7f0 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -391,12 +391,11 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser &cl) return true; } -MainFrame::MainFrame() : wxFrame(), did_link_init(false), focused(false), +MainFrame::MainFrame() : wxFrame(), focused(false), paused(false), menus_opened(0), dialog_opened(0) {} MainFrame::~MainFrame() { - if(did_link_init) CloseLink(); } @@ -642,6 +641,18 @@ void MainFrame::StopModal() panel->Resume(); } +LinkMode MainFrame::getOptionsLinkMode() { + if (gopts.gba_joybus_enabled) { + return LINK_GAMECUBE_DOLPHIN; + } else if (gopts.rfu_enabled) { + return LINK_RFU_IPC; + } else if (gopts.gba_link_enabled) { + return LINK_CABLE_IPC; + } + + return LINK_DISCONNECTED; +} + // global event filter // apparently required for win32; just setting accel table still misses // a few keys (e.g. only ctrl-x works for exit, but not esc & ctrl-q; diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index f6404e20..d3477c44 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -205,7 +205,6 @@ public: // required for event handling DECLARE_EVENT_TABLE(); private: - bool did_link_init; GameArea *panel; // the various reasons the game might be paused @@ -244,6 +243,8 @@ private: void OnDropFile(wxDropFilesEvent&); // pop up menu in fullscreen mode void OnMenu(wxContextMenuEvent &); + // Returns the link mode to set according to the options + LinkMode getOptionsLinkMode(); #include "cmdhandlers.h" };