Welcome

Welcome to the Exodus SDK support documentation. The goal of this documentation is to provide all the information necessary to understand the architecture and design of the Exodus emulation platform, and how to use the provided APIs and tools to build new emulation cores, and add more debug and development features to existing cores, or the platform itself.

This documentation is a work in progress, and will continue to be expanded and improved as this project advances. The very latest version of this documentation can be built as part of the Exodus source repository. A periodically updated version of the documentation will also be published online at the project website http://www.exodusemulator.com.

Future Changes

Please note that although the Exodus API has a versioning system for individual interfaces, and will in the future provide full API backwards compatibility between versions, as this is a very early release of the API, and there is at this time no known usage of this API outside of the Exodus repository itself, the project lead reserves the right to break compatibility with existing code or existing binaries between versions. This documentation will note areas of the API that are expected to change in the near future. Feel free to open a discussion on the support forums you have any questions or concerns about this.


Overview of Exodus SDK

Description

The Exodus SDK is a set of support libraries that allow communication with the Exodus Platform. All communication between plugins and the platform itself happens through a set of pure virtual interfaces, which allows plugins to be developed, compiled, and deployed separately from the platform itself.

Note that the Exodus Platform itself is also a separate component, which is isolated from the platform and user interface. The SDK also contains the necessary interfaces to communicate with the Exodus Platform and implement an overall user interface to manage it.

Concepts

  • System Model
  • Plugin Model
  • Timing Model
  • Exported Interfaces

Interface Libraries

  • DeviceInterface
  • ExtensionInterface
  • SystemInterface

Base Class Libraries

  • Device
  • Extension
  • Processor

Utility Libraries

  • GenericAccess
  • TimedBuffers


Exodus Plugin Model

Description

Devices and Extensions

Creation and Initialization

See also


DeviceInterface Library

Description

Status of the library


IDevice interface

Description

The IDevice interface is the primary interface which exposes devices, such as processors, memory, peripherals, etc, to the emulation environment. A device must implement this interface in order to be compatible, although it is better to derive from the Device base class instead, which contains a default implementation of this interface. Many devices only need to implement a few of these methods in order to actually perform the tasks they need to do, so it is better to use this base class and override just the methods that need to be defined for a given device.

Note that this interface is designed to be passed across DLL boundaries, so it must meet the requirements of a Shared Interface.

Initialization functions

 | Name | Description
Public member | BindToSystemInterface | Called by the system to bind the device to the ISystemDeviceInterface object
Public member | BindToDeviceContext | Called by the system to bind the device to its IDeviceContext object
Public member | Construct | Allows a device to load additional parameters which control its construction, as they have been specified in the module file which has created this device instance.
Public member | BuildDevice | Allows devices to perform additional one-time construction tasks during the module load process.
Public member | ValidateDevice | Allows a device to validate its current state and connection to other devices, as a final check before the device is considered successfully loaded.
Public member | Initialize | Is called to instruct a device to initialize its internal state back to a state consistent with a cold-boot.

Reference functions

 | Name | Description
Public member | AddReference | Allows a device to reference another element in the system. References are the means by which devices are able to be associated with other system components. Objects of type IDevice, IExtension, IBusInterface, and IClockSource can be referenced.
Public member | RemoveReference | Removes a reference previously accepted by a successful call to the AddReference method

Device context functions

 | Name | Description
Public member | GetDeviceContext | Returns the IDeviceContext object associated with this device
Public member | GetCurrentTimesliceProgress | Returns the progress this device has made through the current timeslice, in nanoseconds.

Suspend functions

 | Name | Description
Public member | UsesExecuteSuspend | Reports whether this device ever calls the SuspendTimesliceExecution method on the IDeviceContext object associated with this device.
Public member | UsesTransientExecution | Reports whether this device ever calls the SetTransientExecutionActive method on the IDeviceContext object associated with this device.

Execute functions

 | Name | Description
Public member | BeginExecution | Called by the system on each device when before system execution starts
Public member | SuspendExecution | Called by the system on each device when system execution is paused
Public member | ExecuteStep | Called by the system to advance execution on devices that return "Step" as the execution method from GetUpdateMethod
Public member | ExecuteTimeslice | Called by the system to advance execution on devices that return "Timeslice" as the execution method from GetUpdateMethod
Public member | ExecuteTimesliceTimingPointStep | Called by the system to step through a timing point for devices that return "Timeslice" as the execution method from GetUpdateMethod
Public member | GetNextTimingPointInDeviceTime | Called by the system to request a device to report when its next known timing point will occur
Public member | ExecuteRollback | Called by the system to request a device to rollback its execution state to the point it was at when the last call to ExecuteCommit occurred
Public member | ExecuteCommit | Called by the system to request a device to commit its current execution state, so that it can be restored if the ExecuteRollback is called.
Public member | GetUpdateMethod | Returns the update method the device uses to advance execution
Public member | SendNotifyUpcomingTimeslice | Reports whether the device wants the system to call the NotifyUpcomingTimeslice method before each system timeslice begins execution
Public member | NotifyUpcomingTimeslice | Called before each system timeslice begins execution, if this device returned true from the SendNotifyUpcomingTimeslice method.
Public member | SendNotifyBeforeExecuteCalled | Reports whether the device wants the system to call the NotifyBeforeExecuteCalled method before any devices execute the upcoming timeslice
Public member | NotifyBeforeExecuteCalled | Called before each device executes the upcoming timeslice, if this device returned true from the SendNotifyBeforeExecuteCalled method.
Public member | SendNotifyAfterExecuteCalled | Reports whether the device wants the system to call the NotifyAfterExecuteCalled method after all devices finish executing the last timeslice
Public member | NotifyAfterExecuteCalled | Called after all devices finish executing the last timeslice, if this device returned true from the SendNotifyAfterExecuteCalled method.
Public member | NotifyAfterExecuteStepFinishedTimeslice | Called on this device after it finishes executing the current timeslice

Name functions

 | Name | Description
Public member | GetDeviceImplementationName |
Public member | GetDeviceInstanceName |
Public member | GetFullyQualifiedDeviceInstanceName |
Public member | GetModuleDisplayName |
Public member | GetModuleInstanceName |
Public member | GetDeviceModuleID |

Savestate functions

 | Name | Description
Public member | GetScreenshot |
Public member | LoadState |
Public member | SaveState |
Public member | LoadPersistentState |
Public member | SavePersistentState |
Public member | LoadSettingsState |
Public member | SaveSettingsState |
Public member | LoadDebuggerState |
Public member | SaveDebuggerState |

CE line state functions

 | Name | Description
Public member | GetCELineID |
Public member | SetCELineInput |
Public member | SetCELineOutput |
Public member | CalculateCELineStateMemory |
Public member | CalculateCELineStateMemoryTransparent |
Public member | CalculateCELineStatePort |
Public member | CalculateCELineStatePortTransparent |

Memory functions

 | Name | Description
Public member | ReadInterface |
Public member | WriteInterface |
Public member | TransparentReadInterface |
Public member | TransparentWriteInterface |

Port functions

Name | Description
ReadPort |
WritePort |
TransparentReadPort |
TransparentWritePort |

Line functions

 | Name | Description
Public member | GetLineID |
Public member | GetLineName |
Public member | GetLineWidth |
Public member | SetLineState |
Public member | TransparentSetLineState |
Public member | RevokeSetLineState |
Public member | AdvanceToLineState |
Public member | AssertCurrentOutputLineState |
Public member | NegateCurrentOutputLineState |

Clock source functions

 | Name | Description
Public member | GetClockSourceID |
Public member | GetClockSourceName |
Public member | SetClockSourceRate |
Public member | TransparentSetClockSourceRate |

Input functions

 | Name | Description
Public member | GetKeyCodeID |
Public member | GetKeyCodeName |
Public member | HandleInputKeyDown |
Public member | HandleInputKeyUp |

See also

  • Device
  • IDeviceContext
  • IBusInterface
  • IExtension
  • IClockSource


IDeviceContext interface

Description

The IDeviceContext interface provides an interface to the device context for a given device. The system implements this device in an internal type, which is not exposed to any elements in the system. The purpose of the device context is to hold the current execution state for the associated device, and to manage the execution of that device. The target device for an IDeviceContext object can be retrieved by calling the GetTargetDevice method.

Timing functions

 | Name | Description
Public member | GetCurrentTimesliceProgress |
Public member | SetCurrentTimesliceProgress |

Control functions

 | Name | Description
Public member | DeviceEnabled |
Public member | SetDeviceEnabled |

Device interface

 | Name | Description
Public member | GetTargetDevice |
Public member | GetDeviceIndexNo |

System message functions

 | Name | Description
Public member | WriteLogEvent |
Public member | FlagStopSystem |
Public member | StopSystem |
Public member | RunSystem |
Public member | ExecuteDeviceStep |
Public member | GetFullyQualifiedDeviceInstanceName |
Public member | GetModuleDisplayName |
Public member | GetModuleInstanceName |

Suspend functions

 | Name | Description
Public member | UsesExecuteSuspend |
Public member | UsesTransientExecution |
Public member | TimesliceExecutionSuspended |
Public member | SuspendTimesliceExecution |
Public member | WaitForTimesliceExecutionResume |
Public member | ResumeTimesliceExecution |
Public member | TimesliceSuspensionDisabled |
Public member | TransientExecutionActive |
Public member | TransientExecutionActive |
Public member | TimesliceExecutionCompleted |

Dependent device functions

 | Name | Description
Public member | SetDeviceDependencyEnable |

See also

  • IDevice


IDeviceInfo interface

Description

The IDeviceInfo interface is used by the system to retrieve information on devices that are exposed by plugins. A plugin exports the GetDeviceEntry function, through which the system can retrieve information on the defined devices in that plugin by sending an IDeviceInfo object to that function to retrieve the device info.

Getters

 | Name | Description
Public member | GetAllocator | Gets a pointer to a function which will create a new object for the device when it is called
Public member | GetDestructor | Gets a pointer to a function which will delete a previously created object for the device when it is called
Public member | GetDeviceClassName | Gets the class name of the device
Public member | GetDeviceImplementationName | Gets the implementation name of the device
Public member | GetDeviceVersionNo | Gets the version number of the device
Public member | GetDeviceCopyright | Gets the copyright string for the device
Public member | GetDeviceComments | Gets the comment string for the device

Setters

 | Name | Description
Public member | SetDeviceSettings | Sets the commonly used device settings in one function call
Public member | SetDeviceAllocators | Sets the allocator and deallocator function pointers for the device
Public member | SetDeviceClassName | Sets the class name of the device
Public member | SetDeviceImplementationName | Sets the implementation name of the device
Public member | SetDeviceVersionNo | Sets the version number of the device
Public member | SetDeviceCopyright | Sets the copyright string for the device
Public member | SetDeviceComments | Sets the comment string for the device

See also

  • IDevice


IBusInterface interface

Description

The IBusInterface interface is the way devices communicate with other devices during execution. There are two primary methods of communication, the first and simplest being using the memory interface functions ReadMemory and WriteMemory. These methods implement high-level read and write bus operations in a simple and efficient way. The second method is using the line interface functions SetLineState and RevokeSetLineState. These methods implement low-level communication over individual lines, or grouped sets of individual lines.

Note that the IBusInterface interface has a major redesign in progress, in particular around the implementation of the line interface functions. The goal of the redesign is to improve the usefulness and efficiency of the line interface functions, and to allow line-level emulation of a bus to be mixed with high-level emulation of that bus. Lines will no longer be "set" to a boolean state, rather, they will be "driven" to a logic low or high state, or left floating. This will allow us to support tri-state lines, and correctly model the transition state for lines which have pull-up or pull-down behaviour when they are not being actively driven. The IBusInterface object itself will hold the current state of the lines, rather than each device holding its own state, which is currently the case. Additionally, devices will not receive notification of every change in line state the way they currently do, but rather, system modules will be able to define line "triggers", where when a line or several lines meet a set of conditions, a device-specific trigger is activated, and the device receives a notification that the trigger has occurred.

With this redesign, the high level memory interface functions will just become wrappers over the line interface functions, where sets of lines are mapped to address, data, and strobe lines through system XML and formed into buses, that can then be mapped to devices that want high level bus interfaces, or used at the line level by devices that work directly with lines.

Note that the port interface methods are deprecated, and will be removed as part of the bus redesign. The normal memory interface functions can be used to support port access, by using an interface number on the mapping which represents the port interface for that device.

Memory interface functions

 | Name | Description
Public member | ReadMemory |
Public member | WriteMemory |
Public member | TransparentReadMemory |
Public member | TransparentWriteMemory |

Port interface functions

Name | Description
ReadPort |
WritePort |
TransparentReadPort |
TransparentWritePort |

Line interface functions

 | Name | Description
Public member | SetLineState |
Public member | RevokeSetLineState |
 | AdvanceToLineState |

Clock source functions

 | Name | Description
Public member | SetClockRate |
Public member | TransparentSetClockRate |

See also

  • IDevice
  • IDeviceContext
  • IClockSource


IClockSource interface

Description

The IClockSource interface provides a way to manage clock sources within the system. The effective output rate of a clock source can be modified using methods on this interface, with the new clock rate propagated to all devices in the system that use this clock.

Clock type functions

 | Name | Description
Public member | GetClockType |

Clock frequency functions

 | Name | Description
Public member | SetClockFrequency |
Public member | SetClockDivider |
Public member | SetClockMultiplier |
Public member | TransparentSetClockFrequency |
Public member | TransparentSetClockDivider |
Public member | TransparentSetClockMultiplier |

See also

  • IDevice
  • IBusInterface


ISystemDeviceInterface interface

Description

The ISystemDeviceInterface provides a means for devices to communicate directly with the Exodus Platform. The system communicates with devices over the IDevice interface, and devices communicate back with the system over this interface.

Path functions

 | Name | Description
Public member | GetCapturePath |

Logging functions

 | Name | Description
Public member | WriteLogEvent |

System execution functions

 | Name | Description
Public member | FlagStopSystem |
Public member | IsSystemRollbackFlagged |
Public member | SystemRollbackTime |
Public member | SetSystemRollback |
Public member | PerformingSingleDeviceStep |

Input functions

 | Name | Description
Public member | TranslateKeyCode |
Public member | TranslateJoystickButton |
Public member | TranslateJoystickAxisAsButton |
Public member | TranslateJoystickAxis |
Public member | HandleInputKeyDown |
Public member | HandleInputKeyUp |
Public member | HandleInputAxisUpdate |
Public member | HandleInputScrollUpdate |

See also

  • IDevice


Data class

Description

The Data class is designed to simplify working with binary and integer data with a fixed bit count. Rather than using raw integer types with lots of bitwise AND, OR, and shift operations to set or test bit segments within integer types, the Data class provides functions to simplify these tasks, making the operation clearer and less error prone. Functions are also provided to test advanced properties of integer types, such as parity and the highest set bit number, and conversion functions are provided to perform tasks like sign extension. An extensive set of custom operators are also provided to allow Data objects to be operated on directly in the same way as native integer types. The bit count of the Data objects are taken into account when calculating the results of any operations.

Constructors

 | Name | Description
Public member | Data |

Management functions

 | Name | Description
Public member | Resize |

Container size properties

 | Name | Description
Public member | GetBitMask |
Public member | GetMaxValue |
Public member | GetMaxValue |
Public member | GetHexCharCount |
Public member | GetBitCount |

Data conversion functions

 | Name | Description
Public member | Convert |
Public member | SignExtend |

Data segment extraction/insertion

 | Name | Description
Public member | GetData |
Public member | SetData |
Public member | MSB |
Public member | LSB |
Public member | GetBit |
Public member | SetBit |
Public member | GetByteFromBottomUp |
Public member | SetByteFromBottomUp |
Public member | GetByteFromTopDown |
Public member | SetByteFromTopDown |
Public member | GetDataSegment |
Public member | SetDataSegment |

Upper/Lower half functions

 | Name | Description
Public member | GetUpperHalf |
Public member | GetLowerHalf |
Public member | SetUpperHalf |
Public member | SetLowerHalf |

Upper/Lower bit functions

 | Name | Description
Public member | GetUpperBits |
Public member | GetLowerBits |
Public member | SetUpperBits |
Public member | SetLowerBits |

Data properties

 | Name | Description
Public member | Even |
Public member | Odd |
Public member | Zero |
Public member | NonZero |
Public member | Negative |
Public member | Positive |
Public member | ParityEven |
Public member | ParityOdd |
Public member | GetSetBitCount |
Public member | GetHighestSetBitNumber |
Public member | GetHighestSetBitMask |
Public member | GetLowestSetBitNumber |
Public member | GetLowestSetBitMask |

Custom operators

 | Name | Description
Public member | operators |


ExtensionInterface Library

Description

Status of the library


SystemInterface Library

Description

Status of the library


Device Library

Description

The Device library provides a default base class implementation of the IDevice interface. This library provides the Device base class, which can be inherited from by device emulation cores to simplify their implementation. Note that use of the Device library is optional, and the Exodus Platform isn't even aware this library exists. A device core is free to implement the IDevice interface directly, and not link to this library at all.

Status of the library

This library is stable, and largely trivial. Please refer to the DeviceInterface library for the interfaces that affect this base class library.

See also

  • DeviceInterface


Device base class

Description

The Device class provides a default implementation of the IDevice interface. It is provided simply as a convenience to avoid the need for a device to provide an implementation for each pure virtual function in the IDevice interface, even if many of those methods are not required. Devices are free to derive from this base class, or to implement the IDevice interface directly.

As this class doesn't add any functionality that isn't present in the IDevice interface, please refer to the documentation on that interface for further info.

See also

  • IDevice


Extension Library

Description

The Extension library provides a default base class implementation of the IExtension interface. This library provides the Extension base class, which can be inherited from by extension plugins to simplify their implementation. Note that use of the Extension library is optional, and the Exodus Platform isn't even aware this library exists. An extension is free to implement the IExtension interface directly, and not link to this library at all.

Status of the library

This library is stable, and largely trivial. Please refer to the ExtensionInterface and DeviceInterface libraries for the interfaces that affect this base class library.

See also

  • DeviceInterface
  • ExtensionInterface


Extension base class

Description

The Extension class provides a default implementation of the IExtension interface. It is provided simply as a convenience to avoid the need for an extension to provide an implementation for each pure virtual function in the IExtension interface, even if many of those methods are not required. Extensions are free to derive from this base class, or to implement the IExtension interface directly.

As this class doesn't add any functionality that isn't present in the IExtension interface, please refer to the documentation on that interface for further info.

See also

  • IExtension


Processor Library

Description

Status of the library


TimedBuffers Library

Description

Status of the library


GenericAccess Library

Description

Status of the library


Overview of Support Libraries

Description

The support libraries for the Exodus project are libraries that were written to make performing various programming tasks easier, but are technically issues outside the bounds of the Exodus project itself. Ideally, none of these libraries would exist as part of this project at all, and would instead be provided as part of the C++ STL libraries, or a widely used and accepted set of third party libraries like boost. Where no suitable language or third party library has been available to perform a particular task however, or where the solutions provided by them were deemed to be poor, incomplete, or too low level for us to use directly within our code, support libraries have been created for use within Exodus. If suitable third party libraries or language features are added or identified in the future that could replace a custom support library here, it may be appropriate to deprecate or remove that library.

Note that unlike the Core Libraries, our support libraries do not need to be platform independent. In fact, some libraries may exist for the sole purpose of assisting development on a particular platform. Where it is technically feasable and sensible to do so however, our support libraries aim to provide platform independent APIs, and should always keep any references to non-platform third party libraries hidden internally, so that our application doesn't become tightly coupled to third party APIs over which we have no control.

Support Libraries

  • AudioStream
  • CallbackSupport
  • DataConversion
  • Debug
  • HierarchicalStorage
  • Image
  • MarshalSupport
  • Stream
  • ThinContainers
  • ThreadLib
  • WindowsControls
  • WindowsSupport
  • ZIP


AudioStream Support Library

Description

The AudioStream support library simplifies the playback of audio output streams on Windows. Experience has shown that it is very difficult to achieve low-latency continuous audio playback on Windows where the audio stream is being generated at runtime. Audio output is fairly simple if a large number of samples can be buffered by Windows for playback. This is problematic for emulation however, as the larger the amount of audio data that is buffered, the further behind the audio playback is from the time at which the content was actually generated, which is undesirable, as even with quite small buffer sizes, the user can notice lag between their input or graphical output and the audio output. The AudioStream class is provided to achieve low latency audio output on Windows without the user having to worry about how that is achieved. This class also handles issues of sample rate conversion.

Public Members

  • AudioStream

Status of the library

The AudioStream library itself is fairly stable, although there are missing features. The AudioStream class doesn't currently provide any way to enumerate the list of available audio output devices, or to detect their capabilities. Devices which currently use the AudioStream class have to request the output sample rate to use, but don't actually know what devices are present in the system, and what output sample rates they support. The AudioStream class also doesn't provide any way to specify the output device to use, and relies on Windows to select the default compatible device based on the specified output audio settings. The AudioStream class should be extended to allow enumeration and selection of individual audio output devices.

There is also a problem with the level at which the AudioStream library is currently being used. Right now, our audio devices in Exodus directly bind to this library and create independent audio output streams driven directly by the devices. This will change in the future, once Exodus provides a framework for handing over management of filtering, mixing, and output of audio and video streams to the platform itself. This is essential in order to properly manage analog mixing and filtering issues in particular, which are system specific concerns. Once this framework is implemented, individual devices shouldn't need to directly work with this library.

Note that there is also some thought that this library could be merged into WindowsSupport, although at this time it seems like a better idea to keep it as a separate library.

Achieving low latency

For emulation purposes, when it comes to latency of audio playback, the ideal scenario is as close to zero latency as possible, where samples are sent directly to your speakers almost the instant they're generated. On the real hardware, the audio output was effectively zero latency. Due to the nature of emulation however, and the fact that the samples are not generated at a constant rate as they would have been on the real hardware, at least some buffering is required. We can't let the buffer get too big though, or the user will start to notice the audio lagging. Although a very small buffer size is desirable, on Windows, buffering a very small amount of audio data makes continuous playback much more difficult to manage, as buffer underruns happen very easily with no warning, and always result in audible clicks and pops during audio playback when they occur. The provided APIs are quite limited and awkward to work with, and in some cases don't work properly at all. In addition to the usual hassles of achieving low latency audio playback on Windows, emulation adds a rather unique problem on top of this that makes things much harder. The nature of emulation means that the rate at which audio data is generated is unpredictable and unstable. Not only can the emulation lag by an unpredictable amount that can change from moment to moment, it's also possible for the emulation to run faster than normal speed, especially when the user has disabled speed limiting, and again the rate at which it can run faster than normal can vary from moment to moment. In order to handle these speed issues on Windows, we need to carefully manage the Windows audio buffer, and feed it data as we recieve it, but not too much or too little at a time. We need to maintain at least two buffered blocks of sample data in the Windows playback queue at all times, one being played, and another waiting to be played, in order to prevent buffer underruns that could cause clicks and pops. If the sample generation is lagging, and we run out of sample data to feed Windows, we grab the last sample in the last buffer, and generate a dummy buffer filled with this sample. This prevents clicks or pops on the audio output. If we're being sent more sample data than we can play in realtime, we need to ensure the audio playback doesn't fall too far behind by discarding audio samples where required.

Sample rate conversion

Computer audio hardware is extremely limited in the output sample rates they support. Often the output sample rates that are possible on standard computer hardware differ from the effective output rates of hardware devices being emulated. In the interests of accuracy and audio quality, emulation cores for audio devices in Exodus should not attempt to decimate or reduce the number of samples being generated, but rather, that issue should be left until playback to manage. This also assists with debug features like audio logging to a file, where the output stream can be saved at its original sample rate, without filtering or decimation. The AudioStream class performs sample rate conversion internally as sample data is recieved, in order to adapt it to the capabilities of the output device.


CallbackSupport Support Library

Description

The CallbackSupport library provides classes to make callbacks easier to manage in C++. Ccurrently, the library provides a set of types to assist in implementing an observer pattern, where interested parties can register themselves as observers of an entity, and be notified when an event occurs that observers should be notified about.

Public Members

  • IObserverCollection
  • IObserverSubscription
  • ObserverCollection
  • ObserverSubscription

Status of the library

This library is relatively new, although it is reasonably well implemented. The current implementation is not feature complete however. One significant improvement would be to template the IObserverCollection and IObserverSubscription interfaces using variadic templates to allow an arbitrary number and type of arguments to be passed to observers when they are notified.


DataConversion Support Library

Description

The DataConversion library provides a set of general conversion routines to and from text for integers, floating point, and boolean types. The library also provides some text to text conversion routines. All conversion functions adopt the same conventions, which makes it easy to convert betwen types and understand what the output of various conversions will be.

All integer conversion functions support a unified prefix notation for distinguising the base encoding of any arbitrary number from a string. These prefixes are adopted based on the prevailing conventions used in various programming languages and markup systems. Only one prefix is used when converting to a string, but when loading from a string, several forms are permitted. The following list shows the list of supported prefixes for converting integers from strings. The prefix used for saving to string is the first one shown for each base encoding.

Base 16: 0x????, 0X????, 0h????, 0H????
Base 10: 0d????, 0D????
Base 8:  0o????, 0O????, 0q????, 0Q????
Base 2:  0b????, 0B????

Note that we don't support any postfix base encoding forms, because they can be ambiguous with unqualified number encodings from other bases. Using the 'b' and 'd' characters in particular as postfixes would conflict with base 16 encoding, but other encoding schemes like base 32 encoding that could be added later would conflict with all postfixes. There are various other language conventions that have also been rejected, such as a leading '0' in C++ representing a base 8 number. Using the prefixes that have been specified, it is always safe to evaluate qualified or non-fixed length unqualified strings containing integers.

Public Members

Boolean Conversion

 | Name | Description
Public member | BoolToString | Converts a boolean into a string in the requested form
Public member | StringToBool | Attempts to convert a string into a boolean

Integer Conversion

 | Name | Description
Public member | HexNybbleToChar | Converts an integer of the range 0x0-0xF to a corresponding hexadecimal char
Public member | HexNybbleToWChar | Converts an integer of the range 0x0-0xF to a corresponding hexadecimal wchar_t
Public member | HexCharToNybble | Converts a hexadecimal digit from a char into an integer of the range 0x0-0xF, or 0x10 if the specified character is not a hexadecimal digit.
Public member | HexWCharToNybble | Converts a hexadecimal digit from a wchar_t into an integer of the range 0x0-0xF, or 0x10 if the specified character is not a hexadecimal digit.
Public member | IntToString | Converts an integer into a string, using the specified base encoding.
Public member | IntToStringBase16 | Converts an integer into a base 16 string, with control over type encoding and length.
Public member | IntToStringBase10 | Converts an integer into a base 10 string, with control over type encoding and length.
Public member | IntToStringBase8 | Converts an integer into a base 8 string, with control over type encoding and length.
Public member | IntToStringBase2 | Converts an integer into a base 2 string, with control over type encoding and length.
Public member | StringToInt | Attempts to convert a string into an integer, using the specified default base encoding if it isn't specified in the string.
Public member | StringToIntBase16 | Attempts to convert a base 16 number as a string into an integer
Public member | StringToIntBase10 | Attempts to convert a base 10 number as a string into an integer
Public member | StringToIntBase8 | Attempts to convert a base 8 number as a string into an integer
Public member | StringToIntBase2 | Attempts to convert a base 2 number as a string into an integer

Floating Point Conversion

 | Name | Description
Public member | FloatToString | Converts a single precision floating point number into a string in the requested form
Public member | StringToFloat | Attempts to convert a string into a single precision floating point number
Public member | DoubleToString | Converts a double precision floating point number into a string in the requested form
Public member | StringToDouble | Attempts to convert a string into a double precision floating point number

String Conversion

 | Name | Description
Public member | TokenizeString | Tokenizes the supplied string using the set of specified delimiter characters
Public member | CharToLower | Converts the target ASCII character to its lowercase equivalent. This function does not attempt to support Unicode characters.
Public member | CharToUpper | Converts the target ASCII character to its uppercase equivalent. This function does not attempt to support Unicode characters.
Public member | StringToLower | Converts all ASCII characters in the target string to their lowercase equivalent. This function does not attempt to support Unicode characters.
Public member | StringToUpper | Converts all ASCII characters in the target string to their uppercase equivalent. This function does not attempt to support Unicode characters.
Public member | StringToWString | Converts an std::string with ASCII encoding to an std::wstring. This function does not attempt to support non-ASCII characters.
Public member | WStringToString | Converts an std::wstring with ASCII encoding to an std::string. This function does not attempt to support non-ASCII characters.

Status of the library

This library originally grew as required, however it is now quite consistent in its use. There are some limitations regarding the output of floating point numbers at fixed lengths however, and these cannot be worked around without a major investment of work, due to limits of control around how both std::stringstream and printf perform floating point conversion. These issues will be fixed if they cause problems in the future.

Note that although what is currently in this library is fairly good, the library itself is not considered feature complete. There are many other conversion functions that may be added in the future as a need for them arises.


Debug Support Library

Description

The Debug library provides a set of classes and functions to assist with debugging, assertion testing, and runtime failure analysis.

Status of the library

This library is imatture and not very well thought out. There are some things in here that should probably be moved out into the WindowsSupport library. It might even be better to merge this entire library into that library.


HierarchicalStorage Support Library

Description

The HierarchicalStorage library is designed to support an abstract representation of a hierarchical data structure, where each node on the hierarchy can potentially contain child nodes, as well as an unlimited number of attributes in the form of a key/value pair, and a single block of arbitrary data associated with the nodes. This library allows a structure like this to be created, edited, saved, and loaded.

The primary input and output format of the HierarchicalStorage library is XML. Support for other formats has been considered in the design of the library however, and new input and output formats can easily be added without breaking compatibility with existing code.

This library is split into two halves, HierarchicalStorage and HierarchicalStorageInterface. This allows code which only needs to use these structures, not create the initial root definition of the structure itself, to include only the header files required to work with the structure. This reduces code linkage, encourages the use of the interface base types, and reduces compilation types and assembly sizes.

Public Members

HierarchicalStorageInterface Members

  • IHierarchicalStorageTree
  • IHierarchicalStorageNode
  • IHierarchicalStorageAttribute

HierarchicalStorage Members

  • HierarchicalStorageTree
  • HierarchicalStorageNode
  • HierarchicalStorageAttribute

Status of the library

This library is considered stable and complete. If support for more storage formats is desired in the future, extensions may be made to the library to implement that support, however this should not impact existing use.


Image Support Library

Description

The Image library is designed to simplify working with graphical images. The Image class is provided by this library, which allows images to be created and edited, and saved to or loaded from a variety of image formats. The IImage interface is provided to allow Image objects to be easily shared between assemblies.

This library is split into two halves, Image and ImageInterface. This allows code which only needs to use Image objects, not create them, to include only the header files required to work with the object. This reduces code linkage, encourages the use of the interface base types, and reduces compilation types and assembly sizes.

Public Members

ImageInterface Members

  • IImage

Image Members

  • Image

Status of the library

The Image library has a number of issues, and there are major changes planned for it in the future.

The current Image class was built heavily around the idea of loading and displaying images, and not as much around editing and creating them. As a result, the Image class is very slow and difficult to work with when actually trying to build image data. There is a future plan to build a Canvas class, which will allow advanced drawing operations, with other classes like a Pen, Brush, etc supporting advanced draw operations to it. If we create a Canvas class, there may not be any need for a separate Image class type.

The Image class as it stands also has a major issue around the use of third party libraries. Most of the libraries we include to add support for extra image formats are very large, and increase the size of the output assemblies significantly. There should be a way to separate the image file load and save routines from the Image class itself. Since that is mostly all that this class does, it makes sense that we would just provide a separate class to assist in image loading or saving with image files, and that this class would work with Canvas objects.

There is a further question around the idea of image sets, or in other words, files which contain multiple images. Icon files are an example of this, and it would be extremely useful to support them. It's only a small step from this to animated files like GIF images, or even actual video files, with audio tracks. With this in mind, the future of this library is probably as some kind of MediaSupport library, with support for all kinds of image and sound data formats, both creation and editing, as well as saving and loading. Any refactor of this library should consider this as the logical future direction we should head towards.


MarshalSupport Support Library

Description

The MarshalSupport library is an advanced library which provides easy, and in most cases transparent, exchange of objects between assemblies in C++, even if the sender and receiver represent the object differently. This library is particularly good for sending STL objects, or custom types that contain STL objects, across pure virtual interfaces that are being exchanged between assemblies. This is something that is extremely difficult to achieve in C++, and that the language provides no support for. The MarshalSupport library solves this problem comprehensively for any C++03 conformant compiler onwards, and allows exchange of any types between assemblies over pure virtual interfaces, where the assemblies support at least enough ABI compatibility to exchange pure virtual interfaces.

Public Members

Marshal Operators

  • Marshal::In
  • Marshal::Out
  • Marshal::InOut
  • Marshal::Ret

Marshal Classes

  • IMarshalSource
  • IMarshalTarget
  • MarshalSource
  • MarshalTarget

Status of the library

This library is in an extremely advanced and mature state, with a high level of optimization in place, as well as extensive cross-compiler testing having been performed. A full set of unit tests has also been developed. This library is considered stable and available for use in all areas of code.

The only planned future changes to this library are to add support for new container types. Full support for C++11 container types is provided currently, with the exception of std::pair and std::tuple, both of which we should support in the future. The C++14 standards and onwards have not been considered yet.


Stream Support Library

Description

The Stream library is designed to comprehensively handle access to free-form buffers of data, making it easy to extract or insert either text or binary data in the buffer, with advanced control over issues such as text encoding and byte order, so that types can be easily read in using settings are required. High level and low level access is supported, with abstract stream operator support through the ViewBinary and ViewText classes, or direct reading of primitive types at the stream level itself.

Two generic interfaces are provided by the Stream library: IStream and IStreamNonSeekable, to support streams which either do or do not support seek operations. The use of pure virtual interfaces allows streams to be defined in one assembly and safely shared with other assemblies.

This library is split into two halves, Stream and StreamInterface. This allows code which only needs to use streams, not create them, to include only the header files required to work with the stream. This reduces code linkage, encourages the use of the interface base types, and reduces compilation types and assembly sizes.

Public Members

StreamInterface Members

  • IStream
  • IStreamNonSeekable
  • ViewBinary
  • ViewText

Stream Members

  • File
  • Buffer
  • WAVFile
  • Stream

Status of the library

The Stream library is stable and mature, with no significant work planned at this stage. There is some future work to be done regarding the handling of unicode characters however. The Stream library currently assumes wchar_t to use UTF-16 encoding, which is not true on all platforms. There was no platform independent way of handling Unicode text in C++ at the time this library was created however. With C++11, we now have the Unicode character types char16_t and char32_t which will allow us to support Unicode text properly in a plaform independent way, however these character types are still not properly supported in Visual Studio 2013. When Visual Studio fully supports the Unicode character types, we should drop the IStream::UnicodeCodePoint type, and use the char32_t type for all Unicode string encoding work. We should also extend encoding support to all Unicode encodings. This will make our IStream interface fully platform independent, and give more options for text encoding.


ThinContainers Support Library

Description

This library provides a limited set of containers that have been specifically engineered to provide the most performance and space efficient containers possible, at the cost of usability. These containers are essentially convenient thin structures over raw memory buffers, and are not intended for general use. These containers were designed and written specifically for the BusInterface class after extensive profiling and thought, to provide high speed access to the very large and open-ended bus mapping information, which is one of the most critical components in the performance of the emulator.

Public Members

  • ThinVector
  • ThinList
  • ThinListDouble
  • ThinListContainer
  • ThinListDoubleContainer

Status of the library

The containers provided in this library achieve what they were written to do. No more changes are intended to be performed to add features or improve usablity.


ThreadLib Support Library

Description

This library supplies classes and functions to assist with threaded programming.

Status of the library

This entire library is deprecated and scheduled for removal. This library is mostly a throwback to times before the C++11 standard, when there was no STL support for threading, and we were experimenting with low-level implementations of our own locking mechanisms to give a performance edge over boost. The real world gains were minimal. With C++11 support for threading, and low-level synchronization primitives, there's little need for this library anymore. When we have C++14 support for std::shared_mutex, we'll no longer be dependent on the ReadWriteLock class provided by this library, at which point the entire library should be removed. There's no confirmation yet on when std::shared_mutex support is planned for Visual Studio.

It should be noted that the PerformanceTimer class in this library, despite being a very old class, is still the synchronization mechanism that Exodus uses to keep execution running in time. We should completely re-evaluate the method this class uses to maintain synchronization, and consider rolling this functionality out of a separate class and directly into the function that controls system execution. This may improve performance, and it will make the behaviour of the main system loop more obvious, and easier to follow and modify.


WindowsControls Support Library

Description

The WindowControls support library provides a set of custom Win32 controls that are designed to assist when building views.

Public Members

Layout Controls

  • LayoutGrid
  • ScrollViewer
  • StackPanel
  • DockPanel
  • DockingWindow
  • DashboardWindow

Document Controls

  • DataGrid
  • HexEdit

Status of the library

The library is generally stable, and the controls are considered suitable for general use, although not all the controls are currently considered to be feature complete.

There is a pending task which involves changing naming conventions for messages and classes in this library, as well as the possibility of building high level functions for messaging that will handle the use of the Win32 SendMessage API internally, although window messages will still be able to be sent directly if desired. This change will impact the use of this library for all types, breaking existing code that uses this library. Users of this library should be aware that this change will occur sooner or later.


WindowsSupport Support Library

Description

The WindowsSupport library is a Windows-specific library that has been written to provide more convenient access to the Win32 API. The intention of this library is not to wrap the Win32 API, but rather, to include its standard headers with the necessary preprocessor macros defined first, and to suppliment the Win32 library for functions that are particularly hard to use by default, or are used often enough for a simpler wrapper for them to be convenient. Many of the wrappers added here are designed to allow strings to be worked with as std::wstring objects rather than raw character buffers, which simplifies the use of many functions. All places in code should include this library rather than directly including the windows.h header file.

Status of the library

This support library has not been designed as such, it is simply viewed as a set of convenient extensions to the Win32 API, which have been added to as needed. It is not currently formally documented, and a review of all existing functions would be appropriate before attempting to do this. It is worth noting that it may also be appropriate to shift all the functions in this library into a namespace, to explicitly separate them from the global scope. Users of the library could apply a using statement if they wanted to be able to use the Win32 function wrappers without qualifying them with the namespace.


ZIP Support Library

Description

The purpose of this library is to provide an easy way to read and write compressed ZIP files.

Status of the library

This entire library needs to be deprecated, and a new general "CompressionSupport" library created to replace it, which can provide an abstract way of working with the concept of a file library, with support for multiple forms of compression, not just ZIP compression. The support for file library compression should also just provide support for these high level container formats like ZIP, while actual lower level data compression algorithms, like deflate, or any other supported compression method, should be exposed through generic functions that operate on data streams, like we currently have for deflate compression in this ZIP support library.

Since this library is intended to be replaced with a better support library, it is not currently documented here.


AddReference method

Description

The AddReference method allows a device to reference another element in the system. References are the means by which devices are able to be associated with other system components. Objects of type IDevice, IExtension, IBusInterface, and IClockSource can be referenced.

Usage

virtual bool AddReference(const std::wstring& referenceName, IDevice* target);
virtual bool AddReference(const std::wstring& referenceName, IExtension* target);
virtual bool AddReference(const std::wstring& referenceName, IBusInterface* target);
virtual bool AddReference(const std::wstring& referenceName, IClockSource* target);

Argument list

referenceName [std::wstring]
Name which identifies this reference to the device. Reference names are specific to the device that the reference is being added to, and supported reference names, and the purpose of each reference, should be clearly documented for each device.
target [IDevice / IExtension / IBusInterface / IClockSource]
The object being referenced. A pointer is passed in to this object, and it is perfectly valid, and expected, for the device to keep a reference to the target object. If the referenced object is removed from the system, the RemoveReference method will be called before the target object is destroyed. Note that RemoveReference is not guaranteed to be called for all existing references before a device which has added references to other devices is destroyed, although any remaining references are guaranteed to still be valid at the time the destructor is run.

Return value

[bool]
True if the reference was successfully added by the target device, false otherwise.

See also

  • RemoveReference
  • IDevice
  • IBusInterface
  • IExtension
  • IClockSource


BeginExecution method

Description

The BeginExecution method is called by the system on each device in the system when system excution is about to begin. Devices can use this method to start worker threads for example, or perform any kind of initialization that is useful to perform before execution begins. When system execution is paused, the corresponding SuspendExecution method is called.

Usage

      virtual void BeginExecution();

See also

  • IDevice
  • SuspendExecution


BindToDeviceContext method

Description

The BindToDeviceContext method is called once during the creation of the device object, to pass in the instance of the IDeviceContext object which has been allocated for this device. The DeviceContext object manages the execution of this device, and stores information on its current execution state. See the Plugin Model document for more information on the role of the IDeviceContext interface, and the stages of device initialization.

Note that the Device base class implements this method, and stores a reference to the object. If a device derives from this base class, it can retrieve the object by calling the GetDeviceContext method on the Device base class.

Usage

      virtual bool BindToDeviceContext(IDeviceContext* adeviceContext);

Argument list

adeviceContext [IDeviceContext*]
The instance of the IDeviceContext object which has been created to manage this device

Return value

[bool]
True if the interface was bound successfully, false otherwise. If a device returns false from this method, the creation of the device object will be considered to have failed, and the destructor of the device object will immediately be called.

See also

  • IDeviceContext
  • IDevice
  • Plugin Model


BindToSystemInterface method

Description

The BindToSystemInterface method is called once during the creation of the device object, to pass in the instance of the ISystemDeviceInterface object to use for communication with the system. Devices are free to keep a reference to this interface for the lifetime of the device object. See the Plugin Model document for more information on the stages of device initialization.

Note that the Device base class implements this method, and stores a reference to the object. If a device derives from this base class, it can retrieve the object by calling the GetSystemInterface method on the Device base class.

Usage

      virtual bool BindToSystemInterface(ISystemDeviceInterface* asystemInterface);

Argument list

asystemInterface [ISystemDeviceInterface*]
The instance of the ISystemDeviceInterface object for use in this device

Return value

[bool]
True if the interface was bound successfully, false otherwise. If a device returns false from this method, the creation of the device object will be considered to have failed, and the destructor of the device object will immediately be called.

See also

  • ISystemDeviceInterface
  • IDevice
  • Plugin Model


BuildDevice method

Description

The BuildDevice method is called during the creation of the device object, to give the device a chance to perform any initialization tasks that it needs to perform. It is better to use this method rather than the constructor as the point where any significant tasks, such as building lookup tables or allocating significant memory buffers. Like the constructor, this method is only called once for the lifetime of the object, and it is called shortly after the constructor is called, but unlike the constructor, virtual functions can be invoked safely, the BindToSystemInterface, BindToDeviceContext, and Construct functions have already been called, and this function can return false to indicate failure.

Usage

      virtual bool BuildDevice();

Return value

[bool]
True if the construction was successful, false otherwise. If a device returns false from this method, the creation of the device object will be considered to have failed, and the destructor of the device object will immediately be called.

See also

  • IDevice
  • BindToSystemInterface
  • BindToDeviceContext
  • Construct
  • Plugin Model


Construct method

Description

The Construct method is called during the creation of the device object, and allows custom XML data to be supplied for the device from the XML markup for the module that is using this device. The XML node that defines the device in the module is passed into this method. Device specific settings can be passed in through the system module and retrieved here. This is the best way to allow externally configurable device settings to be provided. This devices are free to use any custom attributes, data, or child nodes on the Device node in the system module.

Usage

      virtual bool Construct(IHierarchicalStorageNode& node);

Argument list

node [IHierarchicalStorageNode&]
The XML node which defined this device in the XML module definition

Return value

[bool]
True if the construction was successful, false otherwise. If a device returns false from this method, the creation of the device object will be considered to have failed, and the destructor of the device object will immediately be called.

See also

  • IDevice
  • Plugin Model


ExecuteStep method

Description

The ExecuteStep method is called during system execution for a device that has returned the "Step" execution method from GetUpdateMethod. When this method is called, the device should perform whatever logic is necessary to advance the device by the smallest indivisible operation step that device supports. This may mean advancing the device by a single internal cycle, or for a series of operations which are carried out in sequence which cannot be interrupted or altered by any external event.

This device must return a double value, which is the total time the device advanced in nanoseconds by the step the device just performed. This amount will be automatically added to the accumulated total of time advanced reported by the GetCurrentTimesliceProgress method. When the device reaches or passes the total amount of time allocated to the device in the current timeslice, the ExecuteStep method will no longer be called until all devices complete the timeslice, and a new timeslice begins.

Usage

      virtual double ExecuteStep();

Return value

[double]
The total time the device advanced in the executed update step, in nanoseconds.

See also

  • IDevice
  • GetCurrentTimesliceProgress


GetCurrentTimesliceProgress method

Description

The GetCurrentTimesliceProgress method should directly call and return the value returned by the GetCurrentTimesliceProgress method on the IDeviceContext object for this device. This method is only provided here for convenience and efficiency, due to the large number of times and places this value is retrieved for devices.

Note that the Device base class implements this method. If a device derives from this base class, it doesn't need to implement this method itself.

Usage

      virtual double GetCurrentTimesliceProgress() const;

Return value

[double]
The current progress of the device through the current timeslice, in nanoseconds.

See also

  • GetCurrentTimesliceProgress
  • IDeviceContext
  • IDevice
  • Plugin Model


GetDeviceContext method

Description

The GetDeviceContext method must return the IDeviceContext object that was passed into the device when the BindToDeviceContext method was called. When a device or extension needs the IDeviceContext instance for another device, it can call this method to retrieve the object.

Note that the Device base class implements this method. If a device derives from this base class, it doesn't need to implement this method, or the BindToDeviceContext method.

Usage

      virtual IDeviceContext* GetDeviceContext() const;

Return value

[IDeviceContext*]
The IDeviceContext object associated with the device

See also

  • IDeviceContext
  • IDevice
  • Plugin Model


GetUpdateMethod method

Description

GetUpdateMethod is called by the system to determine what kind of update method a device needs in order to advance its current execution state. Some devices are passive, and don't need to perform any execution steps of their own, they merely need to respond to input from other devices. Memory buffers are an example of this. Devices which need to initiate unsolicited contact with other devices however are considerd active devices, and will generally need an update method to be called to advance their execution state. The device must return a member of the UpdateMethod enumeration, which indicates the kind of update method this device uses.

There are currently three supported update methods, "None", "Step", and "Timeslice". None is the default. If a device is active, and needs to perform its own execution steps, it will probably need either the "Step" or "Timeslice" update methods. If a device requests the step update method, it must implement the ExecuteStep method. If a device requests the timeslice update method, it must implement the ExecuteTimeslice and ExecuteTimesliceTimingPointStep methods. See the documentation for those methods for further info.

Note that the value returned by this method should be constant, and should not change for the lifetime of the device object. Returning a different value from this method at different times may result in the change not taking effect, or causing unexpected problems during system execution.

Usage

      virtual double ExecuteStep();

Return value

[UpdateMethod]
The update method this device requires for execution

See also

  • IDevice
  • UpdateMethod
  • ExecuteStep
  • ExecuteTimeslice
  • ExecuteTimesliceTimingPointStep


Initialize method

Description

The Initialize method should return the device to a clean default state, the same as if the device had just been created. The Exodus Platform calls the Initialize method on each device to perform a "hard reset" of the system back to an initial power-on state. Persistent state should not be cleared when Initialize is called, but any volatile state should be reset to the correct initial state for power-on.

The Initialize method is called on all devices after they are created, and then could be called at any time afterwards when a hard reset is performed.

Usage

      virtual void Initialize();

See also

  • IDevice


RemoveReference method

Description

The RemoveReference method is the reverse of the AddReference method. This method is called by the system on a device when an object that the device has previously accepted a reference to, as indicated by it returning true from the AddReference method, is being released. If the device has retained a reference to the target object, or has established any kind of connection or association with the target object, it must be released when this function is called.

Usage

virtual void RemoveReference(IDevice* target);
virtual void RemoveReference(IExtension* target);
virtual void RemoveReference(IBusInterface* target);
virtual void RemoveReference(IClockSource* target);

Argument list

target [IDevice / IExtension / IBusInterface / IClockSource]
The target object having its referencec removed

See also

  • AddReference
  • IDevice
  • IBusInterface
  • IExtension
  • IClockSource


SuspendExecution method

Description

The SuspendExecution method is called by the system on each device in the system when system excution is being halted. The complementing method to this method is BeginExecution, which is called when system execution begins. It is generally expected that this method wll be called if something is setup in the BeginExecution method that needs to be undone here, such as stopping a worker thread.

Usage

      virtual void SuspendExecution();

See also

  • IDevice
  • BeginExecution


UsesExecuteSuspend method

Description

The UsesExecuteSuspend method must return true if this device ever calls the SuspendTimesliceExecution method on the IDeviceContext object associated with this device. If the device attempts to call the SuspendTimesliceExecution method when it has not returned true from this method, an assertion failure may be triggered by the system.

Note that the return value from this method should be consistent after the device object has been created, and never change, otherwise errors may occur at runtime. The system uses this function as a hint to help it optimize performance.

The Device base class implements this method, and returns false by default. If a device derives from this base class, it doesn't need to implement this method unless it needs to call the SuspendTimesliceExecution method.

Usage

      virtual bool UsesExecuteSuspend() const;

Return value

[bool]
True if the device may call the SuspendTimesliceExecution method at any point during its lifetime, false otherwise.

See also

  • IDevice


UsesTransientExecution method

Description

The UsesTransientExecution method must return true if this device ever calls the SetTransientExecutionActive method on the IDeviceContext object associated with this device. If the device attempts to call the SetTransientExecutionActive method when it has not returned true from this method, an assertion failure may be triggered by the system.

Note that the return value from this method should be consistent after the device object has been created, and never change, otherwise errors may occur at runtime. The system uses this function as a hint to help it optimize performance.

The Device base class implements this method, and returns false by default. If a device derives from this base class, it doesn't need to implement this method unless it needs to call the SetTransientExecutionActive method.

Usage

      virtual bool UsesTransientExecution() const;

Return value

[bool]
True if the device may call the SetTransientExecutionActive method at any point during its lifetime, false otherwise.

See also

  • IDevice


ValidateDevice method

Description

The ValidateDevice method gives devices a chance to notify the system if there's some aspect of the configuration of the device that is invalid. Every loaded device is validated after system modules are loaded or unloaded, so devices must be able to allow this method to run multiple times, and at potentially any time after device creation. Returning false from this method indicates that the device cannot execute with the current configuration.

The main purpose of this method is to validate the device connections to other devices. The AddReference method is called during device construction to link it to other devices. If a required link for a device has not been established, the ValidateDevice method should return false.

Usage

      virtual bool ValidateDevice();

Return value

[bool]
True if the device was validated successfully, false otherwise. If a device returns false from this method, the system will consider the device to be in an invalid state, and the system will not be allowed to execute.

See also

  • IDevice
  • Plugin Model


AudioStream class

Description

The AudioStream class is designed to allow simple low-latency gapless audio playback on Windows, even when the sample data being output isn't generated at a constant rate. Measures are taken to prevent audio artifacts that can occur from buffer underruns, and synchronization problems from sample data arriving too quickly or at a varying rate. See the overall description of the AudioStream library for further info.

Audio stream binding functions

 | Name | Description
Public member | Open | Opens an audio output device and prepares it for playback
Public member | Close | Closes the previously opened audio output device

Buffer management functions

 | Name | Description
Public member | CreateAudioBuffer | Creates an AudioBuffer object for supplying audio data
Public member | DeleteAudioBuffer | Deletes a previously allocated AudioBuffer object that has not been sent for playback
Public member | PlayBuffer | Places an AudioBuffer object in the list for playback. The buffer must not be accessed after this function is called, and the buffer is deleted automatically when playback is complete.

Sample rate conversion functions

Name | Description
ConvertSampleRate | Performs a high quality sample rate conversion on raw sample data from one sample rate to another

See also

  • AudioStream library


Close method

Description

The Close method does the reverse of the Open method, that is, if an audio output device has previously been opened, it terminates the worker thread which is managing audio playback, and closes the handle to the audio output device. If a device is open when the AudioStream object is destroyed, it is closed automatically.

Usage

void Close();

See also

  • AudioStream class
  • Open method


ConvertSampleRate method

Description

The ConvertSampleRate method performs a high quality resampling operation on the supplied raw sample data buffer, from the specified input sample rate to the desired output sample rate.

Usage

static void ConvertSampleRate(const std::vector<short>& sourceData, unsigned int sourceSampleCount, unsigned int achannelCount, std::vector<short>& targetData, unsigned int targetSampleCount);

Argument list

sourceData [const std::vector<short>&]
The input sample data to convert
sourceSampleCount [unsigned int]
The sample rate of the input sample data
achannelCount [unsigned int]
The number of channels in the sample data
targetData [std::vector<short>&]
The output buffer to receive the converted sample data. If this buffer contains any existing data, it will be erased.
sourceData [unsigned int]
The desired sample rate of the output sample data

See also

  • AudioStream class


CreateAudioBuffer method

Description

This method creates an AudioBuffer object which is compatible with playback on this AudioStream object. The created AudioBuffer object can be then filled with sample data by the caller, and sent for playback by calling the PlayBuffer method, or deleted without being sent for playback by calling the DeleteAudioBuffer method.

Usage

AudioBuffer* CreateAudioBuffer(unsigned int sampleCount, unsigned int achannelCount);

Argument list

sampleCount [unsigned int]
The number of samples to allocate in the AudioBuffer per channel
achannelCount [unsigned int]
The number of channels to allocate the specified number of samples for in the buffer

Return value

[AudioBuffer*]
A pointer to the allocated AudioBuffer object if the creation is successful, nullptr otherwise. Creation of the buffer will fail if the AudioStream has not been successfully opened through a call to the Open method, or if the supplied channel or sample count arguments are set to 0.

See also

  • AudioStream class
  • DeleteAudioBuffer method
  • PlayBuffer method


DeleteAudioBuffer method

Description

This method deletes a previously allocated AudioBuffer object which was returned by the CreateAudioBuffer method. This method only needs to be used if the caller wants to delete a previously allocated buffer without playing it. If a buffer is sent for playback through a call to the PlayBuffer method, the AudioStream class will delete it automatically after playback is complete.

Usage

void DeleteAudioBuffer(AudioBuffer* buffer);

Argument list

buffer [AudioBuffer*]
The AudioBuffer object to delete

See also

  • AudioStream class
  • CreateAudioBuffer method
  • PlayBuffer method


Open method

Description

The Open method opens a handle to the audio output device to use for playback, and spawns a worker thread to manage playback of the supplied audio data to that device. If an output device is already open for this AudioStream, it is closed before the open attempt is processed. After opening an audio output device, it can be closed again by calling the Close method. If a device is open when the AudioStream object is destroyed, it is closed automatically.

Usage

bool Open(unsigned int achannelCount, unsigned int abitsPerSample, unsigned int asamplesPerSec, unsigned int amaxPendingSamples = 0, unsigned int aminPlayingSamples = 0);

Argument list

achannelCount [unsigned int]
The number of channels in the audio data being sent for playback. Note that this does not need to match the number of channels being used by the actual playback device. This number should be set to the actual number of channels that are present in the audio stream being played.
abitsPerSample [unsigned int]
The number of bits in a single sample entry for a single channel in the audio stream.
asamplesPerSec [unsigned int]
The output sample rate to use on the audio output device. This must be set to a sample rate which is supported by the audio hardware on the computer, such as 44100 or 48000. Note that this is generally going to be different to the sample rate of the actual data being generated by an emulation core. Where the playback sample rate differs from the sample rate of the generated data, the ConvertSampleRate method should be used to resample the audio data prior to sending it for playback. Right now no assistance is provided to determine what sample rates are supported by the local computer. See the AudioStream library overview for more information on this.
amaxPendingSamples [unsigned int]
The maximum number of samples that should be buffered in the Windows audio buffers at any one time. The lower this value, the less latency there is between sending audio data to the AudioStream and the actual playback of that audio data on the hardware, however this also reduces the tolerance of the audio playback to variations in speed at which the audio data is supplied. If the default value of 0 is used, the AudioStream will use a default calculation of samplesPerSec/4.
aminPlayingSamples [unsigned int]
The minimum number of samples that are allowed to be buffered in the Windows audio buffers at any one time, before filler sample buffers are inserted to avoid clicks and pops if the buffer was to underflow. This should be set to a value as low as possible, before clicks or pops begin appearing in the audio playback. If the default value of 0 is used, the AudioStream will use a default calculation of samplesPerSec/20.

Return value

[bool]
True if the audio output stream is created successfully, false otherwise.

See also

  • AudioStream class
  • Close method
  • PlayBuffer method
  • ConvertSampleRate method


PlayBuffer method

Description

This method sends a previously allocated AudioBuffer object for playback. The caller is responsible for filling the AudioBuffer object with valid sample data before calling this method. Note that the caller is also responsible for handling sample rate conversion issues. When a buffer is sent for playback, it must match the sample rate being used for the audio output device. If sample rate conversion is required, the caller must perform this sample rate conversion. This is best achieved by using the ConvertSampleRate function to adjust the sample rate of the raw sample data.

Note that audio buffers should be sent for playback in the order they are created. If two AudioBuffer objects are allocated by successive calls to the CreateAudioBuffer method, and the second buffer is sent for playback through a call to the PlayBuffer method, that buffer will not begin playback until the first buffer is either sent for playback too, or deleted through a call to the DeleteAudioBuffer method.

Usage

void PlayBuffer(AudioBuffer* buffer);

Argument list

buffer [AudioBuffer*]
The AudioBuffer object to send for playback

See also

  • AudioStream class
  • CreateAudioBuffer method
  • DeleteAudioBuffer method


ThinVector class

Description

This container is designed to allow the most efficient representation of an array with a variable size in memory to be created and accessed, which is a single integer giving the size of the array, followed at the same place in memory by an array of items of a specified type, with any necessary padding the hardware platform requires inserted between the size and the array of items. This is not possible to achieve with normal C++ structures. In traditional C++ code, two separate memory allocations would be required, one storing the array of items, and another storing the size of the array and a pointer to the array of items, which doubles the number of memory allocations required for the vector, and slows down access due to another layer of indirection adding additional cycles and cache misses.

Remarks

A typecast is necessary to get the intended use out of this class. It is expected that instances of the ThinVector class will be allocated on the heap, and that the size makes this possible through the use of templates to create the structure in memory, with the caller then using a typecast to effectively discard the size parameter, after which the container can be passed around and used in a generic manner, and referenced in arrays with other containers that have different sizes.

It is very important to note that the ThinVector class is, by design, only intended for use with primitive types. Specifically, any types which cannot by initialized by a zero fill, or be populated from a completely uninitialized state by an assignment operation, should not be used in this container, and any type that has a destructor will fail catastrophically. The lack of a virtual destructor, combined with the intention of casting away the true number of elements in the array, makes memory deallocation unsafe for any objects with a destructor.

Template parameters

 | Name | Type | Description
Public member | T | class | The type of each element in the array. Note that only primitive types are supported.
Public member | S | size_t | The number of elements to allocate in the array. Note that this template parameter is only used during construction. After construction, the arraySize member is used to test the size of the array.

Data members

 | Name | Type | Description
Public member | arraySize | size_t | The number of entries in the array
Public member | array | T[] | The array of data entries

Member functions

 | Name | Description
Public member | InitializeData | Performs a zero fill of all entries in the array
Public member | CopyData | Copies data from the specified array into the vector. If more elements are in the array than the vector, the extra elements are ignored. If more elements are in the vector than the array, the remaining entries in the vector are zero filled.

See also

  • ThinList
  • ThinListDouble


Table of Contents

  • Home
  • Exodus SDK
    • Concepts
      • System Model
      • Plugin Model
      • Timing Model
      • Exported Interfaces
    • Interface Libraries
      • DeviceInterface
        • Device System
          • IDevice
          • IDeviceContext
          • IDeviceInfo
          • IBusInterface
          • IClockSource
          • ISystemDeviceInterface
          • Data
      • ExtensionInterface
        • Extension System
          • IExtension
          • IExtensionInfo
          • ISystemExtensionInterface
          • IGUIExtensionInterface
        • Menu System
          • IMenuHandler
          • IMenuSegment
          • IMenuItem
          • IMenuSelectableOption
          • IMenuSubmenu
        • View System
          • IViewPresenter
          • IView
          • IViewManager
          • IUIManager
      • SystemInterface
        • ISystemGUIInterface
        • ISystemInfo
    • Base Class Libraries
      • Device
        • Device
      • Extension
        • Extension
      • Processor
        • Processor
        • IWatchpoint
        • IBreakpoint
        • IOpcodeInfo
        • OpcodeTable
    • Utility Libraries
      • TimedBuffers
        • RandomTimeAccessBuffer
        • RandomTimeAccessValue
        • ITimedBufferInt
        • ITimedBufferIntDevice
      • GenericAccess
        • IGenericAccess
        • GenericAccessBase
  • Support Libraries
    • AudioStream
    • CallbackSupport
    • DataConversion
    • Debug
    • HierarchicalStorage
    • Image
    • MarshalSupport
    • Stream
    • ThinContainers
    • ThreadLib
    • WindowsControls
    • WindowsSupport
    • ZIP