Source · companion/source-samples/bmcpu-main.cpp
Forty lines from the archive — the actual main() that instantiates a BMCPU and steps it through a BML application:
{`#define INITGUID
#include <bmvm.h>
#include <stdio.h>
#include <stdlib.h>
DEFINE_GUID( TEST_def,
0x63CC7777, 0xD99A, 0x11d3, 0xA5, 0x49,
0x00, 0x10, 0x5A, 0xAB, 0x8B, 0x48 );
void main( void ) {
BMVM pCPU;
BMCreateMachine( &pCPU, 0 );
BMStartApplication( pCPU, &TEST_def );
BMMachineStep( pCPU, BM_RUN );
/* Step-into mode with DO/UNDO trace:
BMTest( pCPU, 1 );
do {
UNICHAR szBuffer[1024];
BMVM_STATE sState;
sState.dwSize = sizeof( BMVM_STATE );
BMQueryMachineState( pCPU, &sState );
PUNICHAR szMode = sState.byMode ? L"UNDO" : L" DO";
if( BMQueryInstruction( pCPU, sState.ndxCodeOffset,
szBuffer, 1024 ) == BM_SUCCESS ) {
wprintf( L"%s: %s\\n", szMode, szBuffer );
}
} while( BMMachineStep( pCPU, BM_STEP_INTO ) == BM_SUCCESS );
BMDestroyMachine( pCPU, 0 );
*/
}`}
Read this carefully and four design choices appear. Applications are addressed by DEFINE_GUID — COM-addressable, system-registry-discoverable. The public API uses opaque BMVM handles, not C++ inheritance — language-portable. Stepping modes are first-class: BM_RUN for fast execution, BM_STEP_INTO for the debugger trace shown in the comment block. And the commented trace loop reads sState.byMode to print DO or UNDO for every instruction — the speculation phase made visible to the developer.