Yeah use a debugger.
The saves use a certain area of memory so watch that (save loading might be at boot, after pressing start on the title screen or a save load screen, sometimes even when they do a save load screen)
http://problemkaputt.de/gbatek.htm#dscartridgebackup
Anyway you can watch it take the save into memory, do whatever maths it is doing (will probably be a long series of basic steps as processors only do basic things) on the memory selection it does it on (sometimes the save hash will be the only part that is not hashed, other times it will be a smaller selection) and then replicate that in whatever language on the PC.
If however it is just for a single thing you want to edit (or maybe if you want to fiddle with the save format to do some things) then it can be easier to just disable the check coming the other way. The game might do some fun maths throwing numbers around over the course of a few hundred instructions to do a nice custom checksum you would never guess by observation*. In the end though it will take the result of that, compare it to the checksum the game provides and say yay or nay. You tell it to let everything through and it will load your edited save, get it to save again and it will likely also fix the hash for you when it does so you can then restore it to an original/unmodded game (though you could probably port that patch to a cheat if you really wanted). Such a thing is usually a single instruction change somewhere to change a break if not equal to a jump every time; in most cases you will have something like a compare between the two values, then a break if not equal and another jump it is equal/matches, many ways to sort this issue but if you want to patch the break of not equal to be a do nothing instruction it will always then take the good jump.
I thought some emulators had a measure of multiplayer support but yeah it is going to be tedious. Editing outside and then forcing another save might well work -- most saves are just copy user data to save, do hash, write save rather storing random bits of data here and there.
*most DS games will not do some kind of crazy high security custom MD5 or another as much as a basic CRC used elsewhere in other games, a simple bytesum or something equally banal -- cheaters gonna cheat as it were so you are mainly concerned with simple corruption and thus don't need the fancy stuff that the poor 66MHz ARM9 with a couple of megs of RAM is going to have to power its way through over several seconds vs something that does the same job in a blink of an eye with a fraction of the memory needed. Pokemon might well be an exception though.