mirror of
https://github.com/JanNeuendorf/SVC16.git
synced 2025-06-03 01:50:18 +00:00
Some rewording of the specs (Debug port in the sketch)
This commit is contained in:
parent
ca028dbdc2
commit
dab743dafc
@ -8,7 +8,7 @@
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="sketch.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -23,11 +23,11 @@
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1.2973709"
|
||||
inkscape:cx="31.21698"
|
||||
inkscape:cy="148.377"
|
||||
inkscape:window-width="1856"
|
||||
inkscape:window-height="1131"
|
||||
inkscape:zoom="2.5947418"
|
||||
inkscape:cx="106.75436"
|
||||
inkscape:cy="179.01589"
|
||||
inkscape:window-width="3440"
|
||||
inkscape:window-height="1379"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
@ -76,19 +76,19 @@
|
||||
x="0.60439652"
|
||||
y="0.39472535" />
|
||||
<rect
|
||||
style="fill:#c7c7c7;fill-opacity:1;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
style="fill:#c7c7c7;fill-opacity:1;stroke:#000000;stroke-width:0.343;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect1196"
|
||||
width="114.58817"
|
||||
height="47.955166"
|
||||
x="3.4289503"
|
||||
y="40.318504" />
|
||||
width="114.59528"
|
||||
height="46.02486"
|
||||
x="3.4253974"
|
||||
y="42.354332" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-opacity:1"
|
||||
id="rect2"
|
||||
width="106.83552"
|
||||
height="3.1948919"
|
||||
x="5.7333722"
|
||||
y="71.351784" />
|
||||
y="73.391167" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect3"
|
||||
@ -112,7 +112,7 @@
|
||||
aria-label="2 16-bit values"
|
||||
id="text4-2"
|
||||
style="font-size:3.175px;font-family:Cabin;-inkscape-font-specification:Cabin;letter-spacing:0px;fill:none;stroke:#000000;stroke-width:0.349999;stroke-linecap:round"
|
||||
transform="translate(0,6.3500003)">
|
||||
transform="translate(0,8.3893811)">
|
||||
<path
|
||||
d="m 41.595644,76.756889 h -1.584325 v -0.333375 l 0.568325,-0.574675 q 0.17145,-0.1778 0.276225,-0.295275 0.104775,-0.12065 0.1524,-0.2159 0.04763,-0.09843 0.04763,-0.20955 0,-0.136525 -0.0762,-0.2032 -0.07303,-0.06668 -0.200025,-0.06668 -0.130175,0 -0.254,0.06033 -0.123825,0.06032 -0.26035,0.17145 l -0.26035,-0.307975 q 0.09842,-0.08572 0.206375,-0.15875 0.111125,-0.07303 0.254,-0.117475 0.14605,-0.04762 0.34925,-0.04762 0.22225,0 0.381,0.08255 0.161925,0.07937 0.24765,0.219075 0.0889,0.136525 0.0889,0.31115 0,0.187325 -0.0762,0.3429 -0.07303,0.155575 -0.2159,0.307975 -0.1397,0.1524 -0.339725,0.33655 l -0.2921,0.27305 v 0.02222 h 0.987425 z"
|
||||
style="font-weight:bold;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono Bold';fill:#000000;stroke:none;stroke-width:0.35"
|
||||
@ -170,22 +170,22 @@
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.9467px;font-family:Cabin;-inkscape-font-specification:Cabin;letter-spacing:0px;fill:none;stroke:#000000;stroke-width:0.214596;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="41.586529"
|
||||
y="81.713913"
|
||||
y="83.753296"
|
||||
id="text4-2-5"><tspan
|
||||
id="tspan4-1-3"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono Bold';letter-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.214596"
|
||||
x="41.586529"
|
||||
y="81.713913">16</tspan></text>
|
||||
y="83.753296">16</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Cabin;-inkscape-font-specification:Cabin;letter-spacing:0px;fill:none;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="6.6575131"
|
||||
y="49.477089"
|
||||
y="51.516468"
|
||||
id="text4-3"><tspan
|
||||
id="tspan4-8"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono Bold';letter-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35"
|
||||
x="6.6575131"
|
||||
y="49.477089">Screen-buffer</tspan></text>
|
||||
y="51.516468">Screen-buffer</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Cabin;-inkscape-font-specification:Cabin;letter-spacing:0px;fill:none;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
@ -231,40 +231,44 @@
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Cabin;-inkscape-font-specification:Cabin;letter-spacing:0px;fill:none;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="6.6575131"
|
||||
y="69.056274"
|
||||
y="71.095657"
|
||||
id="text5"><tspan
|
||||
id="tspan5"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono Bold';letter-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35"
|
||||
x="6.6575131"
|
||||
y="69.056274">Memory</tspan></text>
|
||||
y="71.095657">Memory</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 35.263958,28.43003 c 34.349788,0 34.349788,0 34.349788,0 z"
|
||||
id="path5" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 46.475735,18.896846 v 21.29424 z"
|
||||
d="m 46.475735,18.722743 v 23.46014 z"
|
||||
id="path6" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 71.361303,37.785178 v 4.569154 z"
|
||||
id="path6-5" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Cabin;-inkscape-font-specification:Cabin;letter-spacing:0px;fill:none;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="75.50354"
|
||||
y="46.422173"
|
||||
y="48.461552"
|
||||
id="text7"><tspan
|
||||
id="tspan7"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono Bold';letter-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35"
|
||||
x="75.50354"
|
||||
y="46.422173">Instruction-pointer</tspan></text>
|
||||
y="48.461552">Instruction-pointer</tspan></text>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect7"
|
||||
width="3.4790916"
|
||||
height="3.4789827"
|
||||
x="70.052422"
|
||||
y="43.97871" />
|
||||
y="46.018089" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-dasharray:1.05, 1.05;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#ArrowWide);marker-end:url(#marker11)"
|
||||
d="M 10.377259,77.431989 H 108.79207"
|
||||
d="M 10.377259,79.47137 H 108.79207"
|
||||
id="path10" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
@ -279,24 +283,24 @@
|
||||
width="106.83552"
|
||||
height="3.1948919"
|
||||
x="5.7333722"
|
||||
y="61.826775" />
|
||||
y="63.866154" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Cabin;-inkscape-font-specification:Cabin;letter-spacing:0px;fill:none;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="6.6575131"
|
||||
y="59.531265"
|
||||
y="61.570644"
|
||||
id="text6"><tspan
|
||||
id="tspan6"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono Bold';letter-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35"
|
||||
x="6.6575131"
|
||||
y="59.531265">Utility-buffer</tspan></text>
|
||||
y="61.570644">Utility-buffer</tspan></text>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-opacity:1"
|
||||
id="rect1"
|
||||
width="106.83552"
|
||||
height="3.1948919"
|
||||
x="5.7333722"
|
||||
y="51.772598" />
|
||||
y="53.811977" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect5"
|
||||
@ -321,4 +325,21 @@
|
||||
height="3.4789827"
|
||||
x="69.587906"
|
||||
y="26.535919" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:Cabin;-inkscape-font-specification:Cabin;letter-spacing:0px;fill:none;stroke:#000000;stroke-width:0.349999;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="74.962029"
|
||||
y="37.085091"
|
||||
id="text4-3-3-1-3-2"><tspan
|
||||
id="tspan4-8-0-7-6-9"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono Bold';letter-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35"
|
||||
x="74.962029"
|
||||
y="37.085091">Debug Port</tspan></text>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.35;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect1073-1"
|
||||
width="3.4790916"
|
||||
height="3.4789827"
|
||||
x="69.587906"
|
||||
y="34.21637" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 23 KiB |
@ -30,12 +30,11 @@ header: align(right,[v #version]))
|
||||
|
||||
= Motivation and Goals
|
||||
|
||||
We want to fully specify a very simple virtual computer that can be emulated.
|
||||
The goal is to recreate the feeling of writing games for a system with very tight hardware constraints without having to deal with the complicated reality of real retro systems.
|
||||
It should be simple to understand every instruction, to write machine code that runs on it, and to write a compiler for it.
|
||||
The instruction set and the design in general are in no way meant to resemble something that would make sense in real hardware.
|
||||
The instruction set and the design in general are in no way meant to resemble something that would make sense in real hardware. This is primarily because this is aimed only at emulation but also because it encourages different designs when compiling to this architecture.
|
||||
It is also not intended to be as simple and elegant as it could possibly be. This might make it easier to emulate but harder to develop for.
|
||||
Since learning about assemblers and compilers is the point, we provide no guidelines on how to build the programs.
|
||||
Since learning about assemblers and compilers is the point, we provide no guidelines on how to build complex programs.
|
||||
|
||||
== Reproducibility
|
||||
|
||||
@ -51,6 +50,7 @@ This might seem at odds with the previous goal.
|
||||
But if adding a new feature always requires changing the specification, that either means that supporting any new feature means breaking all compatibility, or it means that any expansions are ruled out forever.
|
||||
The compromise is that the behavior for the computer itself is fixed and we define an interface and rules for expansions that can be emulated together with the computer.
|
||||
The Idea is that it is always enough to know this specification and one specification (if any) for the expansion.
|
||||
Think of this as having an expansion-card slot. We can write code that interfaces with expansions invented after the computer, but the expansion-card can not change the way the cpu works.
|
||||
|
||||
|
||||
= General Principles
|
||||
@ -58,7 +58,7 @@ The Idea is that it is always enough to know this specification and one specific
|
||||
Every value is represented as a (little-endian) unsigned 16-bit integer.
|
||||
That includes numbers, addresses, colors, the instruction pointer and the input.
|
||||
Booleans are represented as `u16` values as well: 0 for `false` and >0 for `true`.
|
||||
Whenever an instruction writes out a boolean explicitly, it is guaranteed to represented as the number 1.
|
||||
Whenever an instruction writes out a boolean explicitly, it is guaranteed to be represented as the number 1.
|
||||
|
||||
There are no registers, no built-in stack or special sections of memory.
|
||||
Operations can be performed directly on arbitrary addresses.
|
||||
@ -91,10 +91,10 @@ The coordinate $(0,0)$ is in the upper left-hand corner.
|
||||
|
||||
|
||||
#not-specified[
|
||||
- Colors do not have to be represented accurately (accessability options).
|
||||
- There is no rule for how scaling and aspect ratio might be handled.
|
||||
- Colors do not have to be represented accurately (accessability options, artistic shaders).
|
||||
- There is no rule for how scaling or filtering might be handled.
|
||||
- It is not fixed what the screen shows before it is first synchronized.
|
||||
- A cursor can be shown on the window, as long as its position matches the mouse position passed to the system
|
||||
- A cursor can be shown on the window, as long as its position matches the mouse position passed to the system. The default assumption should be that there is no external cursor, but it might not always be possible to hide it.
|
||||
- There might be a delay before the updated frame is shown on screen.
|
||||
For example one might need to wait for _vsync_ or the window takes time to update.]
|
||||
|
||||
@ -103,8 +103,8 @@ The only supported inputs are the mouse position and a list of eight keys.
|
||||
These keys are supposed to represent the face buttons of an NES controller.
|
||||
The codes for the *A* and *B* keys also represent the left and right mouse buttons.
|
||||
|
||||
On synchronization the new input is loaded into the input-buffer.
|
||||
Before the first synchronization, the input codes are not accessible.
|
||||
On synchronization the new input is stored to a specified memory address.
|
||||
This means that the input is inaccessible before the system is first synchronized. (See @instructions, @synchronization)
|
||||
|
||||
The *position code* is the index of the pixel, the mouse is currently on.
|
||||
It follows the same convention as the screen index explained in @screen.
|
||||
@ -136,14 +136,14 @@ The bits in @inputs are supposed to indicate if a key is currently pressed (and
|
||||
|
||||
#not-specified[
|
||||
- It is not guaranteed on which frame the virtual machine sees an input activate or deactivate.
|
||||
- The emulator might not allow arbitrary combinations of buttons to be pressed simultaneously.
|
||||
|
||||
]
|
||||
|
||||
|
||||
== Synchronization<synchronization>
|
||||
When the console executes the *Sync* instruction, the screen buffer is drawn to the screen.
|
||||
It is not cleared. The system will be put to sleep until the beginning of the next frame.
|
||||
The targeted timing is 30fps. There is a hard limit of 3000000 instructions per frame.
|
||||
The targeted timing is 30fps. There is a hard limit of 3000000 (three million) instructions per frame.
|
||||
This means that if the Sync command has not been called for 3000000 instructions, it will be performed automatically.
|
||||
This can mean that an event (like a mouse click) is never handled.
|
||||
An alternative way to describe it is that the syncing happens automatically every frame and the instructions each take $frac(1,30*3000000)$ seconds.
|
||||
@ -164,21 +164,31 @@ If the opcode is greater than 15, the system will abort.
|
||||
|
||||
#let instruction_table=table(
|
||||
columns: (auto,auto,auto),
|
||||
align: horizon,
|
||||
align:(horizon,horizon,left),
|
||||
table.header(
|
||||
[*Opcode*], [*Name*],[*Effect*],
|
||||
),
|
||||
[0],[*Set*],[`if arg3{
|
||||
@arg1=inst_ptr
|
||||
}else{
|
||||
@arg1=arg2
|
||||
}`],
|
||||
[1],[*GoTo*],[`if(not @arg3){inst_ptr=@arg1+arg2}`],
|
||||
[0],[*Set*],[
|
||||
```
|
||||
if arg3{
|
||||
@arg1=inst_ptr
|
||||
}else{
|
||||
@arg1=arg2
|
||||
}
|
||||
```
|
||||
],
|
||||
[1],[*GoTo*],[
|
||||
```
|
||||
if(not @arg3){
|
||||
inst_ptr=@arg1+arg2
|
||||
}
|
||||
```
|
||||
],
|
||||
[2],[*Skip*],[
|
||||
```
|
||||
if(not @arg3){
|
||||
inst_ptr=inst_ptr+4*arg1-4*arg2
|
||||
}
|
||||
if(not @arg3){
|
||||
inst_ptr=inst_ptr+4*arg1-4*arg2
|
||||
}
|
||||
```
|
||||
],
|
||||
[3],[*Add*],[`@arg3=(@arg1+@arg2)`],
|
||||
@ -229,9 +239,9 @@ It can be shorter, in which case the end is padded with zeroes.
|
||||
The computer will begin by executing the instruction at index 0.
|
||||
|
||||
= Handling Exceptions
|
||||
There are only two reasons the program can fail (for internal reasons).
|
||||
There are only two ways the program can fail (for internal reasons).
|
||||
|
||||
- It tries to divide by zero
|
||||
- It tries to divide by zero.
|
||||
- It tries to execute an instruction with an opcode greater than 15.
|
||||
|
||||
In both cases, the execution of the program is stopped. It is not restarted automatically.
|
||||
@ -262,7 +272,7 @@ It should follow the following rules:
|
||||
- It can not change any rule of the emulation.
|
||||
|
||||
|
||||
Synchronizations that are caused by exceeding the instruction limit never trigger the expansion mechanism. The expansion card can not know that such a synchronization happened.
|
||||
Synchronizations that are caused by exceeding the instruction limit never trigger the expansion mechanism.
|
||||
|
||||
|
||||
If no expansion card is available, there is no answer when the exchange is triggered. As a result the utility buffer is simply cleared.
|
||||
@ -283,7 +293,7 @@ Further information, examples and a reference emulator can be found at #link("ht
|
||||
Everything contained in this project is provided under the _MIT License_.
|
||||
Do with it whatever you want.
|
||||
|
||||
One think we would ask is that if you distribute a modified version that is incompatible with the specifications,
|
||||
One think we would ask is that if you distribute an emulator that is incompatible with the specifications,
|
||||
you make it clear that it has breaking changes.
|
||||
|
||||
= Example Program
|
||||
@ -297,7 +307,7 @@ you make it clear that it has breaking changes.
|
||||
stroke: (paint: rgb("9e9e9e"),thickness: 2pt),
|
||||
text(fill: rgb("#000000"), it))
|
||||
|
||||
While this is not needed for the specifications, it might be helpful to look at a very simple example.
|
||||
|
||||
|
||||
|
||||
Our goal could be to print all $2^16$ possible colors to the screen.
|
||||
|
Loading…
x
Reference in New Issue
Block a user