Quoted from idealjoker:
I am using SWI to execute a single instruction of a "new" virtual machine, which I call the IVM. The IVM uses the WVM (Sys 11 Pinbol) interpreter as a "plug-in", so all the useful WVM instructions are available in-line (setBits, killThreads, exitThread, etc.). This alone saves tons of space in Bad Cats. In the IVM I reuse some of the WVM opcodes that are not useful as "one shots"; for example, opcode $01 (noOperation in WVM) starts WVM mode. I added new system calls, including display_str16 which you can use both in WVM_mode and as one shots. Finally, I added M6800 extension opcodes, such as PSHX, PULX, AAX, A2BX, etc. I have not yet implemented any string compression but I am pretty sure that I will at some stage. Eventually I would like to make this available to other interested parties.
What I like best about the IVM is that it is "boot-strappable": The first stage is a patch to the original WVM interpreter that adds one-shot capability while making the code 1-byte smaller. Therefore I can add the IVM to a game with zero bytes of free ROM. The space I get with the first stage is sufficient to implement the 2nd, etc.
This is similar to the Stern mpu200 virtual machine, it starts by default as a one shot and you have to tell it to switch to multiple mode - very handy to do the one function you need, and sets the condition accordingly for the 6800 to react to. I hadn't actually thought about adding those pshx/pulx etc type 6803/6809 functionality to it but that makes sense as all over the place system 11 does an inline assembly command to do exactly those types of functions. I know pinbol was made to be extensible, but then they went ahead and used all of the opcodes available.
I would be interested to see how much your method saves in Rollergames, as the pinbol in that game is a lot sparser than earlier games where it was used heavily.
I also think there's some savings to be had in the comparison functions that use $F2 'force' a little excessively; the way I understood it is that the $f2 prefix is only required is you are using a comparison literal that starts with $Fx, so that the interpreter forces it to load it as a literal value instead of another comparison on the stack. I haven't tested that idea out yet though.
For what you're doing in TCM with the different rulesets that one-shot capability is essential for sure. I'll have to get around to applying the latest patches you sent to the beta testers and look at it closer. I guess you make the jsr pnbolstart into the swi and anywhere you need the WVM mode you are doing swi,$01 instead of jsr xxxx, saving 1 byte off every call. Nice that you get all your registers for free there as well if needed.