diff --git a/specification/specification.typ b/specification/specification.typ index 0c004d7..bfbfb1b 100644 --- a/specification/specification.typ +++ b/specification/specification.typ @@ -172,11 +172,11 @@ All instructions are listed in @instructions. [8],[*Deref*],[`@arg2=@(@arg1+arg3)`], [9],[*Ref*],[`@(@arg1+arg3)=@arg2`], [10],[*Inst*],[`@arg1=inst_ptr`], - [11],[*Print*],[Writes `color=@arg1` to `index=@arg2` of the screen buffer.], - [12],[*Read*],[Copies `index=@arg1` of the screen buffer to `@arg2`.], + [11],[*Print*],[Writes `value=@arg1` to `index=@arg2` of buffer `arg3`], + [12],[*Read*],[Copies `index=@arg1` of buffer `arg3` to `@arg2`.], [13],[*Band*],[`@arg3=@arg1&@arg2` (binary and)], [14],[*Xor*],[`@arg3=@arg1^@arg2` (binary exclusive or)], - [15],[*Sync*],[Puts `@arg1=position_code`, `@arg2=key_code` and synchronizes (in that order).], + [15],[*Sync*],[Puts `@arg1=position_code`, `@arg2=key_code` and synchronizes (in that order).If arg3!=0, it triggers the expansion port mechanism.], ) #figure( @@ -186,6 +186,8 @@ All instructions are listed in @instructions. Every instruction shown in @instructions advances the instruction pointer by four positions _after_ it is completed. The exceptions to this are the *GoTo* and *Skip* instructions. They only do this, if the condition is _not_ met. +When an argument refers to the name of a buffer, it means the screen buffer if it is 0 and the utility buffer otherwise. + = Constructing the Program A program is really just the initial state of the main memory. @@ -210,6 +212,37 @@ There is intentionally no way of restarting or even quitting a program from with - It is not guaranteed that the emulator itself closes if an exception occurs. (So you can not use it to quit a program.) ] += The Utility Buffer and the Expansion Port + +The utility buffer behaves a lot like the screen buffer with the obvious difference that it is not drawn to the screen. +This can be used for intermediate storage at runtime, but it is always initialized to be filled with zeros when the program starts. + +Its second function is to communicate with the expansion port. +The goal is to provide a mechanism for someone to add additional functionality to their emulator without making it completely incompatible. +This we call the expansion card. +The mechanism works as follows: +If the expansion port is triggered with the *Sync* instruction, it writes out the full utility buffer through the virtual port, making it available for the extension card to read. It is then replaced by $2^16$ new values provided by the extension. From the programs perspective, this is an atomic operation. It triggers the mechanism with the *Sync* instruction and when it gets to run again, the whole buffer has been exchanged. This is supposed to model a transfer of data between the program and the virtual extension card. +It should follow the following rules: +- The data coming in can not depend on the data being flushed out this frame. It can be influenced by previous transfers, but it can not run computations during a transfer. +- The expansion card does not get access to any other information internal to the system (screen buffer, memory or instruction pointer). It can not manipulate these components either. +- It can not manipulate the utility buffer at any point where the mechanism was not explicitly envoked. +- It can not see or mainipulate what is on the screen or what input is being passed to the system. +- It can not change any rule of the emulation. + + +Synchronizations that are caused by exceeding the instruction limit never trigger the expansion mechanism. + +If no extension card is available, there is no answer when the exchange is triggered. As a result the utility buffer is simply cleared. + +Here are some examples of what an extension card might do: +- Play an audio sample. +- Provide keyboard or other text input. +- Perform some computation on the input and report back the result the next time it is activated. +- Access some emulated file system. + + + + = Example Program #[