NFC enabled EmulationStation
-
Hi!
For my custom SNES mini (https://www.thingiverse.com/thing:2492366) I was looking for a way to read and write NFC tags on the Raspberry Pi in order to emulate a cartridge slot.
I saw some solutions to this problem, for example a python script that kills EmulationStation and starts the game. I didn't like that solution and I wanted to be able to do everything inside EmulationStation.
So what I did was modifying EmulationStation by adding libnfc for handling the NFC stuff and pigpiod for reading the GPIOs of the Pi.
The code is very basic for now. I'm going to rework parts of it and make the integration a little bit nicer. But it is working! I tested it with MIFARE Ultralight C tags inside SNES cartridges with no problem. I to a NFC tag reader and hooked it up via I2C to the Pi. By pressing the reset switch on my "SNES" (in this case GPIO 20) for over 3 seconds it will write the game that you have selected in EmulationStation to the tag. It will write the filename and the system. For now only NES, SNES, GB, GBC, GBA and GENESIS are supported, but that can be easily changed. If you push the button under 3 seconds it will read the data from the NFC tag and start the game.
I was planning to use the NDEF format to save the data on the NFC tag but that was more complicated than I thought so I instead write the data directly into the tag. Works without any problems, but the downside is that you are only able to read and write tags inside EmulationStation.
The only problems I have right now are:
Reading and writing are not that fast. It will take several seconds until a game is started.Was able to speed up the read process quite a bit. Writing still takes some time.No notification when we are done with writing to the tag.Added a notification when the write process is complete!There is an odd bug. Everytime I start a game with an NFC tag this particular game will disappear from the Favorites menu. After a restart the game will appear again. Anybody have an idea what is going on?Fixed! Thanks pjft!
Link to the repository: https://github.com/ElBartoME/EmulationStation/
Feedback would be welcome!
In action:
-
This is a really cool setup you have there, and the NFC read/write looks spot on. I wonder, without having read the code, what are you calling to launch the game and why would it disappear from the favorites menu.
What does the button in your case actually invoke? I see that if you hold it it writes, and if you press it it reads the game?
-
Thanks!
I do everything in the main.cpp of es-app because I'm lazy. I check if the button hold time was long or short. If it is short (< 4 s) then I will read the tag. If long, I will get the selected game info and write it into the tag. The tag has filename and system information of the game.
I then create a string with the filepath of the game and search for the system. Then I'll start the game through the ViewController.
std::string path = "/home/pi/RetroPie/roms/" + temp.gametype + "/" + temp.filename; boost::filesystem::path filepath{path.c_str()}; std::vector<SystemData*> Systems = SystemData::sSystemVector; for(auto i = Systems.begin(); i != Systems.end(); i++) { if((*i)->getName() == temp.gametype) { FileData *game = new FileData(GAME, filepath.generic_string(),(*i)->getSystemEnvData(),(*i)); ViewController::get()->launch(game); } }
Somehow this code is responsible for temporarily removing entries out of the favorites menu...but why?
P.S.: I know creating the string with a fixed path is not a good idea. But I'm not sure where the default rom folder is stored in EmulationStation. Anybody got an idea?
-
@elbartome yeah. I'm pretty sure I can help with this. Maybe when I'm on my laptop on Monday, would that work?
Basically the fact that you're creating a new file data means that you're not using the current one that exists. As such it may be that it may replace the existing one in the favorites when you update its play count as there can only be one file data per path in ES.
If you're using collections, you can get the right file data by accessing the all games collection using the path as key.
Let me know if this helps or if you need more specifics, but that's my gut feeling. I can look into the code on Monday or so.
-
Sorry, just noticed I had left this waiting for a while now.
So, you have two options there.
Probably the easiest one for you, in this case, is after finding the right system, to get the in-memory FileData games in the system by running
const std::unordered_map<std::string, FileData*>& children = (*i)->getRootFolder()->getChildrenByFilename()
and then, depending on how they're keyed (I don't know off the top of my head) you can either iterate on them and compare the file name until you find the one that matches, and then use that to launch the game, or ideally you'd be able to access it by key:
bool found = children.find(temp.filename) != children.end(); if (found) { FileData* game = children.at(temp.filename); ViewController::get()->launch(game); }
but I'm not sure if the key is the filename only, or if it has the longer path.
Might be worth trying it or even logging the keys as you iterate, just to see what to expect.
Best.
-
@pjft
Thank you very much! Unfortunately work is keeping me busy and I wasn't able to modify the code.I will probably try that this weekend and get back to you if it works. I can step through the code and look at the keys!
Is going trough every game not going to cost a lot of time? Especially if you have 500+ games in one system.
-
@elbartome It shouldn't take that long, really. It's not ideal in concept, but it's not the end of the world.
-
@pjft
Thank you very much for your help. I never would have been able to figure that out!It works perfectly with your suggested changes! I will push the update to git after some cleanup in the code.
-
@elbartome Glad to hear! Out of curiosity, what was the solution you ended up pursuing?
I'm curious about what causes the delay in reading the cartridge and starting the game - is it the reading part, or is it actually launching the game in ES?
Either way, well done - and thanks for sharing!
-
@pjft I used the filename as a key. Works flawlessly. It is more or less your code 1:1.
The delay is caused by the NFC routines. I was able to shrink it down to about 5 seconds. I don't think I can go down much more, but I will look into the NFC routines when I have more time.
Launching the game in ES is really quick!
-
This might be cool with a coin door as well. Toss in a (round) NFC tag and attach a NFC reader inside... Like this!
-
@ElBartoME could you helpme to do the same with snes classic mini console with hakchi mod installed?
-
@esbat1 I don't think this is the right forum for your issue. The original poster hasn't been here in over 5 years, so I don't think you'll get an answer. Maybe try Reddit's forum for hakchi / snesmini mods ?
-
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.