Load roms externally?

Official support forum for the Exodus Emulation Platform

Moderator: Nemesis

Post Reply
Montserrat
Very interested
Posts: 114
Joined: Fri Sep 18, 2015 2:56 pm

Load roms externally?

Post by Montserrat » Mon Apr 15, 2019 6:52 pm

There is a way to load roms via command line? like c:\exodus.exe rom.bin. I need it to fire some macros in my IDE.

Thanks!

Nemesis
Very interested
Posts: 773
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Re: Load roms externally?

Post by Nemesis » Tue Apr 16, 2019 1:39 am

Not currently I'm afraid, right now there are no command line arguments. Support for them could of course be added, but I'd have to give some thought as to what I'd support on the command line, and how it would be implemented.

Montserrat
Very interested
Posts: 114
Joined: Fri Sep 18, 2015 2:56 pm

Re: Load roms externally?

Post by Montserrat » Tue Apr 16, 2019 7:23 am

Ok thanks for the reply anyway!

ryanfaescotland
Interested
Posts: 48
Joined: Mon Feb 09, 2015 10:46 pm
Contact:

Re: Load roms externally?

Post by ryanfaescotland » Wed Apr 24, 2019 8:02 am

This is one of the Feature Requests I was thinking of taking a look at, it's handy, highly requested, fits with my own needs and likely achievable even with limited C++ and Exodus knowledge.

I've a few other items I want to take care of first irl but after that I'll likely look at this if it's still on the list.

Just a thought though, it might be easier (and still in keeping with the project) to have a ROM definable to load automatically as part of the workspace? I'd still have command line support to override the default and handle other arguments but this seems like a handy and simple feature to add.

tryphon
Very interested
Posts: 303
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Re: Load roms externally?

Post by tryphon » Wed Apr 24, 2019 9:49 am

A simple key-shortcut to load the last loaded ROM would be nice ;)

Nemesis
Very interested
Posts: 773
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Re: Load roms externally?

Post by Nemesis » Fri Apr 26, 2019 5:43 am

One thing that makes it slightly more complex is how ROM loading works. Exodus can't actually load a ROM. A ROM is just a blob of arbitrary data. Out of context, it means nothing. Exodus doesn't have anything about a Mega Drive hard-coded at all, as the system itself is just defined by a bunch of ports and connections between devices through XML. Exodus itself doesn't understand what to do with a ROM file, all it can do is load additional modules to extend the loaded system. What you really want to do is effectively insert a game cartridge into the system, with the corresponding hardware and behaviour which would be expected for the real cartridge that was released, which happened to store a ROM with the given set of data on it as part of its content.

Nobody has existing xml files to define their Mega Drive roms though, everyone just loads binary blobs into every other emulator, and they expect Exodus to be able to do the same. The solution to this while keeping Exodus generic and platform independent, was to use a plugin, in this case a "Mega Drive ROM loader" plugin under MDExtensions.dll. This plugin adds the menu options to open and close a Mega Drive ROM. All this plugin actually does though is contain the Mega Drive-specific game loading hacks that every other emulator ever written does, which is to look at the ROM header and/or checksum, and based on which game it appears to be, decide on issues like region, SRAM, and other custom hardware or characteristics we expect this game to have. Once this identification has been made though, the plugin just outputs and auto-generated XML file for that game, then uses the internal APIs to load that module in and start the emulator running. You'll find the autogenerated game modules under "Modules\AutoGenerated\MegaDriveROMLoader".

For example, here's the module that gets generated when I load Sonic 2:

Code: Select all

<Module SystemClassName="SegaMegaDrive" ModuleClassName="Sonic The Hedgehog 2 (W) (REV01) [!].gen" ModuleInstanceName="Sonic The Hedgehog 2 (W) (REV01) [!].gen" ProgramModule="1">
	<System.ImportConnector ConnectorClassName="CartridgePort" ConnectorInstanceName="Cartridge Port" />
	<System.ImportBusInterface ConnectorInstanceName="Cartridge Port" BusInterfaceName="BusInterface" ImportName="BusInterface" />
	<System.ImportSystemLine ConnectorInstanceName="Cartridge Port" SystemLineName="CART" ImportName="CART" />
	<Device DeviceName="ROM16" InstanceName="ROM" BinaryDataPresent="1" SeparateBinaryData="1">D:\Emulation\Roms\Mega Drive\FULL Sega Genesis -- Mega Drive -- 32X (GoodGen 3.00)[GoodMerged]\Extracted\Sonic The Hedgehog 2 (W) (REV01) [!].gen</Device>
	<BusInterface.MapDevice BusInterfaceName="BusInterface" DeviceInstanceName="ROM" CELineConditions="FCCPUSpace=0, CE0=1" MemoryMapBase="000000" MemoryMapSize="100000" AddressMask="1FFFFF" AddressDiscardLowerBitCount="1" />
	<System.SetLineState SystemLineName="CART" Value="1" />
</Module>
What happens here is fairly straightforward. I import the "CartridgePort" connector defined in the system, map a logical 16-bit ROM device to the bus, and assert the "CART" line on the connector to indicate a cartridge is present. Things can get more complex though. For example, here's what gets generated for Sonic 3:

Code: Select all

<Module SystemClassName="SegaMegaDrive" ModuleClassName="Sonic The Hedgehog 3 (E) [!].gen" ModuleInstanceName="Sonic The Hedgehog 3 (E) [!].gen" ProgramModule="1">
	<System.ImportConnector ConnectorClassName="CartridgePort" ConnectorInstanceName="Cartridge Port" />
	<System.ImportBusInterface ConnectorInstanceName="Cartridge Port" BusInterfaceName="BusInterface" ImportName="BusInterface" />
	<System.ImportSystemLine ConnectorInstanceName="Cartridge Port" SystemLineName="CART" ImportName="CART" />
	<Device DeviceName="ROM16" InstanceName="ROM" BinaryDataPresent="1" SeparateBinaryData="1">D:\Emulation\Roms\Mega Drive\FULL Sega Genesis -- Mega Drive -- 32X (GoodGen 3.00)[GoodMerged]\Extracted\Sonic The Hedgehog 3 (E) [!].gen</Device>
	<Device DeviceName="RAM8" InstanceName="SRAM" MemoryEntryCount="200" RepeatData="1" PersistentData="1" BinaryDataPresent="1">FF</Device>
	<BusInterface.MapDevice BusInterfaceName="BusInterface" DeviceInstanceName="ROM" CELineConditions="FCCPUSpace=0, CE0=1" MemoryMapBase="000000" MemoryMapSize="200000" AddressMask="3FFFFF" AddressDiscardLowerBitCount="1" />
	<BusInterface.MapDevice BusInterfaceName="BusInterface" DeviceInstanceName="SRAM" CELineConditions="FCCPUSpace=0, CE0=1, R/W=1" MemoryMapBase="200000" MemoryMapSize="400" AddressLineMapping="[09][08][07][06][05][04][03][02][01]" DataLineMapping="[07][06][05][04][03][02][01][00]" />
	<BusInterface.MapDevice BusInterfaceName="BusInterface" DeviceInstanceName="SRAM" CELineConditions="FCCPUSpace=0, CE0=1, R/W=0, LWR=1" MemoryMapBase="200000" MemoryMapSize="400" AddressLineMapping="[09][08][07][06][05][04][03][02][01]" DataLineMapping="[07][06][05][04][03][02][01][00]" />
	<System.SetLineState SystemLineName="CART" Value="1" />
	<System.ImportSystemSetting ConnectorInstanceName="Cartridge Port" SystemSettingName="Region" ImportName="Region" />
	<System.SelectSettingOption SettingName="Region" OptionName="E" />
</Module>
Similar to before, but now we also map in an 8-bit SRAM module. This game also contains a specific region code, in this case a European setting. We also need to advertise this back to the system, so that it can region switch if it's configured to do so. Things can get even more complex though. If Sonic & Knuckles lock-on was properly implemented, that game would actually involve two separate ROMS, as well as defining a new CartridgePort connector chained off the cart, to which another game module could be loaded. All this system-specific information is contained in MDExtensions.dll however, and all that does is output an Exodus-compatible xml module like this and load it into the system. You could hand-craft or hand-edit a module like this yourself and load it directly, allowing you to create your own Mega Drive cartridges, potentially with your own custom hardware, and have Exodus work with it without needing to modify the emulator itself, which is something no other Mega Drive emulators can do.

This makes the seemingly simple addition of command line arguments a bit more complex though. You can add them, but the Exodus process itself can't understand the request to "load a ROM". Exodus can "load a module", and if you've already got a generate XML file ready to go you can load with that, but to load a raw ROM file on the command line you'll need to expose functions over the plugin API to deal with command line arguments, and make it possible for plugins to register their own arguments that they handle. On a similar line, I'd also like to add functions to support plugins registering custom hotkeys, a lack of which is the reason why the "Open Mega Drive ROM" menu option doesn't currently have a keyboard shortcut.

ryanfaescotland
Interested
Posts: 48
Joined: Mon Feb 09, 2015 10:46 pm
Contact:

Re: Load roms externally?

Post by ryanfaescotland » Tue Apr 30, 2019 8:23 am

You know it's funny you should mention all this Nemesis as the other day I was mulling over the idea of loading carts in Exodus and I was actually thinking that the in keeping way to do it wouldn't be to 'load a rom' but would in fact be to code up all the chips on the cart and connect that up. So to handle things like Street Fighter 2 (which from my memory had extra chips on board) you wouldn't code the handling of that directly into the emulator like most but instead code up the logic for each of the components and fit them together. This would in turn make it possible to use these extra chips in other games if you were so inclined.

Pretty interesting idea, could make for some fun exploration.

Thanks for all the advice on the challenges with adding command line support. Still not had a chance to look into it in earnest.

Post Reply