> The next part of the problem is there's too many goddamn UI toolkits.
I solved that
http://xkcd.com/927/ style. I wrote a toolkit that wraps other toolkits. So now one nice, clean API can generate native Win32, GTK+, Qt and Cocoa applications. And targeting a new API in the future would only take a week or so. It does force you to target the least common denominator, though. A feature not available on one or more platforms means a feature that can't be available to the wrapper API, so you get a really barebones UI. Still, more than enough to design a decent UI. Real downside is I've spent 70% of the past two years writing the UI wrapper now :P
> If people didn't insist on doing the resampling themselves, sound would be significantly easier. I don't get the insistence on doing it themselves.
The reason I enjoy programming is to learn how to do things.
In my mind, a programmer is a creator who learns how things work and creates tailored, lean, efficient implementations, where the journey is the reward. A coder is someone who glues libraries together, and is only focused on the end result.
This spectrum is of course infinitely wide. You can go to the extreme of a guy wrapping aluminum foil around a glass jar full of saltwater to make his own capacitors -- to ultimately build an entire hardware replica; all the way to a guy forking a pre-made emulator frontend, and simply paying for-hire coders to make little tweaks he requests.
In the realm of non-absurdity, you get a smaller spectrum. People like me that want to write all of the code, sans the core libc++ functions and real hardware drivers. Others are okay with using libraries for all ancillary stuff like image scaling and audio resampling. Others are okay with gluing pre-made CPU/APU cores together, and adding a bit of video rendering. And finally, you have people taking fully pre-made emulators and creating things like multi-emulators from them.
I spent an extra 2-3 days cloning a mini-Deflate algorithm, so that I can decompress ZIP and PNG files in 8-10KB. You could say it's a stupid waste of time since I could have just used the 400kb zlib. But why then isn't it stupid to write your own CPU core when you could just use Musashi 68K or Starscream or MZ80 or m6502? I ended up making a better SNES CPU core than anyone before me. Maybe once I learn audio processing, I might come up with a novel technique that improves upon blip_buffer. Very unlikely, but it is possible.
...
Audio emulation is a lot more than resampling, too. The non-linear mixing was a real challenge even with Ryphecha's help. I have no idea if I got all of the weird shadow registers correct for the individual channels, and I have zero test ROMs I can run to find out.
> I'm just "sensitive" over the number of NES emulators that are getting made, because I feel if all that energy was directed in a more organised/effective manner, we'd probably have perfect NES emulators for every OS/platform by now.
The vast majority of emulator authors contribute nothing to advance core emulation (UI experience, sure.)
If you're reimplementing documentation, at best you might guess a way to fix a bug in known games, but unless you have your own hardware testing rig and are verifying your behaviors are 100% correct, all you're doing is potentially leading people down the wrong path.
Most likely all you're doing is bugging the people who are doing real work when you get stuck (like my GB forum threads.) But on the bright side, that creates absolutely stellar documentation. Compare NES docs to DMG docs. For the NES, you get step-by-step fetches for the PPU. For the DMG, you get pandocs, last updated in 1998. There's less detail in all of pandocs than on loopy_t/v by itself.
In an ideal world yeah, we'd all work together. But we too quickly disagree on details, so it's never going to work.
I decided to make an NES emulator because I wanted to experiment with the mapper and file format issues. I prefer to split the PRG and CHR ROMs, and then describe the board in an extensible markup. And longer-term, I am working on a micro DSL to implement the actual board emulation from an external file. This file would either be interpreted or converted to bytecode, but never hard-compiled and platform-dependent like DLLs are. The ultimate goal would be allowing to express bootleg mappers without having your emulation core have to support them.
I doubt a single emulator author on this forum thinks the above is a good idea. So how would I work with a large group of developers here? Pretty much everything I did with the SNES was extensively derided, yet I've shown that it works really well. And now
most SNES emulators are cycle-based, and are starting to do coprocessor LLE. Making ones own emulator is a way to try out their own ideas, unimpeded.
There are also, of course, a lot of vanity / just-for-fun projects. Get Mario running, then release it and abandon it. That is just a drain on everyone else. The people who explained stuff to them, the people testing and reporting bugs, the people trying to choose an emulator to run and having one more useless emulator in the list, etc.
It's really hard to tell who will end up serious, too. FHorse's first release reeked of a vanity emulator, yet he's topping the list of test ROMs passed now.
So, who knows. I agree with your advice in general, but I'd tweak it a bit: please don't write an NES emulator unless you know you are really serious and intend to contribute something significant to the resources you will undoubtedly consume in the process.
Of course, nobody's going to listen. They'll do whatever the hell they want, because they can.
> Also the 3 - 1 ratio only works for NTSC NES. On other systems, there is multiple unrelated oscillators for the SPC and CPU and there is not a clear clock ratio between them.
The best way to synchronize two processors of the same clock ratio is to have an int64_t clock = 0; variable. When one processor adds clocks, increment the value. If it's >= 0, switch to the other processor if you are doing an operation that might effect it. The other processor will decrement by number of clocks executed. If the clock drops below 0, then switch again if doing something that processor might see.
When you get different frequencies: processor A adds B.frequency * clocks, and processor B subtracts A.frequency * clocks.