News of the great refactoring
In this post I showed an attempt at running two melonDS windows at the same time. Just a silly test, but groundwork for more.

What became apparent during this is the fact that our current configuration system won't do.

The current config system was born out of simple needs: at the time we just needed to store a few configuration values. The keyboard and joystick input mappings, and misc settings like direct boot or 3D renderer threading. For this, a simple pseudo-INI format was deemed enough. The config file is named melonDS.ini, but it is just a simple key-value pair format with a custom parser, not an actual INI format.

The configuration data in melonDS is just a bunch of global variables in the Config namespace exposed to the entire program. The parser simply goes through all the lines in melonDS.ini, checks the key against a list of possible keys, and when a match is found, the corresponding variable is filled with the value that was read. The same list also serves to initialize the config data with default values (for example, if melonDS.ini wasn't created yet). All fine and dandy.

This system, however, doesn't shine in its flexibility. This started becoming apparent in 0.9.5 when the new local multiplayer system was added. I realized we needed a way to allow each melonDS instance to have different settings for things like input mappings. Prior, the only way to do that was to run the different instances from different folders.

The solution I had come up with, was to create other melonDS.ini files: melonDS.2.ini for instance 2, melonDS.3.ini for instance 3, and so on. melonDS.ini would contain the bulk of the settings: the settings that are common across all instances, and the settings for instance 0. Then, when opening a new instance, it will get the global settings from the main melonDS.ini, and its instance-specific settings from its specific config file. If said specific file doesn't exist, it is initialized from the main melonDS.ini.

It's nice and colorful, but a bit unwieldy...

When I started working on that proof-of-concept multiple window thing, I had a realization in the same vein. Basically, the config file also serves to store settings related to the window: size, layout settings, etc. For a multi-window feature to be useful, we want each window to have its own settings (say, having one window display the top screen, and another the bottom screen). Clearly, the current config system won't do here.

So what can we do? Find other creative ways to get around the lack of flexibility of the pseudo-INI system?

Nah.

Instead, we are going for a radical approach: replacing the pseudo-INI system entirely. We decided to go with TOML for a flexible config system. With a TOML file, we can store arbitrary amounts of entries, sub-tables, arrays, and so on.

For example:
RecentROM_0=/home/arisotura/ndsrom/sm64ds.nds
RecentROM_1=/home/arisotura/ndsrom/mkds.nds
RecentROM_2=/home/arisotura/ndsrom/sonic.nds
RecentROM_3=/home/arisotura/ndsrom/nsmb.nds
RecentROM_4=/home/arisotura/ndsrom/2d_latch.nds
RecentROM_5=/home/arisotura/ndsrom/a_blarg.nds
RecentROM_6=/home/arisotura/ndsrom/libfatdir.nds
RecentROM_7=/home/arisotura/ndsrom/pokeplat.nds
RecentROM_8=/home/arisotura/ndsrom/party.nds
RecentROM_9=/home/arisotura/ndsrom/httpget.nds
The recent ROM list in the current pseudo-INI format is basically 10 separate variables. If you want more than 10 entries in the recent files menu? You would have to add more variables.

In TOML, it can be stored like this:
RecentROM = [
"/home/arisotura/ndsrom/sm64ds.nds",
"/home/arisotura/ndsrom/mkds.nds",
"/home/arisotura/ndsrom/sonic.nds",
"/home/arisotura/ndsrom/nsmb.nds",
"/home/arisotura/ndsrom/2d_latch.nds",
"/home/arisotura/ndsrom/a_blarg.nds",
"/home/arisotura/ndsrom/libfatdir.nds",
"/home/arisotura/ndsrom/pokeplat.nds",
"/home/arisotura/ndsrom/party.nds",
"/home/arisotura/ndsrom/httpget.nds",
]
Then the RecentROM item is accessed as an array. The only limit on its length is decided by the UI code.

In a similar vein, multiple instances and windows can simply be handled by adding more data tables for them in the config file. It is possible to store them as an array of tables, but I chose to explicitly name them 'Instance0', 'Instance1', 'Instance2', and so on, to make the file more readable.

Obviously, this requires reworking the way melonDS accesses the settings. Just exposing a bunch of global variables won't do here.

So far, I added a simple wrapper class for TOML tables. Besides keeping the TOML library code in one place, it also allows me to handle default values and allowable ranges for integer values transparently. Then any given emulator instance can keep track of its own config table, as well as the global table. The current format isn't set in stone, but it gives me an idea how things should be laid out.

Of course, there is also code in place to convert pseudo-INI files to the new format if needed, so you won't lose your settings.

I am now in the process of adapting the frontend code to use the new config system. Easier said than done, because this is intertwined with the rest of the refactoring: basically encapsulating everything so that multiple melonDS instances can be run within the same process, without them sharing global state.

So, yeah. Slowly but steadily, we're getting there.
Zyute says:
Apr 19th 2024
Got to admit this sounds like a nightmare but you seem to have the right mindset to handle the situation. Using a wrapper with the toml tables along side the ini files is proving to work for you so keep at it! One piece of the puzzle at a time 😎.
XeroEcho says:
Apr 20th 2024
This is awesome keep it up!
dsi says:
Apr 23rd 2024
i knew you were a genius.
i can't believe that there are people who can think like that.
does this also solve the problem of kaotore's slow camera?🤔
Post a comment
Name:
DO NOT TOUCH