Qt: Add Net Gate Functionality & Fix Chip Gate for non-JP versions of Battle Network 6#3568
Qt: Add Net Gate Functionality & Fix Chip Gate for non-JP versions of Battle Network 6#3568DeCoded-Void wants to merge 4 commits intomgba-emu:masterfrom
Conversation
- Edited via QT Creator - Added an additional vertical separator for the "Net Gate" section in "show advanced" - "Inserted" was renamed to "Keep Inserted" to reflect new behavior - By default, address and port strings are 127.0.0.1 and 2000 - Tooltips were added in gate options in Gate Type and Enable Net Gate checkbox There may be some enum conflicts as a result of using a later version of qt, some affected enums were modified to work with the current branch of mGBA.
- Utilizes GBA memory to identify game version by using bytes from the ROM header - Something in "qtitle" seems to have broken from 10.5 --> 11.0, I left a statement there which may correct it if there is preference for that instead. Since there isn't a member in QString for ASCII, fromLatin1 was used instead. - As a result of the "qtitle" issue, the current master branch does not autoselect the gate and has caused the US version of MMBN6 to not work with the chip gate as a result of the chip gate providing the incorrect chip gate identifier to that version. - Added behavior that allows for the chip name spinner to update when the Chip ID is changed - Insertion behavior was modified since Battle Chips with the Chip Gate is intended to be hotswapped rather than being kept inserted. - In order to prevent the issue where swapped chips are not read while "Inserted" is checked, there is a momentary un-insert of the chip before the new chip is inserted and held. - For the Net Gate functionality, the accepted bytes are for parity with shonumi/gbe-plus#87, The 0x80 byte is there as the starting byte for that. It is also used in mGBA to decide to accept the buffer or not.
- Added "onChipIdChanged", used to update the Chip Name spinner when Chip ID is manually changed - Added Net Gate state (no persistence; initialized from UI at runtime) - Default IP and Port is used from the UI file so it wasn't asserted in the header, it may be a good idea to have it here instead
|
Please back out the "qtitle" fix. It was a trivial one line fix when done properly, so instead of complicating the review process I just went ahead and did it myself. I can review this properly afterwards. |
|
any chance of getting the build ? for the live of me cant seam to build it myself |
|
I'm still waiting on them backing out the change I asked for 6 months ago before I can review the rest of it. |
|
Any tips for idiots try building mgba ? I tried to build his forked version with the net gate changes, but docker dont work because you cant get wsl to update and building with MSYS2 worked but the resulted mgba.exe with all dll's in the folder just wont start. |
Somehow didn't get the notif for the incoming change conflict resolution from the fork until the pr got a new comment. @Rotockter Used the w64 docker image with wsl2 backend, you may need to enable virtualization in the bios. @endrift Adding this info in case it results in breaking changes or requires further research as a separate issue, it was work done after this pr: Ended up getting a PIO (Programable In Out) implementation working on a physical GBA to have a rp2040 microcontroller to act as the chip gate. The GBA's clock and SO pin helped with framing as well as serve as interrupt triggers on the microcontroller's end. The weird values that seem to increment and decrement surprisingly helped with making sure I was reading the data correctly. There would be phantom disconnects in BN6 requiring a reset in the emu. BN6 was the only game I have seen where it would respond with the "resync command" directly after confirmation (8FFF), where the game will ease its way into the indefinite communication loop. The state machine could break at this point but it'll fix itself once a resync is forced (in this case, passing the title screen and triggering a battle). This behavior doesn't seem to be present for my BN4 and BN5 copies. The games seem to also have no problem with being probed with different Chip Gate IDs until the game sees the one it likes. For the microcontroller implementation, I'd test each flavor 5 times indefinitely until we get the 8FFF response where the MCU will remember the previous accepted flavor so it will attempt to use it as the first flavor the next time the GBA triggers the communication again. It's a workaround, but the results were consistent when it came to handling BN6 US and JP versions on real hardware, so the user doesn't have to do any sort of manual intervention and it seems instantaneous because this all happens before the title screen fully fades in. |
|
I cant update wsl it always fails and internet dont give me any solution for that. so cant use docker. cant you upload one of ya test builds of the fork ? kinda got interrested in this through a youtube short seeing first time the battle gate. currently i got mgba running in gamenative on android with your 2022 lua code that seam to only be for BN 4-5. Sending the 3 byte code from my pc worked on my ayn thor running Battle Network 4.5 through gamenative with the script. Its only realy convoluted to set everytime with: "open mgba, run BN4.5, open battle gate, restart bn4.5, open script window, find and load script, go fullscreen" i wonder if you can autostart battle gate in the background. sadly the script net gate wont work without opening battel gate window. goal is to make one of my micro controllers (esp32 etc) read out battle chips and sent to my any thor. struggeling with getting a connector working for the battle chips pcb contacts. buying edge connector didnt helped. now tinkering with 3d printing and paper clips. |
|
The lua script is not a proper implementation because of it being made with the per frame limitation in that script. Communication with the accessory can't be done in a per frame basis with scripting alone, so the window is necessary to keep the emulated connection alive. The lua script just edits the "end result" per frame rather than simulate the actual peripheral interaction itself. The current PR here was intended keeping things as high level as possible (in this case, mgba qt/gui) for accessibility since the lower level implementation is not feature complete, but already handles most of the time-sensitive related communication (assuming additional work in the future is going to be done to expand it for multiplayer capabilities, additional scripting abilities, etc.) That does consequently mean that mGBA would still require its chip gate gui to remain open if you'd want to interface with it using an external/middleman program with this. A dirty build was made based off of the fork to test its viability near the time of the pr for devs and hobbists working on chip gate related ideas to test, but it's unstable (leading to manual patching or workaround fixes, handling breaking changes to scripting API, etc.) Haven't recompiled it since then. For chip gate related projects in the way you describe, gbe+ is recommended for the time being. Although the "netgate" isn't really a set standard, hobbyists and collectors that do their own ways to do chip insertions from existing projects were able to get them working in the dirty build and gbe+ within a few minutes including:
You can use pogo pins or these instead of paperclips if you want to use a microcontroller to read chips since they lower the risk of damaging chip pins. |
|
seams like mgba 0.10.5 in software render mode and your script are the only things that run in windows emulation on the android ayn thor. I would like to use gbe+ but that does run extreamly slow in windows emulation(1 frame per 20 sec). my paperclip solution as pins works so far, but the connection seam not to be fool proof and sometimes pins dont connect even then touching the contacts, like old gba cartridges into gameboy fails. |
|
Yes, for the most part, a lot of undocumented information of the battlechips is discussed and collaborated on in the MegaMan Battle Network Collectors community discord: https://discord.gg/Wa98sZza4g There are members that have worked on or are currently working on battlechip related projects (chip reproduction, chip gate accessory research, disassembled chip gate board pics, code snippets, pcb schematics, etc.) so they can point you to someone or an existing message on there that may be able to answer some of the niche questions surrounding them. Connectors were one of the hurdles for diy related projects, the ones used for the original accessory weren't the best quality leading to some collectors requiring to disassemble and bending connectors back on them. There is a worry about connectors scratching pins on the chips because of how scalped the original chips are. @zarcha has a pogo pin implementation of the connector and is using an arduino nano: @BlaXun has worked on an NFC implementation to substitute for chip reading The 6 position spring contact connector linked above is what I currently use because of board assembly costs as a limitation. Using this for the implementation described in the pr with a few prototypes that can be used on that and physical hardware: Interlinking some publicly available info/documentation around this that can be helpful for contributors here, since search engines are getting more unreliable lately:
|
endrift
left a comment
There was a problem hiding this comment.
My concerns with this implementation are largely stylistic. Please adhere to existing style throughout and don't change nearby style either.
One major change I'd like is that the actual server logic should be pulled out into C code that's usable across implementations and operates directly on GBASIOBattlechipGate instances. The UI will need to synchronize with it, but it would let this be used with other frontends if we want to add that. mGBA already includes TCP server code, so you can see how to do it in gdb-stub.c. It will complicate the integration, but it's more forward-thinking in the process. I'm actually not sure it makes sense to allow both the view and a server to both be operating on the chip deck at the same time, so we might want to make it just disable the controls while it's operating.
There are also changes that were made here for reasons that aren't obvious to me, so please elaborate on why those were changed.
As for the Qt Designer changes I'm asking you to revert, I know you didn't do those manually; the Qt 6 version of Designer does them automatically. However, I'm maintaining the older Qt 5 style for now since it works with Qt 6 already and allows it to compile with older versions of Qt 5 as well.
| #include "GBAApp.h" | ||
| #include "ShortcutController.h" | ||
| #include "Window.h" | ||
| #include <mgba/internal/gba/gba.h> |
There was a problem hiding this comment.
Should be a blank line between the C++ header and the C header include blocks
| #include <QSettings> | ||
| #include <QStringList> | ||
|
|
||
| #include <QTcpServer> |
There was a problem hiding this comment.
This should be merged and sorted into the include block above.
| if (id < 0) { | ||
| return; | ||
| connect(m_ui.chipName, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this](int idx) { | ||
| if (idx < 0) return; |
There was a problem hiding this comment.
Please follow the existing style guide--no single line blocks.
| if (idx < 0) return; | ||
| const auto keys = m_model.chipNames().keys(); | ||
| if (idx >= 0 && idx < keys.size()) { | ||
| bool blocked = m_ui.chipId->blockSignals(true); | ||
| m_ui.chipId->setValue(keys[idx]); | ||
| m_ui.chipId->blockSignals(blocked); |
There was a problem hiding this comment.
This can be simplified:
| if (idx < 0) return; | |
| const auto keys = m_model.chipNames().keys(); | |
| if (idx >= 0 && idx < keys.size()) { | |
| bool blocked = m_ui.chipId->blockSignals(true); | |
| m_ui.chipId->setValue(keys[idx]); | |
| m_ui.chipId->blockSignals(blocked); | |
| auto keys = m_model.chipNames().keys(); | |
| if (idx < 0 || idx >= keys.size()) { | |
| return; | |
| } | |
| QSignalBlocker blocker(m_ui.chipId); | |
| m_ui.chipId->setValue(keys[idx]); |
Though if I may ask, why are we blocking signals here now?
| connect(m_ui.chipId, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &BattleChipView::onChipIdChanged); | ||
| connect(m_ui.insert, &QAbstractButton::clicked, this, &BattleChipView::reinsert); | ||
| connect(m_ui.add, &QAbstractButton::clicked, this, &BattleChipView::addChip); | ||
| connect(m_ui.remove, &QAbstractButton::clicked, this, &BattleChipView::removeChip); | ||
| connect(m_ui.save, &QAbstractButton::clicked, this, &BattleChipView::saveDeck); | ||
| connect(m_ui.load, &QAbstractButton::clicked, this, &BattleChipView::loadDeck); |
There was a problem hiding this comment.
Please follow existing convention. Do not do inline alignment, and especially don't change existing code just to match a convention you added.
| <property name="toolTip"> | ||
| <string><html><head/><body><p><span style=" font-weight:700;">Beast Link Gate</span></p><p>Usable with <span style=" font-style:italic;">Rockman EXE 6</span>, including support for <span style=" font-style:italic;">Mega Man Battle Network 6</span>.</p></body></html></string> | ||
| </property> |
| <property name="toolTip"> | ||
| <string><p><b>Net Gate</b> - Sends Battle Chip data to mGBA over TCP.</p> <p>It can be used with an external service/app that opens a TCP socket to submit Chip IDs.</p> <p style="margin:0"><b>Protocol (3 bytes)</b>:</p><span style="font-family:'Courier New';"><ol style="margin:0; padding-left:1.2em"> <li><tt>0x80</tt></li> <li><tt>CHIP_ID_HI</tt></li> <li><tt>CHIP_ID_LO</tt></li> </ol></span></string> | ||
| </property> |
| <number>5</number> | ||
| </property> | ||
| <property name="placeholderText"> | ||
| <string>1-65535</string> |
There was a problem hiding this comment.
| <string>1-65535</string> | |
| <string>1 – 65535</string> |
| <property name="placeholderText"> | ||
| <string>e.g., 127.0.0.1</string> | ||
| </property> |
There was a problem hiding this comment.
Unsure a placeholder is useful here when there's already a default.
| <set>QDialogButtonBox::Close|QDialogButtonBox::Reset</set> | ||
| <set>QDialogButtonBox::StandardButton::Close|QDialogButtonBox::StandardButton::Reset</set> |
|
It also seems to have merge conflicts, so please rebase it and fix those. |
|
A lot of kludges on my end. Some of the rationale behind some of it is handling potential user misconfiguration (ex: user blanking out defaults without changing them before attempting to start the qt server) and trying to handle certain quirks in the game like where if the chipId is immediately switched in the state machine, the game could ignore that insert. Going to be refactoring according to the style guide and suggestions and to make sure my interpretation is correct. I definitely do want it to work so users will still be able to use mgba's current chip gate gui, while also being able to use multiple clients at the same time (ex: being able to remotely send chips while the user also locally is able to do it themselves). A potential issue may pop up is with overfeeding data and handling how and what to prioritize on the network end of things. |
|
If you want to allow multiple different sources of inputs it sounds like all the more reason to have a central object for coordinating the state that multiple things can plug into and synchronize with. FYI, I might not merge anything for 0.11 as I'm winding down, depending on how much of a change this is, but I am interested in pulling it into 0.12 once it's cleaned up |




This allows developers to create apps to easily interface with mGBA via TCP to insert chips in the chip gate.
Potential applications include: creating a wireless reader that reads real battlechips, using NFC tags to substitute as battle chips, phone/web app to use for chip selection, livestream chat to control inserted chips, etc.
Tested on Windows 11 64-bit with the windows:w64 build.