|
| 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 • Savestates • Various display position/sizing/rotation modes • (WIP) Wifi: local multiplayer, online connectivity • (WIP) DSi emulation • DLDI • (WIP) GBA slot add-ons • and more are planned! Download melonDS If you're running into trouble: Howto/FAQ |
| Pages:1234567···26 |
|
Motivation, motivation... Jul 18th 2026, by Arisotura |
|
Yeah, I haven't been great at this. I told myself I would work on 2D filters, since it's one of the last things to do... then I ran into a bit of a wall: I need my filters to have alpha support, but the filter shaders I can find don't support it. I would need to spend some time figuring out how they work and how I can add that in based on other references (there is code for xBRZ or HQX filters with alpha support, but not in the form of shaders). And I, well, didn't feel the desire to continue... Maybe it's the nature of software development in itself. Unless you're working on a smaller, simpler project, you're never really done, and especially not with a project like melonDS. What started as a way to pass time has become a full commitment, in a way. By comparison, my job has been a lot simpler, and better suited to my brain too. When you set out to repair something, it's a project with a clear end. Most of what I deal with is also fairly simple, but sometimes there are more complicated cases, requiring more time and research. For example, those HMI lamp ballasts I'm working on: they are quite complex. This has been an ongoing project for a while now. Maybe it's the fact that the project still largely rests on my shoulders. While bigger projects like Dolphin or PCSX2 may have a bigger team and more of a workflow in place, things aren't really like that here... I'll just quote Generic, because he put it well: [18:55]Generìc "Yes, we can!": I think I stated this before, but how I see it melonDS never went through the professionalisation many other projects went through
[18:58]Generìc "Yes, we can!": just look at other projects (even with just a single maintainer) setting milestones, systematically "triaging" issues and so on [19:00]Generìc "Yes, we can!": also tests [19:01]Generìc "Yes, we can!": and throuroughly adoption of new fangled C++ features [19:03]Generìc "Yes, we can!": if it wasn't for Nadia putting so much effort into the build system through the whole time, the codeblocks project file would still be the way to build melonDS I feel bad about having so many issues, pull requests, etc, staying open and rotting in the backlog. At the same time, I just don't have the brain power to review every single PR alone. And to make matters worse, now we have people submitting AI-generated code, which is problematic from several standpoints: code quality (AI tends to make a mess and not really understand what it's doing, and someone who's using AI isn't likely to understand those things any better), plagiarism, the usual ethical and environmental problems with AI too... I like the idea of open source, but for a project of this caliber, it feels that we should have more of a system in place, with a bigger team, clearer roles... a proper organization. One where different people with different skillsets and preferences can complement eachother. For example, while I enjoy researching the DS hardware, or figuring out why a game isn't working as it should, stuff like build systems can quickly feel very frustrating to me. As Generic put it, if it weren't for Nadia handling that work, we might not have nightly builds today, for example. ... read more |
| 5 comments (last by SkalFate) | Post a comment |
|
Bit of plans Jun 21st 2026, by Arisotura |
|
As far as melonDS is concerned, my last work was all about CPU timings... and I couldn't yet find an elegant way to handle them. I had some kind of caching in mind, but it's still less than ideal. Code fetch timings could be cached, but data fetch timings aren't really predictable, and there are other mechanics coming into play. What I had in mind was a sort of graph system, but I don't know how well it would work in practice. This will be for later though. I didn't foresee how much time and energy starting this job would take me. Things are starting to even out now. Same story for my psyche, things are falling into place, but there's still work... Anyway. Plans. I will try to finish the work I was doing with the new OpenGL renderer. It was mostly dealing with things like VRAM streaming, and adding a "Golden Sun hack". I could also try and see if I can build something for 2D layer filtering, but I might postpone that. When I'm satisfied with what I have, I'll release melonDS 1.2. Sound good? |
| 13 comments (last by elunes) | Post a comment |
|
Expect slowdown May 10th 2026, by Arisotura |
|
A bit of a status update since the last post... "I've been taking a bit of a break from melonDS lately... mental health reasons, a silly side project, the usual stuff." More of the same stuff, but add to it that I've been getting started in this new job. While it's been nice to have time to myself in order to deal with mental health matters, unemployment gets old after a while, so I was eager to finally start this job. If you remember, I've had a foretaste of it back in December, too. I've seen my ADHD self thrive in that setting. The job is largely about repairing A/V equipment. This feels like a much better fit for my brain than a regular developer job. I like to code, but that's not all I do: I also like to build, repair things, and in general, understand how systems work (or design them). I consider code to be much of the same, but it's all inside a computer instead of being a physical object, so it lacks the "doing things with my hands" aspect. A related example here: last year, I repaired buttons on a vacuum tube radio as part of a larger project. This is the kind of small project where I have a blast: using my brain to figure out a solution, actually implementing it with my hands, doing my best to adapt to how things actually work out... It makes me feel alive like nothing else. But I digress. The flip side of this is that the longer work day and commute time leave me with less time at home. On the other hand, this job is a particular arrangement where I'll be working half of the year, which will definitely give me time for my personal projects, including melonDS. Just, won't be now. The first work period is going to be 6 months. - This also means having to balance work and mental health. ... read more |
| 21 comments (last by Sebvant) | Post a comment |
|
A bit of a status update Apr 26th 2026, by Arisotura |
|
I've been taking a bit of a break from melonDS lately... mental health reasons, a silly side project, the usual stuff. Regardless, I've been rethinking my plans for melonDS. I think I might postpone the timing work to melonDS 1.3. It's bigger than anticipated. I want to address some other issues, most notably finishing the new OpenGL renderer, and release melonDS 1.2. There's also some codebase cleanup I want to do. Regarding the timing work, it's going to take some planning, and possibly a larger rework. As I've said, the ARM7 is simple enough. Things are pretty much sequential, and the only extra complexity comes from main RAM burst termination delays. The ARM9 is where it gets hard. We deal with mechanics like cache streaming, write buffering, ability to keep running code while the bus is in use... All sorts of mechanics which highlight the limits in melonDS's current model. For example, take the LDM and STM instructions. They do multiple consecutive memory accesses in a row. They're commonly used to push registers to the stack and pop them back, or to quickly clear or copy large blocks of memory. There are several issues arising from this. Depending on the base address, a LDM/STM instruction might cross the boundary between two memory regions, or two MPU regions on the ARM9. STM, when accessing I/O registers, might also cause a bus stall between two memory writes (for example, if it starts a DMA transfer...). melonDS was built on top of a plain old interpreter. We read one instruction word from memory, we use a lookup table to figure out what we should do, we do it, then we move on to the next instruction, and so on. This model treats individual instructions as atomic: there is no way to account for all possibilities with LDM and STM, for example. Or atleast, not easily. ... read more |
| 12 comments (last by janitor) | Post a comment |
|
New demo: Emulator Examination Apr 12th 2026, by Arisotura |
|
Emulator Examination is a DS demo which has been released recently, and has been programmed by PoroCYon. I figured this would be an opportunity to write about something other than CPU timings for once! But first, a video of this demo, comparing the hardware results against melonDS. This demo bends the DS hardware in creative ways. You can read PoroCYon's writeup here, but I figured I would write about my perspective too. First of all, this is a DSi demo, which limits the opportunities for emulator comparison. As of now, melonDS and NO$GBA are the only emulators with some degree of DSi support. The demo will still run on a DS, but you'll be limited to the first test, since this one isn't DSi-exclusive. Now, let's see what we got here. First, we have an eyesight test. At first, I had no real idea what was going on here. Basically, the PPU mode is changed in the middle of a scanline, which causes very specific glitches. The interesting part is that this mirrors how hardware reverse-engineering works: doing unintended things with the hardware, observing the results and figuring out the logic behind them, can offer insight into how the hardware works beneath the surface. It can also confuse you to shit (hi, 3D GPU). However, this effect is unlikely to ever work correctly in melonDS. Emulating it requires understanding and accurately modelling how the PPU works at a cycle level, while melonDS employs a scanline-based renderer. And since no games out there try to modify PPU registers during a scanline, there are no provisions for supporting that. ... read more |
| 6 comments (last by gtx1050tiuser) | Post a comment |
|
The timings saga, ep 2 Apr 9th 2026, by Arisotura |
|
At this point, this might as well be its own little saga... albeit not as exciting as the local multiplayer one, atleast on the surface. What is exciting, though, is the possibility to deal with timing issues once and for all. Maybe not. We can't get it 100% perfect without cycle accuracy. But we can get as close as possible, and then see how much leeway we have. It should be easier to figure this out with a more correct model. When your timing model is fundamentally inaccurate, you can tweak the numbers, but that's a game of whack-a-mole: it fixes some bugs and causes other bugs. This is what the "Enable Advanced Bus-level Timings" option in DeSmuME does. The cache timing constants in melonDS, if they could be modified by the end user, would yield similar results. Fun fact, melonDS's current timing model is flawed. Due to a few bugs, it doesn't even work as intended. But even if it did, it would still be inaccurate. DesperateProgrammer's cache PR, aka PR #1955, is a pretty solid base for cache emulation. I think it's a good sign that it alone has showed promising results, despite being based on the same fundamentally flawed timing model. Anyway, enough talking. Let's see where we're at today. So far, I'm mostly done with ARM7 timings. I've been collecting timing numbers, figuring out the logic behind those with Jakly's help (thanks there!), and implementing it. In my timing tests, melonDS yields the same numbers as hardware, so that's nice. It feels pretty satisfying when you figure out the logic and everything clicks into place. I still need to doublecheck everything, and do actual real-world timing tests, to make sure I have everything right. However, as far as CPU timings are concerned, the ARM7 is only the appetizer. The timing model is fairly simple. The ARM7 doesn't have internal memory and only has one bus, and everything runs at the same frequency, so most timings are fairly straightforward. ... read more |
| 8 comments (last by Justmythoughts) | Post a comment |
|
Actual status update on timings Apr 2nd 2026, by Arisotura |
|
As promised. Timings work is underway. I'm mostly done collecting numbers, minus stuff like CP15 operations and any special cases that might crop up. I started fixing up ARM7 timings. Thing is, timings work isn't always easy. Collecting timing numbers is one thing, understanding the logic behind them is another thing entirely. Geometry engine timings, which I've worked on years ago, are a prime example of this: when you submit a display list to the geometry engine, the total execution time isn't simply the sum of each command's execution time. The reason for this is that the geometry engine has a pipeline: it can execute certain commands in parallel. It took me a lot of testing and number collecting to understand the logic behind it. If the geometry engine, a simple 3D command processor, is already like that, you can imagine what a full-fledged CPU is going to be like. This is why CPU timings are an area of melonDS that has been more or less neglected for so long. On the flip side, the DS isn't like older consoles such as the GameBoy or the NES, where games might rely on very precise timings in order to get the best out of the system's limited power, and they might crash if a certain event occurs 2 cycles too late. On the DS, from what I've seen, it's more about timings at the macro level, ie. how long a bigger operation takes. For example, consider a DMA transfer to copy a screen-sized bitmap, that is, 24576 words. A difference of 1 cycle in the initial DMA setup time doesn't matter, but a difference of 1 cycle per word transferred quickly adds up. Like here. So, what are ARM7 timings like? The ARM7 has a 3-stage pipeline, which means it can execute an instruction while decoding the next one and fetching the one after. So, for a lot of instructions, the execution time is capped by the access time for the memory region we're executing from. Some instructions may need more cycles to execute. Load and store instructions are also particular, since they access memory. Different memory regions have different access times, depending on their data bus width and the type of memory access. Most of the available memory regions are integrated into the DS SoC, so they can be accessed in one cycle. VRAM has a 16-bit bus, so 32-bit accesses are broken into two 16-bit accesses and take two cycles. External memory, however, has its own rules. There is a notion of nonsequential and sequential accesses. Basically, the memory being accessed may require a setup time for an initial access, but may be able to chain subsequent accesses in a faster way. The ARM7 makes use of this when fetching code: as long as a given instruction doesn't require extra cycles, the next one may be fetched in a sequential memory access, resulting in faster execution. Instructions like LDM and STM, which can load or store several words in a row, also make use of this. ... read more |
| 6 comments (last by marion iggers) | Post a comment |
|
New direction for melonDS Apr 1st 2026, by Arisotura |
|
[POST IS AN APRIL FOOLS JOKE] It has appeared to us that after nearly 10 years of development, we are still very far from having a perfect DS emulator... thus, something has to be done. After all, you can't keep doing the same thing and expect different results, can you? So we have been looking at those AI coding assistants. We have seen Windows 11, and how the use of AI has helped turn it into a truly reliable, performant and user-friendly OS. We were originally doubtful about AI, as we always are towards any new technology, but we have to admit, it's pretty good. So I first gave it a try. I told Claude about the issues I was currently facing in melonDS, the timings work, and how difficult it all is. Claude offered a solution that at first seemed quite unorthodox, but actually makes a whole lot of sense. After all, timing issues exist because timings exist. If you remove timings, no timing issues! That's pretty smart. I offered to let Claude remove all timings from melonDS. It isn't perfect yet, but I observe that most problematic games are now running to some extent. I'm fairly confident that with more refining, we can solve the issue of timings once and for all. The downside is that getting rid of timings basically means melonDS will be running everything as fast as possible, which requires quite a strong CPU. But not too strong, or your games will be running too fast. I haven't yet figured out how to make the framerate limiter work smoothly with timing-less emulation, but once again I'm confident Claude will come up with a genius solution. ... read more |
| 6 comments (last by bob7210) | Post a comment |
|
Chronicles of Timings: Tales of Destruction Mar 16th 2026, by Arisotura |
|
Ah, timings. The infamous Horseman of Timings. This post is going to be about a decision I'm taking for melonDS, but first, I'll write about my recent research regarding two old timing issues. I found it very interesting to dig into those games and figure out how they work. 1. Corrupted FMV audio in Over The Hedge - Hammy Goes Nuts Basically, you start a game, and you have a bit of a video introducing the plot of the game... except the audio is covered in high-pitched beeps and loud screeching. I first found that the game runs a video/audio decoder on the ARM9, which appears to have been largely written in ASM. The audio decoder writes its output in main RAM, where it gets sent to the audio hardware. The way it works is interesting. The audio buffer size is calculated based on the length of the audio track, the audio frequency, and other parameters. In this case, the length is 30 blocks, one block being 128 samples. Then, the decoder is run until the buffer is filled to a certain point (23 blocks). At this point, audio playback is started. The ARM7 also starts a periodic alarm which will notify the ARM9 every time one block worth of audio has been played. The alarm notification is used to run the audio decoder when needed. However, the audio decoder works in terms of bigger chunks: one chunk typically contains 6 blocks worth of audio. So the decoder attempts to process that many blocks in one go, but it stops processing new blocks when the output buffer is full. The catch is that, as far as I can tell, when blocks are skipped, there is no logic to compensate for that. The next time the audio decoder runs, it will start working on the next chunk no matter what. Since the decoding process relies not only on the current input but also the previous output, skipping blocks breaks it. And that's what is happening on melonDS. In this situation, the ARM9 needs to run slowly enough that it doesn't get too far ahead of audio playback, and doesn't fill the output buffer entirely. ... read more |
| 6 comments (last by dreamsyntax) | Post a comment |
|
Fixes, and future of melonDS Mar 8th 2026, by Arisotura |
|
Things have been difficult lately, mental health wise. However, despite this, we're still on a pretty good upward trend on that front. Anyway, I mentioned the cartridge interface in the previous post, so I've been doing an accuracy-oriented revamp of this. I've already been through the technical details, so instead, I'll post about the outcome of this. This fixes the freeze in Surviving High School, and likely other DSiWare titles. This also fixes Rabbids Go Home: in DS mode, the antipiracy no longer kicks in, so the game Just Works(tm). Also, turns out this game skips the antipiracy check when running on a DSi, so that's why it was working fine in DSi mode. I've had reports that this also fixes the crash in The World Ends With You, so that's great. I've also been able to figure out why several games crash in DSi mode. Namely, games that aren't DSi-enhanced, but were built against recent SDK. The code for reading the ROM retrieves the correct value for the ROMCTRL register from the ROM header, at 0x027FFE60. When running on a DSi, that address is adjusted to 0x02FFFE60, to account for the larger main RAM. Technically, 0x02FFFE60 would also work on the DS, due to mirroring; however, since it's not within any MPU region, trying to access it causes a data abort. The issue was due to missing support for the SCFG access registers. Those registers allow to block access to specific DSi I/O ranges, which serves to implement DS backwards compatibility or restrict access to specific hardware components (for example, blocking cartridge games from accessing the NAND). In this case, games read SCFG_A9ROM and determine that they're running in DSi mode if the value is non-zero, but if access to SCFG registers is disabled, the value will be zero. This brings me to ideas I have in mind for melonDS, and the direction things are going to go. ... read more |
| 18 comments (last by Arisotura) | Post a comment |
| Pages:1234567···26 |
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: