|Home | Downloads | Screenshots | Forums | Source code | RSS | Donate|
|Register | Log in|
melonDS aims at providing fast and accurate Nintendo DS emulation. While it is still a work in progress, it has a pretty solid set of features:
• Nearly complete core (CPU, video, audio, ...)
• JIT recompiler for fast emulation
• OpenGL renderer, 3D upscaling
• RTC, microphone, lid close/open
• Joystick support
• Various display position/sizing/rotation modes
• (WIP) Wifi: local multiplayer, online connectivity
• (WIP) DSi emulation
• (WIP) GBA slot add-ons
• and more are planned!
If you're running into trouble: Howto/FAQ
The netplay saga, ep 2
Mar 27th 2023, by Arisotura
I've been building the basic network infrastructure for netplay lately. Oh, the fun that is dealing with synchronization.
If you remember the graph from the previous post:
Implementing this proves to be tricky, because since each individual instance there is its own process, there's a lot of moving parts. So first, we're going to name them.
Assuming player 1 is the player who initiated the game: player 1's instance 1 acts as the game host, while player 2's instance 2 and player 3's instance 3 act as game clients. The game host transmits useful information to the game clients, tells them when to start running, ...
Then player 1's instance 1 acts as a mirror host: players 2 and 3's instance 1, the mirror clients, connect to it, and receive their input from it, thus mirroring player 1's input on players 2 and 3's machines. Similarly, player 2's instance 2 and player 3's instance 3 are also mirror hosts.
As is typical with netplay implementations, inputs are delayed by a fixed amount, which is hardcoded to 4 frames in the current test branch, but will be configurable in the final product. The basic idea is to delay inputs a bit on all sides to counter network lag.
Each input frame sent by a mirror host is given a frame count, which lets mirror clients make sure to apply that frame at the exact same time as their host, thus ensuring all sides are given the exact same inputs. If a mirror client runs out of input frames (because the mirror host is running slower), it will need to block until it receives input frames -- missing an input frame would cause a desync.
During a local multiplayer game, this has shown to be enough to form a somewhat viable netplay implementation: this crude synchronization mechanism, combined with local multiplayer sync, do a good job at keeping all instances in sync. But when the players aren't engaging in a local multiplayer game yet, there is the possibility that mirror clients run too slow and end up lagging behind an awful lot.
... read more
|13 comments (last by Jawlshy) | Post a comment|
The local multiplayer saga, season 2: Netplay
Mar 24th 2023, by Arisotura
As the apartment shito is beginning to settle down, I have been able to start working on this.
My first goal was to fix the two annoying issues I described in the previous post. In this situation, I was trying to get the pause command to simultaneously pause all local melonDS instances, instead of just the one that received the command. There is more to be done in the way of cross-instance sync, but this seemed an obvious starting point to me.
The first issue was due to the way the interface works. Originally, the only way to pause melonDS was through the interface (System->Pause). Later on, the pause hotkey was added. Hotkeys are checked and handled in the emu thread (separate from the UI thread), so to keep things simple, the pause hotkey would just send a signal to the main window which would behave like using the System->Pause menu command. It's a bit of a roundabout way to handle this, but it has the advantages that it avoids duplicating code too much, and keeps the UI state (the Pause checkmark) in sync without having to worry about it.
When I started adding cross-instance pause, I made the pause command handler send a message to other melonDS instances through IPC. Then the other instances would receive that message and treat it the same as pressing the pause hotkey. Easy peasy.
Yeah, except doing so would cause these instances to send more pause messages, essentially entering a feedback loop.
So I had to add a separate handler for the IPC pause command to avoid this. Not the best solution, but it works.
Next problem was that during a local multiplayer game, cross-instance pause would interfere with the local multiplayer sync system, and could essentially cause some instances to get stuck. To deal with this, I had to add some more intelligence to the IPC comm layer to avoid waiting on instances that are paused. And it does the trick. Pausing a local multiplayer game may cause minor packet loss, due to the way this works, but I haven't seen any problems in my testing -- Nintendo's local multiplayer protocol is resilient, so this should be mostly fine.
There is more state that should be shared across melonDS instances, like the recent ROM menu. We'll get there. Now that the system is in place for cross-instance comm, it shouldn't be very difficult.
But for now, I want to build the base for netplay. So let's talk about this.
... read more
|8 comments (last by Este) | Post a comment|
Mar 8th 2023, by Arisotura
Not a lot to report melonDS wise. I'm running into problems with my cross-instance sync design, the kind of issues that are very annoying to solve, so... yeah.
Real life wise, I have finished the diagnosis process, so I'm now diagnosed with ADHD. I'm also able to get medicated for this; we'll have to see how this goes, but so far it's been a night and day difference for me. It's much easier for me to get myself to start tasks and stick to them. I'm impressed at how productive I have been at work these days. And so far I'm not seeing any adverse effects.
I hope this improvement can also help me getting things done for melonDS or my other personal projects, but right now it's a tad complicated. I'm moving to a new, better apartment, and while this is a great thing, it also means that there are a lot of things to take care of still, and that tends to be energy consuming for me.
But hopefully, by the end of March this should all settle down and allow me to take a big sigh of relief. In the meantime I'm trying to think of how to address the problems I'm facing regarding melonDS. Netplay is really something I want to get going.
|12 comments (last by Brandon) | Post a comment|
Jan 30th 2023, by Arisotura
Yeah, we haven't been doing a whole lot for melonDS these days. General winter laziness, I guess.
On my side, that certainly didn't help. I've been taking a new antidepressant, and the first month has been rough. Generally, feeling tired and lethargic, but also having to deal with insomnia, side effects from sleeping pills... you get the picture.
The side effects have largely subsided now, I'm able to sleep without having to take anything, I'm more energetic in general, and feeling good. I have had bad experiences with antidepressants in the past, so I'm glad that this one is working.
Now I'm looking forward to my ADHD diagnosis appointment, which will be next week. Hopefully they can help me there, it sure would be nice if I didn't take forever to motivate myself to do things (including, but not limited to, working on melonDS).
In the meantime, what I'm currently laying out is a base for proper communication between melonDS instances. For example, pausing all instances simultaneously, starting new instances with the right game pre-loaded, and so on. This is going to be a must for netplay.
|22 comments (last by Retropie) | Post a comment|
Lil' site updates
Dec 13th 2022, by Arisotura
Not much to say these times... after the big 0.9.5 release, I've mostly been taking a big break, and thinking of how to properly lay the base for netplay. I've also had a pretty rough time in November, but I feel much better and hopeful now.
Anyway, little update to this site. I changed the way IP bans work: they no longer block you from the entire site, instead they will just restrict your ability to post comments.
I will likely also do some other updates and cleanup related to this, too. So let me know if anything is broken or if you're erroneously banned from somewhere.
|17 comments (last by Jason Mansker) | Post a comment|
melonDS 0.9.5 is out!
Nov 3rd 2022, by Arisotura
First of all, a bit of a special announcement.
As of today, the melonDS project is 6 years old. For this occasion, we present you this special version of the melonDS logo, recolored to the same pretty sky-blue color as 6 itself:
We wanted to have Peach bake a cake shaped like this, but Bowser kidnapped her again. We aren't great bakers at the melonDS HQ, so... yeah.
Regardless, these 6 years are a great success. Back in 2016, when I started working on melonDS, I was mostly just making it to have fun and pass time until my job started. I had absolutely no idea the project would go on for so long, and be as much of a success as it has been. So, first of all, I want to thank all the comrades who have helped make this possible. The melonDS team and other contributors. nocash and his great documentation. Everybody else who has been involved in reverse-engineering the DS/DSi hardware, cracking the DSi security, etc... And of course, everybody who has been using melonDS, testing games in it, reporting issues, suggesting improvements, etc...
Thank you all. melonDS is a team effort, and you deserve your part of the birthday cake.
And, of course, the birthday present. There's only one, but it's a big one. We bring you melonDS 0.9.5, and if you've been following the blog lately, you know it's going to be big.
... read more
|69 comments (last by Alexa) | Post a comment|
Having 'fun' with the DSP
Oct 14th 2022, by Arisotura
DSi support in melonDS has been getting to a pretty good state lately. Basically, the only remaining 'big' thing to deal with is DSP support. The rest is mostly bugfixes, implementing misc features (hi, power button), etc, you get the idea. Plus, an aging cart for the DSi has been discovered, which will help implement and test the DSi features more thoroughly than commercial games do. And then there are the various quality-of-life improvements that come to mind, like not requiring BIOS/firmware/NAND dumps...
Anyway, the DSP.
The thing I have always kept pushing back, and for two good reasons. First, the DSP instruction set and encoding is a mess, and the documentation on it is lackluster. Second, there's hardly anything on the DSi that uses the DSP. The DSi sound app, and a few other DSi titles, and that's it. Everything else sticks to the old DS sound mixer.
But what we have going for us is that the 3DS uses the same DSP, and it is much more popular there with every game using it, so the 3DS scene has already been dealing with it. Namely, we have teakra, which is a fairly reliable DSP interpreter and disassembler.
PoroCYon had integrated teakra into melonDS in an attempt at bringing DSP emulation. It didn't work, but it was atleast a pretty good base. I had tried quickly fixing a couple bugs in it, with no real success. I wasn't really looking forward to having to debug DSP code, either, to be honest.
Lately, I felt like looking into it again.
I launched the DSi sound app, and was sidetracked by another, unrelated bug: the sound app crashes when starting due to a bad memory access. It went unnoticed before because we didn't emulate data aborts, but now, we do, and we can't go back on that.
So I researched that bug. It's a timing issue.
The crash happens when trying to dereference a particular pointer, because it is NULL. During startup, the main thread will allocate some memory, then run a bunch of initialization, then initialize that pointer. During the initialization, it sends an IPC request to the ARM7 to determine whether headphones are connected. While it waits for the ARM7 to respond, another thread runs, which does some other initialization, sends other IPC requests to the ARM7 (to get the date/time and battery status), then tries to do things with the aforementioned pointer, which is expected to have been initialized by now.
... read more
|13 comments (last by hoangson2007) | Post a comment|
Oct 2nd 2022, by Arisotura
We're in the process of getting melonDS ready for a 0.9.5 release. That means, while Generic is working on fixing up OpenGL rendering on desktop, I'm free to go and finish some other fun things.
First, local_wifi has been deemed close enough to completion, and has been merged.
I added some tidbits of wifi emulation (for example, the Inazuma Eleven games use WEP during local multiplayer, so I had to implement enough of that to make them work), but most notably, I worked on the UI side of this feature. No more opening melonDS instances from different folders, MAC randomization, and other awkward workarounds. Now melonDS is able to detect when coexisting with other melonDS instances, and makes sure to save things like user settings, save file, etc, to separate files. For example, that makes it possible to configure each instance to use its own joystick.
It is probably still not perfect, but it's certainly a start. I also want to hear some user feedback on all this.
Regarding local multiplayer, the BSD socket interface is going byebye. This means it's no longer possible to play over LAN (not that it has ever really worked). But we plan to implement netplay for melonDS 1.0, so that will make up for it. It should even work better, in that the connection will be more reliable, but due to having to emulate all the participating consoles on every user's computer, it will be more demanding (although testing has shown that any decent computer can handle atleast two melonDS instances at fullspeed).
Next, I finished the work on camera_betterer, and merged it too.
Basically it was only matter of finishing up the UI side of things, adapting the Qt camera code for Qt6, and fixing up some tidbits (like camera image formats -- most cameras should be able to provide YUYV image data, but Mac cameras can only provide NV12).
... read more
|41 comments (last by a.nak) | Post a comment|
The local multiplayer saga, ep 10
Sep 8th 2022, by Arisotura
This tenth episode is going to close the first season of this saga. At this point, local multiplayer has been tested and found to be smooth in most cases, so we are mostly done with the actual wifi work.
We have also been porting our semaphore code so that our shared-memory based communication layer could work under Linux and macOS. This has shown to be a bit challenging, and I've been making several attempts to try and determine what was the best method for fast and reliable IPC.
What is left is mostly UI-related work. Handling several situations that can be problematic during multiplayer: supporting multiple controllers, maybe also things like multiple firmware settings, making sure the multiple running games don't write to the same save file, firmware file, and so on. I have a few ideas for that.
That will help turn local multiplayer support into a more finished product and less of a clunky experimental thing.
But for now, I'm going to take a break. I've been pouring a lot of my free time into this, and I think I need to relax for a lil' while.
I'm also going to debate the direction to take now with the rest of the melonDS team. There will be a second season to this saga, and it will be about implementing netplay. The results of all this wifi work are well beyond my original expectations, and now we have big ideas and hopes for this. But first, I want to take a collective decision about whether to make a release before season 2, whether to go straight for melonDS 1.0, these things. Stable local multiplayer was one of the must-haves for melonDS 1.0, but that's not all there is.
I'm also collecting ideas for netplay, so if you know more about this than I do (which is, relatively little), feel free to reach out to me!
|28 comments (last by Noah.Cfgeek) | Post a comment|
The local multiplayer saga, ep 9
Aug 28th 2022, by Arisotura
In the previous post I said the slowdown problems in multiplayer games were fixed, but actually, they weren't. Oops.
I looked deeper into the issue. I couldn't let that slip. But I also didn't really have an idea what could be causing it or where to begin looking.
I thought about bit0 in USCOMPARE, again. Basically, when they're connected to a host and receiving beacons from it, games do that weird little dance where they take the beacon's timestamp value, add some offset to it, and write that to USCOMPARE, with bit0 set.
A bit of background. In the DS wifi module, there are two ways of triggering IRQ14: BEACON_COUNT and USCOMPARE. The former triggers IRQ14 every time the BEACON_COUNT timer reaches zero, the latter triggers it when USCOUNT matches USCOMPARE. All fine and dandy.
Back then, I had done hardware tests to figure out what bit0 in USCOMPARE does, given it's a special write-only bit. I had observed that it blocks BEACON_COUNT from triggering IRQ14 until USCOUNT matches USCOMPARE, effectively ensuring that the next IRQ14 will be triggered by USCOMPARE.
But that still didn't quite make sense. Here, the value written to USCOMPARE was based off the beacon's timestamp, which was basically the host's USCOUNT register, which was obviously different than the client's. So I couldn't really see what that was supposed to achieve.
Yesterday, as I went to bed, I had an idea. What if, when receiving a beacon frame with the right BSSID, the DS automatically sets its USCOUNT register to the beacon's timestamp?
But you'd think that sounds far-fetched? I thought so too.
I tested it anyway this morning. Guess what I found out?
... read more
|20 comments (last by Mith) | Post a comment|