|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
melonDS 0.9.3 is out!
Sep 1st 2021, by Arisotura
We bring you melonDS 0.9.3, a tad late, but it comes with a good deal of improvements.
First of all, we fixed touchscreen input, it should now work as expected in all screen modes. We also added support for touchscreen devices (tablets etc).
On the emulation side, we added support for audio interpolation, as an optional emulation improvement. Depending on how good your game's samples are, you may see an improvement in audio quality. There are multiple interpolation types to choose from, so you can see which one you like best.
We also added a setting to optionally degrade the audio output to 10-bit, like the actual DS, for more authentic experience. This goes hand in hand with emulation of the SOUNDBIAS register, too. Emulating this register means nothing for the average game, but it could be used for cool tricks in homebrew. Hell, we even managed to make the DS play a song solely by regularly changing SOUNDBIAS.
There have been several improvements to DSi mode too. Namely, touchscreen calibration is now automatically patched in DSi mode, eliminating the need for a recalibration. It is also possible to boot DSi games and homebrew directly now, although this feature is still experimental. Last but not least, the DSi title manager allows you to easily install your DSiWare titles to your emulated NAND.
A ROM info dialog has also been added under System -> ROM Info.
There's also the usual slew of bugfixes and other little additions, you can check the changelog for the full list.
For the eventual 1.0 release, we also want to make melonDS less obtuse all around: providing user-selectable paths for savefiles and such, BIOS/firmware substitutes atleast for DS mode, less obtuse DLDI support, etc...
melonDS 0.9.3, Windows x64
melonDS 0.9.3, Linux x64
melonDS 0.9.3, Linux ARM64
melonDS 0.9.3, macOS x64
melonDS 0.9.3, macOS ARM64
melonDS 0.9.3, macOS universal
|28 comments (last by Hack) | Post a comment|
Buffing up DSi mode
Aug 24th 2021, by Arisotura
It's no secret that melonDS's DSi mode needs some love, but there are just so many things to do with melonDS.
One of the recurring complaints is that, when running in DSi mode, touchscreen input is off, requiring the user to recalibrate the touchscreen, while this doesn't happen in DS mode.
Reason for that is that on the DS (and DSi), the touchscreen hardware doesn't return pixel coordinates, but raw digitizer readings. Calibration data is then used to convert these readings to pixel coordinates. Every touchscreen digitizer is going to have a slightly different range, which is why users have to calibrate their touchscreen.
melonDS makes up for that in a very simple fashion. It uses its own conversion, basically just multiplying the touchscreen pixel coordinates by 16 to make decent 'raw' coordinates. When booting, melonDS also patches the user's firmware data with its own adequate calibration data, so that no recalibration is required and the touchscreen Just Works(tm). Easy peasy.
However, in DSi mode, it's another story. The old DS firmware data still exists, but the DSi system instead uses user settings files stored in the NAND. Thing is, it's less easy to access the data there: the NAND is mostly a FAT volume with an encryption layer. Not exactly trivial to deal with.
I was shown fatfs, which is basically a lightweight FAT driver. It is meant to be used to access storage media such as SD cards on embedded devices, however it is trivial to make it work on a FAT volume contained within an image file. I wrote code to do that with the DSi NAND, taking care of encryption transparently, and bam, I had a viable base for NAND manipulation.
I then wrote code to access the user settings files inside the NAND, and patch the touchscreen calibration data there. After taking care of all the details like SHA-1 hashes and whatnot, the initial issue was covered: the DSi-mode touchscreen Just Worked(tm), with no recalibration needed, just like its DS-mode counterpart.
With this proof of concept being a success, I took it further:
... read more
|13 comments (last by ^~^) | Post a comment|
Jul 22nd 2021, by Arisotura
Apologies for the slow Summer! We don't have air conditioners in the melonDS HQ. The current climate is causing the team to slowly melt.
Anyway, audio interpolation is one of the emulation improvements that have been requested for melonDS. My general policy for emulation improvements is that they should allow for keeping the accurate code paths, and they shouldn't add too much complexity to the code. Audio interpolation is well within these bounds. Actually, I had implemented it in DeSmuME back then, and due to the way DeSmuME's mixer works, it was quickly done.
So I figured I would give it a try in melonDS.
The basic idea behind audio interpolation is to smooth out the audio samples as they're being upsampled. DS games may have downsampled audio to save on space and bandwidth, and the DS mixer doesn't perform any interpolation, which can lead to rough sounding samples. The reason the DS does no interpolation is most likely due to how its mixer hardware works, but obviously as an emulator we can ignore these constraints and do a better job.
It's also noting that, as far as melonDS is concerned, there are two parts we need to take care of: the DS mixer and the audio output.
In the DS, the mixer is driven by the system clock, like nearly everything else. If you ever coded for the DS, you might have wondered why the frequency registers for the audio channels are weird:
40004x8h - NDS7 - SOUNDxTMR - Sound Channel X Timer Register (W)
Bit0-15 Timer Value, Sample frequency, timerval=-(33513982Hz/2)/freq
The PSG Duty Cycles are composed of eight "samples", and so, the frequency for Rectangular Wave is 1/8th of the selected sample frequency.
For PSG Noise, the noise frequency is equal to the sample frequency.
The SOUNDxTMR registers directly control the channel timers, which are driven at half the system clock. These work like the general purpose timers: they are incremented at half the system clock, and every time they overflow, they are reloaded to the SOUNDxTMR value and the channel advances to the next sample.
... read more
|35 comments (last by Rayyan) | Post a comment|
Jun 27th 2021, by Arisotura
[CONTENT WARNING: mention of suicide]
... read anyway
|19 comments (last by Akmaj) | Log in to post a comment|
Pride month and DMA timings
Jun 7th 2021, by Arisotura
Well, happy Pride month, or whatever, dunno how to put it. As a trans girl of some flavor, I just want to reiterate support to the LGBTI+ community. I'm also not the only LGBTI+ member of the melonDS team, btw.
Now, let's talk about something more technical (so this post is not just a 'political statement' :P ).
You might have noticed the timing17 branch. So what, another timing branch. Arisotura just loves these. Or something.
It's going to be some general timing renovation, depending on how far my motivation will take me. I started the work with DMA timings, figuring it would just be matter of taking into account that sequential timings only work when the address is incrementing linearly... well, it's hairier than that.
This is based on tests done at like 04:00, and this is the DS, so take this with a rock of salt.
Most memory regions in the DS have such timing characteristics that sequential accesses make no difference, atleast from the standpoint of DMA. The ARM9 and its 3-cycle penalty when using the bus are another story.
However, there are a couple regions that have different rules.
Main RAM (0x02000000)
... read more
|12 comments (last by BestestHD) | Post a comment|
Well, guess we owe you another release soon
May 19th 2021, by Arisotura
A quick 0.9.3 release would be welcome, especially to fix the stupid bugs that appeared in 0.9.2.
Like how touchscreen input will wrap around instead of properly clamping like it's always done. This is a good reminder to us to always test all features, even those that are granted for working. They work... until somebody introduces broken code that breaks them. It's not like this hasn't happened in the past, either, so we should do more quality control.
Sorry about this.
I haven't been doing a whole lot of melonDS coding lately either. I began researching some issues, began working on timing test suites, then veered to MPU stuff, and, well...
There are other things going on in real life, which doesn't help. I can't really focus on more than one big thing at once. There are a few going on right now: trying to find a bigger apartment to move in with friends, another housing-related thing I can't really post details about, and dealing with the obnoxious little pricks who live right next to my apartment and like partying all the damn time. Seriously they look like kids who got a fancypants sound system for Christmas or something.
Once these things have settled I will hopefully be able to work more on melonDS.
The first test suites I was making were for DMA timings. I'd need to polish them and add more test cases to make it good. Although really, the timings mostly boil down to a set of rules, some of which I have yet to implement into melonDS: for example, the maximum length of a sequential read/write burst is 118 units, and (figures) sequential bursts only work when the address is incrementing. The main issue I face is implementing the rules in an elegant and efficient way.
This doesn't even get into the fun part of CPU timings. You get the code fetch cycles, data access cycles, and other internal/etc cycles, which may interact and overlap in all sorts of fancy ways.
I want to address the timing issues once and for all, and I feel it's pointless to attempt things like full cache emulation if our underlying timing model is wrong.
|16 comments (last by Arisotura) | Post a comment|
Introducing the compute renderer
May 1st 2021, by Generic aka RSDuck
To make things short, I've been working on porting melonDS's software rasteriser to run on the GPU via compute shaders. So how is this different to melonDS's existing OpenGL renderer? The OpenGL renderer uses builtin functionality of your GPU to draw triangles. This is of course fast, since it uses hardware specifically made for this, but it has the downside that some things can't be controlled by us, so the behaviour of the DS can't be replicated completely faithfully. On the otherhand this only utilises the programmable parts of the GPU (which means we have full control over them), so it's like the software rasteriser, only it utilises the parallel computing power of GPUs. Ideally it should be eable to be just as accurate as the software rasteriser is.
Why are we doing this in the first place?
Currently the main part of the work is done (it's already somewhat playable with a lot of games), so it's easier to list what's still missing:
|27 comments (last by salva) | Post a comment|
melonDS 0.9.2 is out!
Apr 26th 2021, by Arisotura
This release brings some welcome changes.
Namely, improved Mac support: there have been fixes to the JIT, but also to the interface, so things should work more smoothly under macOS.
melonDS also supports loading ROMs from the most common archive formats, now, which means users with large ROM sets should have it easier.
We also have a new menu listing the ROMs you have opened recently, making it quicker to open them again.
We got new fancy screen modes courtesy Generic. These make it possible to use 16:9 hacks along with melonDS, among other fun things. Speaking of renderers, he also went and fixed a whole bunch of OpenGL issues.
The cart interface refactor was finished in time for this release, and with it, support for NAND save memory. WarioWare DIY and Jam with the Band are now able to save correctly under melonDS.
And, as usual, there are a bunch of other misc changes, which you can find about in the changelog or commit history.
melonDS 0.9.2, Windows 64-bit
melonDS 0.9.2, Linux 64-bit
melonDS 0.9.2, Linux ARM64
melonDS 0.9.2, MacOS 64-bit
melonDS 0.9.2, MacOS ARM64
melonDS 0.9.2, MacOS universal
|29 comments (last by Kokonut) | Post a comment|
Change to the save file handling
Apr 15th 2021, by Arisotura
I continued the work on the cart_refactor branch, and the structure itself is nearly done (I'll still need to take care of savestates). And, in a typical burst of ADHD-coding, I went and implemented support for NAND save memory, as used by WarioWare DIY and Jam with the Band.
This is when I realized that the current way melonDS handles save files was going to be problematic. Basically, if a save file already exists, melonDS will determine the save memory type from that file's size, instead of using its built-in game list. This was designed in the old days, where we had some wonky heuristics instead of the game list -- the basic idea was that if melonDS failed to determine the correct save memory type, you could provide a known good save file and it would work, bypassing the problem.
Obviously, this is also a double-edged sword. If you happen to have a save file that isn't the correct size, melonDS will pick the wrong save memory type, potentially breaking things. In the end, this strategy now seems to cause more problems than it solves, especially since we have the game list.
The NAND thing was the final nail in the coffin of this strategy. It had been assumed, from some source I don't recall, that the save memory size for NAND was 32MB, and this was nice, because each possible save memory size had only one associated type, no confusion. However, the hardware tests I did showed that the NAND save memory is actually 8MB, and this conflicts with one of the possible FLASH sizes.
(EDIT- I was corrected by another tester. The save memory for WarioWare DIY is 16MB, not 8MB.)
So I ripped the old thing out, and instead made it always rely on the game list to determine the save memory type, regardless of the save file's size. As a bonus, save files that are too big will work too, melonDS will just ignore the extra contents. Which means that, for example, DeSmuME's .dsv files could be used as-is, by just changing the extension to .sav.
If you believe this is going to be a major disadvantage, or see any issue with this, I encourage you to reply to this post.
|12 comments (last by Rayyan) | Post a comment|
Redesigning the cart interface
Apr 13th 2021, by Arisotura
The kind of change that doesn't immediately mean a lot for end users, but means a lot for us coders (and ultimately means something for end users, too).
Anyway, this tends to show why it's good to think forward when designing your code. That being said, I need to find a balance with this. I tend to either think forward too much and end up paralyzed by questions that don't mean much, or just write code as it comes to my mind.
The cart interface in melonDS was originally built without much consideration for future. If you're wondering, the cart interface is the part of the emulator that lets emulated software access the emulated cartridge, because on the DS the cart isn't just directly mapped to CPU address space like on older consoles. Instead, there are a bunch of commands you can send to the cart to retrieve various parts of the contents, and different encryption protocols securing it up.
As melonDS became capable enough to run commercial software, emulating the cart interface was a must. So NDSCart.cpp was born. The main component is the NDSCart namespace, which originally emulated the cart interface hardware (basically the DS side) and command responses for a generic cart. There is also NDSCart_SRAM, which emulates the on-cart SPI save memory. A tad hacky, but for most games, it did the job.
But, that's the thing, not all DS carts are the same!
There were already some exceptions for homebrew ROMs, which might want to use the cart interface and, depending how old they are, need a more lax implementation of the generic cart protocol. Namely, retail carts don't let you read addresses lower than 0x8000 via the generic data read command (0xB7), because that region contains the ROM header (read via a different command), the Key1 encryption data and the secure area. However, old homebrew ROMs don't have any of that (save for the oldstyle DS header), and have their ARM9 binary start at 0x200. Newer homebrew ROMs are closer to the layout of a retail cart, mostly due to the added DSi support (the DSi header is 0x1000 bytes instead of 0x200), but, since not everybody is here to rebuild their ROMs, we still need to support the older ROMs.
Homebrew aside, there are also different types of retail carts.
A prime example is Pokémon games. The carts are fitted with a IR transceiver, which is accessed via the save-memory SPI bus. In practice, the first byte of a SPI transfer is a command for the IR transceiver. For now, we know that command 0x08 is some ping command that should reply 0xAA, and command 0x00 is the pass-through command, where any further bytes are forwarded to the save memory. Emulating this is required for Pokémon games to be playable at all. In melonDS, these commands were added to the generic save-memory code. A bit of a hack, since this means these would be 'functional' in any game instead of just Pokémon games, but it did the trick.
But there's more. Games like WarioWare DIY, or Jam with the Band, don't even use the save-memory SPI bus. They have save memory, but it's a NAND memory that is accessed via the same bus as the ROM itself, through a set of specific commands.
... read more
|5 comments (last by Rayyan) | Post a comment|