The VirtualAcorn products are built around three central concepts: Interfaces, Components and Models.
A typical VirtualAcorn can run one Model at a time. The model contains all the components that comprise a particular machine including processors, busses, keyboards, display etc. Many of these components are specified in a user editable model configuration file. Others are added by the emulator shell so it can control, or be controlled, by the model.
Components typically encapsulate a feature of the machine such as a processor or bus. They are constructed and connected to other components in a well defined order. Each component may export a number of interfaces to which other components may connect. Thus a well connected model can be built.
Interfaces are collections of functions and sometimes data. E.g. the physical bus exports and interface to allow the processor to read/write from the bus and also exports an interface to allow devices to insert themselves on the bus.
Many of these API's are exposed in the SDK for use by plugins.
Component construction/destruction.
The emulator will start and certain UI components will register global components, visible in all models.
The model builder will read all model files and create an associated component for each [] entry. This behaviour may change in future but for now all components should perform minimal initialisation in the C++ constructor.
The user will select which model to use.
The Init() method for each global component is called
The Init() method for each model component is called. Typically models will create structures and possibly add other dynamically created components to the model. These will in turn have their Init() method called. Components should also export any public interfaces at this time.
The Connect() method for each global component is called.
The Connect() method for each model component is called. Components should query public interfaces of other components using FindInterface() and register themselves with those interfaces as appropriate (e.g. bus devices register themselves with the physical bus). The
The Reset() method for all components is called. Components should reset their internal state The PostReset() method for all components is called. Components can set state in other components. The Start() method is called. background threads can be started here but events are preferred. Run() is called on the first processor found.
At this point the model is running.
Deconstruction is pretty much the reverse of this using Stop(), Disconnect(), Cleanup() and the standard destructor.
The SDK
The current SDK provides three features:
For the time being, most plugins should stick to using the C++ classes as they make it quite clear how the interfaces should be used. The classes add very little overhead to the plugin api.
There are currently three example plugins. An FPA10 coprocessor, a simple podule and a quite complex podule. They demonstrate most of the features of the plugin interface.
Special points to note:
All plugins need to be compiled using fastcall rather than cdecl. You should link against retail versions of MFC if you use MFC.
Plugin files
Each plugin should go in its own folder in the Plugins folder. The generated dll should have the same name as the plugin folder. The plugin component can be added to the model file as [component] followed by any parameters.
VirtualAcorn