Skip to content
This repository was archived by the owner on Dec 24, 2020. It is now read-only.

Files

Latest commit

0bc0cd0 · Jun 14, 2019

History

History

devices

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Jun 8, 2019
Jun 26, 2018
Jun 26, 2018
Jun 8, 2019
Jun 8, 2019
Jun 8, 2019
Jun 8, 2019
Jun 8, 2019
Jun 8, 2019
Jun 8, 2019
Jun 14, 2019
layout title permalink
page
PCjs Device Classes
/modules/devices/

PCjs Device Classes

In the spirit of Vanilla JS, a very simple set of ES2015 (ES6) JavaScript classes are used to create a variety of newer (late 2017) PCjs Machines:

which, in turn, build on a simple set of library classes:

Examples of those newer PCjs Machines include:

On the PCjs website, Jekyll Front Matter and templates are used define and embed complete machines. The Markdown file in the TI-57 directory provides a good example. The Front Matter at the top of the file is where you define one or more machines, each with the following minimum set of properties:

machines:
  - id: ti57
    type: ti57
    name: TI-57 Programmable Calculator
    config: /devices/ti57/machine/rev0/ti57.json

The config property specifies the location of a JSON configuration file that describes the machine's internal devices, the IDs of any visual controls that they bind to, and any resources they require (e.g., ROM contents).

Alternatively, a JSON configuration blob can be embedded directly in the machine definition:

    config: |
      {
        "ti57": {
          "class": "Machine",
          "type": "TI57",
          "name": "TI-57 Emulator",
          "bindings": {
            "clear": "clearTI57",
            "print": "printTI57"
          }
        },
        "chip": {
          "class": "Chip",
          "type": "TMS-1500"
        },
        "clock": {
          "class": "Time",
          "cyclesPerSecond": 650000,
          "bindings": {
            "run": "runTI57",
            "speed": "speedTI57",
            "step": "stepTI57"
          }
        },
        "display": {
          "class": "LED",
          "type": 3,
          "cols": 12,
          "rows": 1,
          "color": "red",
          "backgroundColor": "black",
          "bindings": {
            "container": "displayTI57"
          }
        },
        "input": {
          "class": "Input",
          "location": [139, 325, 368, 478, 0.34, 0.5, 640, 853, 418, 180, 75, 36],
          "map": [
            ["2nd",  "inv",  "lnx",  "\\b",  "clr"],
            ["lrn",  "xchg", "sq",   "sqrt", "rcp"],
            ["sst",  "sto",  "rcl",  "sum",  "exp"],
            ["bst",  "ee",   "(",    ")",    "/"],
            ["gto",  "7",    "8",    "9",    "*"],
            ["sbr",  "4",    "5",    "6",    "-"],
            ["rst",  "1",    "2",    "3",    "+"],
            ["r/s",  "0",    ".",    "+/-",  "=|\\r"]
          ],
          "bindings": {
            "surface": "imageTI57",
            "power": "powerTI57",
            "reset": "resetTI57"
          }
        },
        "rom": {
          "class": "ROM",
          "wordSize": 13,
          "valueSize": 16,
          "valueTotal": 2048,
          "littleEndian": true,
          "file": "ti57le.bin",
          "reference": "",
          "values": [
            4623,4386,5106,7051,3246,6152,5813,5628,5805,7051,4386,3246,7911,5132,1822,6798,
            ...
            8183,1313,8182,613,3343,7148,39,3188,6561,3130,3090,7165,3188,3587,0,0
          ]
        }
      }

Front Matter also provides a convenient way to define styles for any of the visual controls. The syntax is similar to basic CSS, except that identifiers with a leading underscore correspond to control IDs without the underscore (in CSS, you would use # in front of each identifier, but that's a comment character in Front Matter). You can also define style classes, by using identifiers with a leading period.

styles:
  _ti57:
    position: relative;
    display: inline-block;
  _displayTI57:
    position: absolute;
    left: 16%;
    top: 7%;
    width: 70%;
    height: 4%;

Next, add some HTML markup at the desired page location, such as:

<div id="ti57">
  <img id="imageTI57" src="/devices/ti57/images/ti57.png"/>
  <div id="displayTI57"></div>
  <button id="powerTI57">Power</button>
</div>
<div style="float:left;">
  <div style="width:100%;">
    <p>Diagnostics</p>
    <textarea id="printTI57" cols="78" rows="16"></textarea>
  </div>
  <button id="runTI57">Run</button>
  <button id="stepTI57">Step</button><span id="speedTI57">Stopped</span>
  <button id="resetTI57">Reset</button>
  <button id="clearTI57">Clear</button>
</div>

Finally, you embed the machine with a simple include template:

{% include machine.html id="ti57" config="json" %}

which automatically adds all the necessary scripts, as listed in machines.json:

<script src="/modules/devices/lib/stdio.js"></script>
<script src="/modules/devices/device.js"></script>
<script src="/modules/devices/input.js"></script>
<script src="/modules/devices/led.js"></script>
<script src="/modules/devices/rom.js"></script>
<script src="/modules/devices/time.js"></script>
<script src="/modules/devices/tms1500.js"></script>
<script src="/modules/devices/machine.js"></script>

and then creates the machine with:

new Machine('ti57','{JSON blob}');

or, if an external JSON file is used, with:

new Machine('ti57','/devices/ti57/machine/rev0/ti57.json');

Of course, you can add any or all of those lines yourself if you don't want to use the include template.