When working on Chin Music, I've come to a number of conclusions.
* What I'm doing is not portable.
* What I'm doing clearly does not always work.
* What I'm doing relies heavily on exploiting some glitches in the system.
* What I'm doing only works with a handful of programs.
I've done some thinking and have come up with what I hope is a brilliant and elegant solution to the problem at hand.
The original idea was to be able to manipulate an emulator with no participation on the part of the emulator's development team. I could just put an emulator in a black box, send it window messages, and it would send a bitmap back. This means doing silly things like killing the menu and status bars, stripping the window decoration, and messing with the device context. All of which can have undesirable results.
An alternative idea is cooperation, either through direct integration or via forking the project to support duplex communication with external applications.
So here is the scenario playing out in my head.
For each emulator there would be two message queue. Queue 1 is the input queue. This is where messages such as button up, button down, cursor moves, volume is increased, game is muted would be sent from the front-end to the emulator. The emulator would consume messages from the queue.
Queue 2 is the output queue. This is essentially a broadcast of what's being displayed on the screen at a given time. The structure could simply be width, height, depth, endianess, followed by the the image generated by the emulator. The queue could be read, not consumed, by the front end. On a local system, this should at most generate one or two frames of lag. Copying a bitmap is far less intense than the operations being done inside the emulator.
One or the other queues could be used, both do not have to be.
Other than communicating with front-ends, this could be most useful for scripting AIs, screen casting, or any number of other applications.
This would also mean only having to configure a game pad or arcade stick from one application instead of editing multiple configurations. This could also mean making up for deficiencies in emulators which lack support for (as an example) taking a screen shot by holding the start and select buttons.
Lets examine what a sample syntax might look like for an NES system
<<system command> <value>> |<<game command> <controller port> <value>>
system commands
* pause
* resume
* volume_up
* volume_down
* set_volume X
* speed_up
* speed_down
* set_speed X
* save_state X
* load_state X
* exit
player commands
* button_press X A
* button_release X A
* button_press X B
* button_release X B
* button_press X Select
* button_release X Select
* button_press X Start
* button_release X Start
* button_press X Up
* button_release X Up
* button_press X Down
* button_release X Down
* button_press X Left
* button_release X Left
* button_press X Right
* button_release X Right
For more advanced emulators, you could set the delta of one of the sticks, or the movement of the mouse, etc.
Using Zero MQ (http://www.zeromq.org/) which satisfies cross platform requirements of many emulators, and boasts great speed seems like an ideal way to move forward.
It's my goal to soon release some prototype code to demonstrate the effectiveness and practicality of this solution. I would greatly appreciate developer and user feedback on this concept. Thanks.
Sounds like you'd rather want a properly librarized emulator core. There are few, but some emulator projects, but off the top of my head you have:
ReplyDeletebSNES => libsnes
Gambatte => libgambatte
etc ...
@Themaister, that would be nice, if more emulators had that support. It would be great if I could just import a DLL and have a common set of functions I could call to send input and get back a bitmap.
ReplyDeleteI have high hopes for mednafen. Eventually it will be a nice all in one.