I’ve been feeling somewhat delusional lately because of this. I am not sure if it is a good idea because (1) it has never been done before; (2) it seems like a misapplication of an interpreter/state machine model; and (3) it takes some work to set up.
In theory, you could turn any sequence of API calls and basic arithmetic into a machine-readable language. Not all encodings are Turing-complete instruction sets, but a number of them are. For instance, I discovered that PostScript is actually a Turing-complete, stack-based language. You can do math in PostScript, define functions, and do things that are far beyond the scope of executing print jobs. If you keep this in mind, you can find that an instruction-based model is not a misapplication for a scripted visual novel. The other question stands, however: is it practical?
The goal behind VNVM is to make visual novels self-containing and portable by adding a layer of abstraction to the behavior of sprites, with the ability for instructions to be sent over the network without any danger of exploitation. While sandboxing is achievable with Lua and Python, I would end up placing an excess amount of emphasis on the security layer to prevent arbitrary code execution, which is ridiculous to defend against using a bytecode that is far more complicated than I really need. Moreover, using Lua in tandem with Python already raises eyebrows: why use two different scripting languages?
A side effect of this project is that you would be able to write visual novels in assembly, if you so choose to. You can also port the VM to the browser, to a GBA, to any platform you can play games on. But the final goal is to make any sort of visual novel play faithfully, without the end user needing to see the backend at all.
Delusional and worried that I was wasting my time, I wondered why the instruction set was so complicated. After taking some inspiration from PostScript, I realized that this approach of a VM, albeit somewhat strange, is workable. I just have to change the instruction set from register-based to stack-based, which was an easy change and eliminated about 100 lines from my code.
My main target right now is Ace Attorney. Currently, case engines are written in exotic languages, such as Delphi, Multimedia Fusion, or some “custom-made” language that looks very similar to AutoIt. VNVM, I admit, is no exception; however, my main argument is that its applications surpass Ace Attorney, and I plan to automate the construction process of a faithful case engine by creating a Python script that emits VNVM machine code. I have already written an assembler; now I am to write a script that uses inline assembly to directly produce machine code.
One useful application of VNVM is writing the behavior of sprites. Users of Attorney Online are accustomed to using .ini files to define emotes, sounds, and delays. But from a technical standpoint, this system is bunk: what if I want my sprite images to be organized in some other way in the file system? What if I need 8-bit transparency in my animations? What if there is something floating around me while I do everything? It is clear that .ini files cannot cover all cases, and even at the introduction of some complexity, the system falls flat on its insufficiency.
My idea was a domain-specific language called Spritelang. This is a macro-based language, which, unfortunately, has rather complicated syntax rules, surpassing my knowledge of compiler theory and the writing of tokenizers. I would certainly write it in JetBrains’ MPS, but I underestimated the notes when they said “this might take about a day’s worth of your time.” The meta-language is not an easy one to understand, but I can sense its immense power currently beyond my reach.