Updated PC8080 and PDPjs to support RAM images, eliminating the need for the old "writable ROM" kludge; RAM images can include their own load and exec addresses as part of the JSON file, but the RAM component can provide explicit overrides (if no load address is specified either way, the default load address is the starting RAM address)
This commit is contained in:
parent
4cfaa5ef6e
commit
980c2ac5ab
64 changed files with 1479 additions and 1154 deletions
|
|
@ -13,8 +13,8 @@ All our [8080-Based Machines](machine/) are built from a collection of devices,
|
|||
* [Control Panels](panel/)
|
||||
* CPU (8080)
|
||||
* [Machines](machine/)
|
||||
* RAM
|
||||
* [ROMs](rom/)
|
||||
* [RAM Images](ram/)
|
||||
* [ROM Images](rom/)
|
||||
* Video Adapters
|
||||
|
||||
Complete [machine configurations](machine/) are constructed from those devices. A machine configuration is a single XML file
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ PCjs Project.
|
|||
|
||||
The test machine below loads a copy of the
|
||||
[8080 Exerciser](https://web.archive.org/web/20151006085348/http://www.idb.me.uk/sunhillow/8080.html)
|
||||
(specifically, [8080EX1](/devices/pc8080/rom/exerciser/8080EX1.MAC)) and intercepts the exerciser's CP/M console
|
||||
(specifically, [8080EX1](/devices/pc8080/ram/exerciser/8080EX1.MAC)) and intercepts the exerciser's CP/M console
|
||||
calls so that you can see its progress in the Control Panel window. This is a "headless" test machine
|
||||
(no keyboard or display), so that's all you get.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
<name pos="center">8080 Exerciser Test Machine</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu8080" model="8080" cycles="2000000"/>
|
||||
<rom id="romTest" addr="0x0100" size="0x1200" file="/devices/pc8080/rom/exerciser/8080EX1.json" writable="true"/>
|
||||
<ram id="ramTest" addr="0x1300" size="0xED00"/>
|
||||
<ram id="ram64K" addr="0x0000" size="0x10000" file="/devices/pc8080/ram/exerciser/8080EX1.json" load="0x100" exec="0x100"/>
|
||||
<panel ref="/devices/pc8080/panel/wide.xml"/>
|
||||
<debugger id="debugger"/>
|
||||
</machine>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
<name pos="center">8080 Exerciser Preliminary Test Machine</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu8080" model="8080" cycles="2000000"/>
|
||||
<rom id="romTest" addr="0x0100" size="0x0400" file="/devices/pc8080/rom/exerciser/8080PRE.json" writable="true"/>
|
||||
<ram id="ramTest" addr="0x0500" size="0xFB00"/>
|
||||
<ram id="ram64K" addr="0x0000" size="0x10000" file="/devices/pc8080/ram/exerciser/8080PRE.json" load="0x100" exec="0x100"/>
|
||||
<panel ref="/devices/pc8080/panel/wide.xml"/>
|
||||
<debugger id="debugger"/>
|
||||
</machine>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
<name pos="center">8080 CPUTEST Machine</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu8080" model="8080" cycles="2000000"/>
|
||||
<rom id="romTest" addr="0x0100" size="0x4B00" file="/devices/pc8080/rom/exerciser/CPUTEST.json" writable="true"/>
|
||||
<ram id="ramTest" addr="0x4C00" size="0xB400"/>
|
||||
<ram id="ram64K" addr="0x0000" size="0x10000" file="/devices/pc8080/ram/exerciser/CPUTEST.json" load="0x100" exec="0x100"/>
|
||||
<panel ref="/devices/pc8080/panel/wide.xml"/>
|
||||
<debugger id="debugger"/>
|
||||
</machine>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
<name pos="center">8080 "Kelly Smith" Test Machine</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu8080" model="8080" cycles="2000000"/>
|
||||
<rom id="romTest" addr="0x0100" size="0x0701" file="/devices/pc8080/rom/exerciser/TEST.json" writable="true"/>
|
||||
<ram id="ramTest" addr="0x0801" size="0xF7FF"/>
|
||||
<ram id="ram64K" addr="0x0000" size="0x10000" file="/devices/pc8080/ram/exerciser/TEST.json" load="0x100" exec="0x100"/>
|
||||
<panel ref="/devices/pc8080/panel/wide.xml"/>
|
||||
<debugger id="debugger"/>
|
||||
</machine>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
<name pos="center">8080 Exerciser Test Machine</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu8080" model="8080" cycles="2000000"/>
|
||||
<rom id="romTest" addr="0x0100" size="0x1200" file="/devices/pc8080/rom/exerciser/8080EX1.json" writable="true"/>
|
||||
<ram id="ramTest" addr="0x1300" size="0xED00"/>
|
||||
<ram id="ram64K" addr="0x0000" size="0x10000" file="/devices/pc8080/ram/exerciser/8080EX1.json" load="0x100" exec="0x100"/>
|
||||
<panel ref="/devices/pc8080/panel/wide.xml"/>
|
||||
<debugger id="debugger"/>
|
||||
</machine>
|
||||
|
|
|
|||
21
devices/pc8080/ram/README.md
Normal file
21
devices/pc8080/ram/README.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
layout: page
|
||||
title: 8080-Based RAM Images
|
||||
permalink: /devices/pc8080/ram/
|
||||
---
|
||||
|
||||
8080-Based RAM Images
|
||||
---------------------
|
||||
|
||||
RAM images are added to machines by including a *<ram>* component in the machine XML configuration file
|
||||
with the *file* attribute set to the filename of the image; eg:
|
||||
|
||||
```xml
|
||||
<ram id="romH" addr="0x0000" size="0x0800" file="/devices/pc8080/rom/invaders/INVADERS-H.json"/>
|
||||
```
|
||||
|
||||
The project currently contains the following 8080-based ROMs:
|
||||
|
||||
* [8080 Exerciser Tests](exerciser/)
|
||||
* [Space Invaders (1978)](invaders/)
|
||||
* [DEC VT100 Terminal](vt100/)
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
---
|
||||
layout: page
|
||||
title: 8080 Exerciser Tests
|
||||
permalink: /devices/pc8080/rom/exerciser/
|
||||
permalink: /devices/pc8080/ram/exerciser/
|
||||
redirect_from:
|
||||
- /devices/pc8080/rom/exerciser/
|
||||
---
|
||||
|
||||
8080 Exerciser Tests
|
||||
|
|
@ -12,4 +14,4 @@ permalink: /devices/pc8080/rom/exerciser/
|
|||
* [8080PRE](8080PRE.MAC)
|
||||
|
||||
Our [8080 Exerciser Test Machine](/devices/pc8080/machine/exerciser/) runs [8080EX1](8080EX1.MAC),
|
||||
since it is the most comprehensive test and verifies strict compatibilty with the original Intel 8080.
|
||||
since it is the most comprehensive test and verifies strict compatibility with the original Intel 8080.
|
||||
|
|
@ -9,10 +9,10 @@ PDP-11 Device Configurations
|
|||
|
||||
[PDP-11 Machines](/devices/pdp11/machine/) powered by [PDPjs](/modules/pdp11/) rely on a variety of devices and resources, including:
|
||||
|
||||
* [Loaders](loader/)
|
||||
* [Machines](machine/)
|
||||
* [Panels](panel/)
|
||||
* [ROMs](rom/)
|
||||
* [RAM Images](ram/)
|
||||
* [ROM Images](rom/)
|
||||
|
||||
Our collection of sample machines includes a
|
||||
[PDP-11/70 with Front Panel](/devices/pdp11/machine/1170/panel/) and [PDP-11/70 with VT100 Terminal](/devices/pdp11/machine/1170/vt100/).
|
||||
|
|
|
|||
|
|
@ -10,3 +10,4 @@ PDP-11/20 Machine Configurations
|
|||
PCjs is adding support the following PDP-11/20 configurations:
|
||||
|
||||
* [PDP-11/20 Test Machine](/devices/pdp11/machine/1120/test/) ([Debugger](/devices/pdp11/machine/1120/test/debugger/))
|
||||
* [PDP-11/20 with 16Kb and Bootstrap Loader](/devices/pdp11/machine/1120/bootstrap/) ([Debugger](/devices/pdp11/machine/1120/bootstrap/debugger/))
|
||||
|
|
|
|||
10
devices/pdp11/machine/1120/bootstrap/README.md
Normal file
10
devices/pdp11/machine/1120/bootstrap/README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
layout: page
|
||||
title: PDP-11/20 with 16Kb and Bootstrap Loader
|
||||
permalink: /devices/pdp11/machine/1120/bootstrap/
|
||||
machines:
|
||||
- id: test1120
|
||||
type: pdp11
|
||||
---
|
||||
|
||||
{% include machine.html id="test1120" %}
|
||||
11
devices/pdp11/machine/1120/bootstrap/debugger/README.md
Normal file
11
devices/pdp11/machine/1120/bootstrap/debugger/README.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
layout: page
|
||||
title: PDP-11/20 with 16Kb, Bootstrap Loader, and Debugger
|
||||
permalink: /devices/pdp11/machine/1120/bootstrap/debugger/
|
||||
machines:
|
||||
- id: test1120
|
||||
type: pdp11
|
||||
debugger: true
|
||||
---
|
||||
|
||||
{% include machine.html id="test1120" %}
|
||||
13
devices/pdp11/machine/1120/bootstrap/debugger/machine.xml
Normal file
13
devices/pdp11/machine/1120/bootstrap/debugger/machine.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="/versions/pdpjs/1.30.1/machine.xsl"?>
|
||||
<machine id="test1120" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/20: 16Kb, Bootstrap Loader, Debugger</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu" model="1120" cycles="6666667"/>
|
||||
<ram id="ram" addr="0x0000" size="0x4000" file="/devices/pdp11/ram/bootstrap/bootstrap.json"/>
|
||||
<device id="default" type="default"/>
|
||||
<device id="pc11" type="pc11"/>
|
||||
<serial id="dl11" adapter="0" binding="print"/>
|
||||
<panel ref="/devices/pdp11/panel/test/debugger/terminal.xml"/>
|
||||
<debugger id="debugger" base="8" messages="" commands=""/>
|
||||
</machine>
|
||||
12
devices/pdp11/machine/1120/bootstrap/machine.xml
Normal file
12
devices/pdp11/machine/1120/bootstrap/machine.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="/versions/pdpjs/1.30.1/machine.xsl"?>
|
||||
<machine id="test1120" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/20: 16Kb, Bootstrap Loader</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu" model="1120" cycles="6666667"/>
|
||||
<ram id="ram" addr="0x0000" size="0x4000" file="/devices/pdp11/ram/bootstrap/bootstrap.json"/>
|
||||
<device id="default" type="default"/>
|
||||
<device id="pc11" type="pc11"/>
|
||||
<serial id="dl11" adapter="0" binding="print"/>
|
||||
<panel ref="/devices/pdp11/panel/test/terminal.xml"/>
|
||||
</machine>
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="/versions/pdpjs/1.30.1/machine.xsl"?>
|
||||
<machine id="test1120" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/20 Test Machine with Debugger</name>
|
||||
<name pos="center">PDP-11/20 Test Machine with 56Kb and Debugger</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu" model="1120" cycles="6666667" resetAddr="0xC000"/>
|
||||
<ram id="ram" addr="0x0000" size="0xC000"/>
|
||||
<rom id="rom" addr="0xC000" file="/devices/pdp11/rom/test/boot.json" writable="true"/>
|
||||
<cpu id="cpu" model="1120" cycles="6666667"/>
|
||||
<ram id="ram" addr="0x0000" size="0xE000" file="/devices/pdp11/ram/bootdemo/bootdemo.json" load="0xC000" exec="0xC000"/>
|
||||
<device id="default" type="default"/>
|
||||
<device id="pc11" type="pc11"/>
|
||||
<serial id="dl11" adapter="0" binding="print"/>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="/versions/pdpjs/1.30.1/machine.xsl"?>
|
||||
<machine id="test1120" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/20 Test Machine</name>
|
||||
<name pos="center">PDP-11/20 Test Machine with 56Kb</name>
|
||||
<computer id="computer" busWidth="16"/>
|
||||
<cpu id="cpu" model="1120" cycles="6666667" resetAddr="0xC000" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xC000"/>
|
||||
<rom id="rom" addr="0xC000" file="/devices/pdp11/rom/test/boot.json" writable="true"/>
|
||||
<cpu id="cpu" model="1120" cycles="6666667" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xE000" file="/devices/pdp11/ram/bootdemo/bootdemo.json" load="0xC000" exec="0xC000"/>
|
||||
<device id="default" type="default"/>
|
||||
<device id="pc11" type="pc11"/>
|
||||
<serial id="dl11" adapter="0" binding="print"/>
|
||||
<panel ref="/devices/pdp11/panel/test/terminal.xml"/>
|
||||
</machine>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
<machine id="test1170" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/70 with Front Panel and Debugger</name>
|
||||
<computer id="computer" busWidth="22"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" resetAddr="0xC000"/>
|
||||
<ram id="ram" addr="0x0000" size="0xC000"/>
|
||||
<rom id="rom" addr="0xC000" file="/devices/pdp11/rom/test/boot.json" writable="true"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667"/>
|
||||
<ram id="ram" addr="0x0000" size="0xE000" file="/devices/pdp11/ram/bootdemo/bootdemo.json" load="0xC000" exec="0xC000"/>
|
||||
<ram id="ram" addr="0x10000" size="0x34000"/>
|
||||
<device id="default" type="default"/>
|
||||
<serial id="dl11" adapter="0" binding="print"/>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
<machine id="test1170" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/70 with Front Panel</name>
|
||||
<computer id="computer" busWidth="22"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" resetAddr="0xC000" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xC000"/>
|
||||
<rom id="rom" addr="0xC000" file="/devices/pdp11/rom/test/boot.json" writable="true"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xE000" file="/devices/pdp11/ram/bootdemo/bootdemo.json" load="0xC000" exec="0xC000"/>
|
||||
<ram id="ram" addr="0x10000" size="0x34000"/>
|
||||
<device id="default" type="default"/>
|
||||
<serial id="dl11" adapter="0" binding="print"/>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
<machine id="test1170" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/70 Test Machine with Debugger</name>
|
||||
<computer id="computer" busWidth="22"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" resetAddr="0xC000"/>
|
||||
<ram id="ram" addr="0x0000" size="0xC000"/>
|
||||
<rom id="rom" addr="0xC000" file="/devices/pdp11/rom/test/boot.json" writable="true"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667"/>
|
||||
<ram id="ram" addr="0x0000" size="0xE000" file="/devices/pdp11/ram/bootdemo/bootdemo.json" load="0xC000" exec="0xC000"/>
|
||||
<ram id="ram" addr="0x10000" size="0x34000"/>
|
||||
<device id="default" type="default"/>
|
||||
<serial id="dl11" adapter="0" binding="print"/>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
<machine id="test1170" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/70 Test Machine</name>
|
||||
<computer id="computer" busWidth="22"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" resetAddr="0xC000" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xC000"/>
|
||||
<rom id="rom" addr="0xC000" file="/devices/pdp11/rom/test/boot.json" writable="true"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xE000" file="/devices/pdp11/ram/bootdemo/bootdemo.json" load="0xC000" exec="0xC000"/>
|
||||
<ram id="ram" addr="0x10000" size="0x34000"/>
|
||||
<device id="default" type="default"/>
|
||||
<serial id="dl11" adapter="0" binding="print"/>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
<machine id="test1170" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/70 with Front Panel</name>
|
||||
<computer id="computer" busWidth="22"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" resetAddr="0xC000" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xC000"/>
|
||||
<rom id="rom" addr="0xC000" file="/devices/pdp11/rom/test/boot.json" writable="true"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xE000" file="/devices/pdp11/ram/bootdemo/bootdemo.json" load="0xC000" exec="0xC000"/>
|
||||
<ram id="ram" addr="0x10000" size="0x34000"/>
|
||||
<device id="default" type="default"/>
|
||||
<serial id="dl11" adapter="0"/>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
<machine id="test1170" class="pdp11" border="1" pos="center" background="#FAEBD7">
|
||||
<name pos="center">PDP-11/70 with Front Panel</name>
|
||||
<computer id="computer" busWidth="22"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" resetAddr="0xC000" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xC000"/>
|
||||
<rom id="rom" addr="0xC000" file="/devices/pdp11/rom/test/boot.json" writable="true"/>
|
||||
<cpu id="cpu" model="1170" cycles="6666667" autoStart="true"/>
|
||||
<ram id="ram" addr="0x0000" size="0xE000" file="/devices/pdp11/ram/bootdemo/bootdemo.json" load="0xC000" exec="0xC000"/>
|
||||
<ram id="ram" addr="0x10000" size="0x34000"/>
|
||||
<device id="default" type="default"/>
|
||||
<serial id="dl11" adapter="0"/>
|
||||
|
|
|
|||
11
devices/pdp11/ram/README.md
Normal file
11
devices/pdp11/ram/README.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
layout: page
|
||||
title: PDP-11 RAM Images
|
||||
permalink: /devices/pdp11/ram/
|
||||
---
|
||||
|
||||
PDP-11 RAM Images
|
||||
-----------------
|
||||
|
||||
* [PDP-11 Boot Demo](bootdemo/)
|
||||
* [PDP-11 Bootstrap Loader](bootstrap/)
|
||||
15
devices/pdp11/ram/bootdemo/README.md
Normal file
15
devices/pdp11/ram/bootdemo/README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
layout: page
|
||||
title: PDP-11 Boot Demo
|
||||
permalink: /devices/pdp11/ram/bootdemo/
|
||||
redirect_from:
|
||||
- /devices/pdp11/rom/test/
|
||||
---
|
||||
|
||||
PDP-11 Boot Demo
|
||||
----------------
|
||||
|
||||
[BOOTDEMO.MAC](bootdemo.mac) is based on [BOOT.MAC](http://skn.noip.me/pdp11/boot.mac) written by [Paul Nankervis](mailto:paulnank@hotmail.com))
|
||||
|
||||
[BOOTDEMO.MAC](bootdemo.mac) was cross-assembled with [MACRO11](https://github.com/shattered/macro11) to produce [BOOTDEMO.LST](bootdemo.lst),
|
||||
which was then processed by [FileDump](/modules/filedump/) to produce [BOOTDEMO.JSON](bootdemo.json).
|
||||
11
devices/pdp11/ram/bootdemo/makefile
Normal file
11
devices/pdp11/ram/bootdemo/makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Don't have macro11? Make yourself a copy from https://github.com/shattered/macro11
|
||||
#
|
||||
|
||||
all: bootdemo.json
|
||||
|
||||
bootdemo.lst: bootdemo.mac
|
||||
macro11 bootdemo.mac -l bootdemo.lst
|
||||
|
||||
bootdemo.json: bootdemo.lst
|
||||
node ../../../../modules/filedump/bin/filedump --file=bootdemo.lst --format=octal --output=bootdemo.json --overwrite
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
---
|
||||
layout: page
|
||||
title: PDP-11 Loaders
|
||||
permalink: /devices/pdp11/loader/
|
||||
title: PDP-11 Bootstrap Loader
|
||||
permalink: /devices/pdp11/ram/bootstrap/
|
||||
---
|
||||
|
||||
PDP-11 Loaders
|
||||
--------------
|
||||
PDP-11 Bootstrap Loader
|
||||
-----------------------
|
||||
|
||||
The blog post "[PDP-11 Paper Tape BASIC](http://avitech.com.au/?page_id=709)" describes the *Bootstrap Loader*,
|
||||
a small program used to load the *Absolute Loader*, which in turn loads the *PDP-11 BASIC Paper Tape*.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
{"words":[
|
||||
{"load":0x3FE4,"exec":0x3FE4,"words":[
|
||||
0x1DC1 /*016701*/,0x0016 /*000026*/,0x15C2 /*012702*/,0x00EA /*000352*/,0x0A89 /*005211*/,0x8BC9 /*105711*/,0x80FE /*100376*/,0x9C72 /*116162*/,
|
||||
0x0002 /*000002*/,0x3F00 /*037400*/,0x0AB7 /*005267*/,0xFFEE /*177756*/,0x01F5 /*000765*/,0xFF68 /*177550*/]
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
layout: page
|
||||
title: PDP-11 ROMs
|
||||
title: PDP-11 ROM Images
|
||||
permalink: /devices/pdp11/rom/
|
||||
---
|
||||
|
||||
PDP-11 ROMs
|
||||
-----------
|
||||
PDP-11 ROM Images
|
||||
-----------------
|
||||
|
||||
* [Test ROM](test/) (based on [BOOT.MAC](http://skn.noip.me/pdp11/boot.mac) written by [Paul Nankervis](mailto:paulnank@hotmail.com))
|
||||
Any ROM images added to the project will be stored here.
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: page
|
||||
title: PDP-11 Test ROM
|
||||
permalink: /devices/pdp11/rom/test/
|
||||
---
|
||||
|
||||
PDP-11 Test ROM
|
||||
---------------
|
||||
|
||||
This isn't a ROM so much as a read-only image that can be loaded in RAM by the ROM component.
|
||||
|
||||
[BOOT.MAC](boot.mac) was cross-assembled with [MACRO11](https://github.com/shattered/macro11) to produce [BOOT.LST](boot.lst),
|
||||
which was then processed by [FileDump](/modules/filedump/) to produce [BOOT.JSON](boot.json).
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#
|
||||
# Don't have macro11? Make yourself a copy from https://github.com/shattered/macro11
|
||||
#
|
||||
|
||||
all: boot.json
|
||||
|
||||
boot.lst: boot.mac
|
||||
macro11 boot.mac -l boot.lst
|
||||
|
||||
boot.json: boot.lst
|
||||
node ../../../../modules/filedump/bin/filedump --file=boot.lst --format=octal --output=boot.json --overwrite
|
||||
|
|
@ -85,7 +85,7 @@
|
|||
}
|
||||
.pcjs-description, .pcjs-status {
|
||||
font-size: x-small;
|
||||
line-height: 2em;
|
||||
line-height: 2.8em;
|
||||
}
|
||||
.pcjs-key {
|
||||
border: 1px solid black;
|
||||
|
|
|
|||
|
|
@ -580,9 +580,9 @@
|
|||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="resetAddr">
|
||||
<xsl:variable name="addrReset">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@resetAddr"><xsl:value-of select="@resetAddr"/></xsl:when>
|
||||
<xsl:when test="@addrReset"><xsl:value-of select="@addrReset"/></xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
|
@ -610,7 +610,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class" select="'cpu'"/>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,resetAddr:<xsl:value-of select="$resetAddr"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,addrReset:<xsl:value-of select="$addrReset"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -931,16 +931,10 @@
|
|||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="writable">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@writable"><xsl:value-of select="@writable"/></xsl:when>
|
||||
<xsl:otherwise>false</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">rom</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>',writable:<xsl:value-of select="$writable"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>'</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -964,6 +958,24 @@
|
|||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="file">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@file"><xsl:value-of select="@file"/></xsl:when>
|
||||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="load">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@load"><xsl:value-of select="@load"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="exec">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@exec"><xsl:value-of select="@exec"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="test">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@test"><xsl:value-of select="@test"/></xsl:when>
|
||||
|
|
@ -973,7 +985,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">ram</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,file:'<xsl:value-of select="$file"/>',load:<xsl:value-of select="$load"/>,exec:<xsl:value-of select="$exec"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,12 @@
|
|||
if (NODE) {
|
||||
var str = require("../../shared/lib/strlib");
|
||||
var web = require("../../shared/lib/weblib");
|
||||
var DumpAPI = require("../../shared/lib/dumpapi");
|
||||
var Component = require("../../shared/lib/component");
|
||||
var State = require("../../shared/lib/state");
|
||||
var PC8080 = require("./defines");
|
||||
var CPUDef8080 = require("./cpudef");
|
||||
var Memory8080 = require("./memory");
|
||||
var ROM8080 = require("./rom");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -45,6 +46,9 @@ if (NODE) {
|
|||
*
|
||||
* addr: starting physical address of RAM (default is 0)
|
||||
* size: amount of RAM, in bytes (default is 0, which means defer to motherboard switch settings)
|
||||
* file: name of optional data file to load into RAM (default is "")
|
||||
* load: optional file load address (overrides any load address specified in the data file; default is null)
|
||||
* exec: optional file exec address (overrides any exec address specified in the data file; default is null)
|
||||
*
|
||||
* NOTE: We make a note of the specified size, but no memory is initially allocated for the RAM until the
|
||||
* Computer component calls powerUp().
|
||||
|
|
@ -57,14 +61,66 @@ function RAM8080(parmsRAM)
|
|||
{
|
||||
Component.call(this, "RAM", parmsRAM, RAM8080);
|
||||
|
||||
this.abInit = null;
|
||||
this.aSymbols = null;
|
||||
|
||||
this.addrRAM = parmsRAM['addr'];
|
||||
this.sizeRAM = parmsRAM['size'];
|
||||
this.nFileLoad = parmsRAM['load'];
|
||||
this.nFileExec = parmsRAM['exec'];
|
||||
|
||||
this.fInstalled = (!!this.sizeRAM); // 0 is the default value for 'size' when none is specified
|
||||
this.fAllocated = false;
|
||||
|
||||
this.sFilePath = parmsRAM['file'];
|
||||
this.sFileName = str.getBaseName(this.sFilePath);
|
||||
|
||||
if (this.sFilePath) {
|
||||
var sFileURL = this.sFilePath;
|
||||
if (DEBUG) this.log('load("' + sFileURL + '")');
|
||||
/*
|
||||
* If the selected data file has a ".json" extension, then we assume it's pre-converted
|
||||
* JSON-encoded data, so we load it as-is; ditto for ROM files with a ".hex" extension.
|
||||
* Otherwise, we ask our server-side converter to return the file in a JSON-compatible format.
|
||||
*/
|
||||
var sFileExt = str.getExtension(this.sFileName);
|
||||
if (sFileExt != DumpAPI.FORMAT.JSON && sFileExt != DumpAPI.FORMAT.HEX) {
|
||||
sFileURL = web.getHost() + DumpAPI.ENDPOINT + '?' + DumpAPI.QUERY.FILE + '=' + this.sFilePath + '&' + DumpAPI.QUERY.FORMAT + '=' + DumpAPI.FORMAT.BYTES + '&' + DumpAPI.QUERY.DECIMAL + '=true';
|
||||
}
|
||||
var ram = this;
|
||||
web.getResource(sFileURL, null, true, function(sURL, sResponse, nErrorCode) {
|
||||
ram.doneLoad(sURL, sResponse, nErrorCode);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Component.subclass(RAM8080);
|
||||
|
||||
RAM8080.CPM = {
|
||||
BIOS: {
|
||||
VECTOR: 0x0000
|
||||
},
|
||||
BDOS: {
|
||||
VECTOR: 0x0005,
|
||||
FUNC: { // function number (specified in regC)
|
||||
RESET: 0x00,
|
||||
CON_READ: 0x01, // output: A = L = ASCII character
|
||||
CON_WRITE: 0x02, // input: E = ASCII character
|
||||
AUX_READ: 0x03, // output: A = L = ASCII character
|
||||
AUX_WRITE: 0x04, // input: E = ASCII character
|
||||
PRN_WRITE: 0x05, // input: E = ASCII character
|
||||
MEM_SIZE: 0x06, // output: base address of CCP (Console Command Processor), but which register? (perhaps moot if this was CP/M 1.3 only...)
|
||||
CON_IO: 0x06, // input: E = ASCII character (or 0xFF to return ASCII character in A)
|
||||
GET_IOBYTE: 0x07,
|
||||
SET_IOBYTE: 0x08,
|
||||
STR_WRITE: 0x09 // input: DE = address of string
|
||||
}
|
||||
},
|
||||
INIT: 0x100
|
||||
};
|
||||
|
||||
RAM8080.CPM.VECTORS = [RAM8080.CPM.BIOS.VECTOR, RAM8080.CPM.BDOS.VECTOR];
|
||||
|
||||
/**
|
||||
* initBus(cmp, bus, cpu, dbg)
|
||||
*
|
||||
|
|
@ -79,7 +135,7 @@ RAM8080.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
this.bus = bus;
|
||||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
this.setReady();
|
||||
this.initRAM();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -92,15 +148,12 @@ RAM8080.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
*/
|
||||
RAM8080.prototype.powerUp = function(data, fRepower)
|
||||
{
|
||||
if (!fRepower) {
|
||||
/*
|
||||
* The Computer powers up the CPU last, at which point CPUState state is restored,
|
||||
* which includes the Bus state, and since we use the Bus to allocate all our memory,
|
||||
* memory contents are already restored for us, so we don't need the usual restore
|
||||
* logic. We just need to call reset(), to allocate memory for the RAM.
|
||||
* logic.
|
||||
*/
|
||||
this.reset();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -120,7 +173,98 @@ RAM8080.prototype.powerDown = function(fSave, fShutdown)
|
|||
* our memory, memory contents are already saved for us, so we don't need the usual
|
||||
* save logic.
|
||||
*/
|
||||
return (fSave)? this.save() : true;
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* doneLoad(sURL, sData, nErrorCode)
|
||||
*
|
||||
* @this {RAM8080}
|
||||
* @param {string} sURL
|
||||
* @param {string} sData
|
||||
* @param {number} nErrorCode (response from server if anything other than 200)
|
||||
*/
|
||||
RAM8080.prototype.doneLoad = function(sURL, sData, nErrorCode)
|
||||
{
|
||||
if (nErrorCode) {
|
||||
this.notice("Unable to load RAM resource (error " + nErrorCode + ": " + sURL + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
Component.addMachineResource(this.idMachine, sURL, sData);
|
||||
|
||||
var resource = web.parseMemoryResource(sURL, sData);
|
||||
if (resource) {
|
||||
this.abInit = resource.aBytes;
|
||||
this.aSymbols = resource.aSymbols;
|
||||
if (this.nFileLoad == null && resource.nLoad != null) this.nFileLoad = resource.nLoad;
|
||||
if (this.nFileExec == null && resource.nExec != null) this.nFileExec = resource.nExec;
|
||||
} else {
|
||||
this.sFilePath = null;
|
||||
}
|
||||
this.initRAM();
|
||||
};
|
||||
|
||||
/**
|
||||
* initRAM()
|
||||
*
|
||||
* This function is called by both initBus() and doneLoad(), but it cannot copy the initial data into place
|
||||
* until after initBus() has received the Bus component AND doneLoad() has received the data. When both those
|
||||
* criteria are satisfied, the component becomes "ready".
|
||||
*
|
||||
* @this {RAM8080}
|
||||
*/
|
||||
RAM8080.prototype.initRAM = function()
|
||||
{
|
||||
if (!this.fAllocated && this.sizeRAM) {
|
||||
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, Memory8080.TYPE.RAM)) {
|
||||
this.fAllocated = true;
|
||||
}
|
||||
}
|
||||
if (!this.isReady()) {
|
||||
if (!this.fAllocated) {
|
||||
Component.error("No RAM allocated");
|
||||
}
|
||||
else if (this.sFilePath) {
|
||||
/*
|
||||
* Too early...
|
||||
*/
|
||||
if (!this.abInit || !this.bus) return;
|
||||
|
||||
var addr = this.addrRAM;
|
||||
if (this.nFileLoad !== null) addr = this.nFileLoad;
|
||||
for (var i = 0; i < this.abInit.length; i++) {
|
||||
this.bus.setByteDirect(addr + i, this.abInit[i]);
|
||||
}
|
||||
|
||||
if (this.nFileExec !== null) {
|
||||
/*
|
||||
* Here's where we enable our "Fake CP/M" support, triggered by the user loading a "writable" ROM image
|
||||
* at offset 0x100. Fake CP/M support works by installing HLT opcodes at well-known CP/M addresses
|
||||
* (namely, 0x0000, which is the CP/M reset vector, and 0x0005, which is the CP/M system call vector) and
|
||||
* then telling the CPU to call us whenever a HLT occurs, so we can check PC for one of these addresses.
|
||||
*/
|
||||
if (this.nFileExec == RAM8080.CPM.INIT) {
|
||||
for (i = 0; i < RAM8080.CPM.VECTORS.length; i++) {
|
||||
this.bus.setByteDirect(RAM8080.CPM.VECTORS[i], CPUDef8080.OPCODE.HLT);
|
||||
}
|
||||
|
||||
this.cpu.addHaltCheck(function(rom) {
|
||||
return function(addr) {
|
||||
return rom.checkCPMVector(addr)
|
||||
};
|
||||
}(this));
|
||||
}
|
||||
this.cpu.setReset(this.nFileExec);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Consider an option to retain this data and give the user a way of restoring the initial contents.
|
||||
*/
|
||||
delete this.abInit;
|
||||
}
|
||||
this.setReady();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -130,41 +274,99 @@ RAM8080.prototype.powerDown = function(fSave, fShutdown)
|
|||
*/
|
||||
RAM8080.prototype.reset = function()
|
||||
{
|
||||
if (!this.fAllocated && this.sizeRAM) {
|
||||
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, Memory8080.TYPE.RAM)) {
|
||||
this.fAllocated = true;
|
||||
}
|
||||
}
|
||||
if (!this.fAllocated) {
|
||||
Component.error("No RAM allocated");
|
||||
}
|
||||
/*
|
||||
* If you want to zero RAM on reset, then this would be a good place to do it.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* save()
|
||||
*
|
||||
* This implements save support for the RAM8080 component.
|
||||
* checkCPMVector(addr)
|
||||
*
|
||||
* @this {RAM8080}
|
||||
* @return {Object}
|
||||
* @param {number} addr (of the HLT opcode)
|
||||
* @return {boolean} true if special processing performed, false if not
|
||||
*/
|
||||
RAM8080.prototype.save = function()
|
||||
{
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* restore(data)
|
||||
*
|
||||
* This implements restore support for the RAM8080 component.
|
||||
*
|
||||
* @this {RAM8080}
|
||||
* @param {Object} data
|
||||
* @return {boolean} true if successful, false if failure
|
||||
*/
|
||||
RAM8080.prototype.restore = function(data)
|
||||
RAM8080.prototype.checkCPMVector = function(addr)
|
||||
{
|
||||
var i = RAM8080.CPM.VECTORS.indexOf(addr);
|
||||
if (i >= 0) {
|
||||
var fCPM = false;
|
||||
var cpu = this.cpu;
|
||||
var dbg = this.dbg;
|
||||
if (addr == RAM8080.CPM.BDOS.VECTOR) {
|
||||
fCPM = true;
|
||||
switch(cpu.regC) {
|
||||
case RAM8080.CPM.BDOS.FUNC.CON_WRITE:
|
||||
this.writeCPMString(this.getCPMChar(cpu.regE));
|
||||
break;
|
||||
case RAM8080.CPM.BDOS.FUNC.STR_WRITE:
|
||||
this.writeCPMString(this.getCPMString(cpu.getDE(), '$'));
|
||||
break;
|
||||
default:
|
||||
fCPM = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fCPM) {
|
||||
CPUDef8080.opRET.call(cpu); // for recognized calls, automatically return
|
||||
}
|
||||
else if (dbg) {
|
||||
this.println("\nCP/M vector " + str.toHexWord(addr));
|
||||
cpu.setPC(addr); // this is purely for the Debugger's benefit, to show the HLT
|
||||
dbg.stopCPU();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* getCPMChar(ch)
|
||||
*
|
||||
* @this {RAM8080}
|
||||
* @param {number} ch
|
||||
* @return {string}
|
||||
*/
|
||||
RAM8080.prototype.getCPMChar = function(ch)
|
||||
{
|
||||
return String.fromCharCode(ch);
|
||||
};
|
||||
|
||||
/**
|
||||
* getCPMString(addr, chEnd)
|
||||
*
|
||||
* @this {RAM8080}
|
||||
* @param {number} addr (of a string)
|
||||
* @param {string|number} [chEnd] (terminating character, default is 0)
|
||||
* @return {string}
|
||||
*/
|
||||
RAM8080.prototype.getCPMString = function(addr, chEnd)
|
||||
{
|
||||
var s = "";
|
||||
var cchMax = 255;
|
||||
var bEnd = chEnd && chEnd.length && chEnd.charCodeAt(0) || chEnd || 0;
|
||||
while (cchMax--) {
|
||||
var b = this.cpu.getByte(addr++);
|
||||
if (b == bEnd) break;
|
||||
s += String.fromCharCode(b);
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
/**
|
||||
* writeCPMString(s)
|
||||
*
|
||||
* @this {RAM8080}
|
||||
* @param {string} s
|
||||
*/
|
||||
RAM8080.prototype.writeCPMString = function(s)
|
||||
{
|
||||
s = s.replace(/\r/g, '');
|
||||
if (this.controlPrint) {
|
||||
this.controlPrint.value += s;
|
||||
this.controlPrint.scrollTop = this.controlPrint.scrollHeight;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ if (NODE) {
|
|||
var DumpAPI = require("../../shared/lib/dumpapi");
|
||||
var Component = require("../../shared/lib/component");
|
||||
var PC8080 = require("./defines");
|
||||
var CPUDef8080 = require("./cpudef");
|
||||
var Memory8080 = require("./memory");
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +46,6 @@ if (NODE) {
|
|||
* size: amount of ROM, in bytes
|
||||
* alias: physical alias address (null if none)
|
||||
* file: name of ROM data file
|
||||
* writable: true to make ROM writable (default is false)
|
||||
*
|
||||
* NOTE: The ROM data will not be copied into place until the Bus is ready (see initBus()) AND the
|
||||
* ROM data file has finished loading (see doneLoad()).
|
||||
|
|
@ -55,13 +53,6 @@ if (NODE) {
|
|||
* Also, while the size parameter may seem redundant, I consider it useful to confirm that the ROM you received
|
||||
* is the ROM you expected.
|
||||
*
|
||||
* Finally, while making ROM "writable" may seem a contradiction in terms, I want to be able to load selected
|
||||
* binary files into memory purely for testing purposes, and the RAM component has no "file" option, so the
|
||||
* simplest solution was to add the option to load binary files into memory as "writable" ROMs.
|
||||
*
|
||||
* Moreover, if a "writable" ROM is installed at addr 0x100, that triggers our "Fake CP/M" support, providing
|
||||
* a quick-and-dirty means of loading simple CP/M test binaries. See addROM() for details.
|
||||
*
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @param {Object} parmsROM
|
||||
|
|
@ -73,7 +64,7 @@ function ROM8080(parmsROM)
|
|||
this.abROM = null;
|
||||
this.addrROM = parmsROM['addr'];
|
||||
this.sizeROM = parmsROM['size'];
|
||||
this.fWritable = parmsROM['writable'];
|
||||
|
||||
|
||||
/*
|
||||
* The new 'alias' property can now be EITHER a single physical address (like 'addr') OR an array of
|
||||
|
|
@ -112,30 +103,6 @@ function ROM8080(parmsROM)
|
|||
|
||||
Component.subclass(ROM8080);
|
||||
|
||||
ROM8080.CPM = {
|
||||
BIOS: {
|
||||
VECTOR: 0x0000
|
||||
},
|
||||
BDOS: {
|
||||
VECTOR: 0x0005,
|
||||
FUNC: { // function number (specified in regC)
|
||||
RESET: 0x00,
|
||||
CON_READ: 0x01, // output: A = L = ASCII character
|
||||
CON_WRITE: 0x02, // input: E = ASCII character
|
||||
AUX_READ: 0x03, // output: A = L = ASCII character
|
||||
AUX_WRITE: 0x04, // input: E = ASCII character
|
||||
PRN_WRITE: 0x05, // input: E = ASCII character
|
||||
MEM_SIZE: 0x06, // output: base address of CCP (Console Command Processor), but which register? (perhaps moot if this was CP/M 1.3 only...)
|
||||
CON_IO: 0x06, // input: E = ASCII character (or 0xFF to return ASCII character in A)
|
||||
GET_IOBYTE: 0x07,
|
||||
SET_IOBYTE: 0x08,
|
||||
STR_WRITE: 0x09 // input: DE = address of string
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ROM8080.CPM.VECTORS = [ROM8080.CPM.BIOS.VECTOR, ROM8080.CPM.BDOS.VECTOR];
|
||||
|
||||
/*
|
||||
* NOTE: There's currently no need for this component to have a reset() function, since
|
||||
* once the ROM data is loaded, it can't be changed, so there's nothing to reinitialize.
|
||||
|
|
@ -350,31 +317,12 @@ ROM8080.prototype.copyROM = function()
|
|||
*/
|
||||
ROM8080.prototype.addROM = function(addr)
|
||||
{
|
||||
if (this.bus.addMemory(addr, this.sizeROM, this.fWritable? Memory8080.TYPE.RAM : Memory8080.TYPE.ROM)) {
|
||||
if (this.bus.addMemory(addr, this.sizeROM, Memory8080.TYPE.ROM)) {
|
||||
if (DEBUG) this.log("addROM(): copying ROM to " + str.toHexLong(addr) + " (" + str.toHexLong(this.abROM.length) + " bytes)");
|
||||
var i;
|
||||
for (i = 0; i < this.abROM.length; i++) {
|
||||
this.bus.setByteDirect(addr + i, this.abROM[i]);
|
||||
}
|
||||
if (this.fWritable && addr == 0x100) {
|
||||
/*
|
||||
* Here's where we enable our "Fake CP/M" support, triggered by the user loading a "writable" ROM image
|
||||
* at offset 0x100. Fake CP/M support works by installing HLT opcodes at well-known CP/M addresses
|
||||
* (namely, 0x0000, which is the CP/M reset vector, and 0x0005, which is the CP/M system call vector) and
|
||||
* then telling the CPU to call us whenever a HLT occurs, so we can check PC for one of these addresses.
|
||||
*/
|
||||
for (i = 0; i < ROM8080.CPM.VECTORS.length; i++) {
|
||||
this.bus.setByteDirect(ROM8080.CPM.VECTORS[i], CPUDef8080.OPCODE.HLT);
|
||||
}
|
||||
|
||||
this.cpu.addHaltCheck(function(rom) {
|
||||
return function(addr) {
|
||||
return rom.checkCPMVector(addr)
|
||||
};
|
||||
}(this));
|
||||
|
||||
this.cpu.setReset(addr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
|
|
@ -383,96 +331,6 @@ ROM8080.prototype.addROM = function(addr)
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* checkCPMVector(addr)
|
||||
*
|
||||
* @this {ROM8080}
|
||||
* @param {number} addr (of the HLT opcode)
|
||||
* @return {boolean} true if special processing performed, false if not
|
||||
*/
|
||||
ROM8080.prototype.checkCPMVector = function(addr)
|
||||
{
|
||||
var i = ROM8080.CPM.VECTORS.indexOf(addr);
|
||||
if (i >= 0) {
|
||||
var fCPM = false;
|
||||
var cpu = this.cpu;
|
||||
var dbg = this.dbg;
|
||||
if (addr == ROM8080.CPM.BDOS.VECTOR) {
|
||||
fCPM = true;
|
||||
switch(cpu.regC) {
|
||||
case ROM8080.CPM.BDOS.FUNC.CON_WRITE:
|
||||
this.writeCPMString(this.getCPMChar(cpu.regE));
|
||||
break;
|
||||
case ROM8080.CPM.BDOS.FUNC.STR_WRITE:
|
||||
this.writeCPMString(this.getCPMString(cpu.getDE(), '$'));
|
||||
break;
|
||||
default:
|
||||
fCPM = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fCPM) {
|
||||
CPUDef8080.opRET.call(cpu); // for recognized calls, automatically return
|
||||
}
|
||||
else if (dbg) {
|
||||
this.println("\nCP/M vector " + str.toHexWord(addr));
|
||||
cpu.setPC(addr); // this is purely for the Debugger's benefit, to show the HLT
|
||||
dbg.stopCPU();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* getCPMChar(ch)
|
||||
*
|
||||
* @this {ROM8080}
|
||||
* @param {number} ch
|
||||
* @return {string}
|
||||
*/
|
||||
ROM8080.prototype.getCPMChar = function(ch)
|
||||
{
|
||||
return String.fromCharCode(ch);
|
||||
};
|
||||
|
||||
/**
|
||||
* getCPMString(addr, chEnd)
|
||||
*
|
||||
* @this {ROM8080}
|
||||
* @param {number} addr (of a string)
|
||||
* @param {string|number} [chEnd] (terminating character, default is 0)
|
||||
* @return {string}
|
||||
*/
|
||||
ROM8080.prototype.getCPMString = function(addr, chEnd)
|
||||
{
|
||||
var s = "";
|
||||
var cchMax = 255;
|
||||
var bEnd = chEnd && chEnd.length && chEnd.charCodeAt(0) || chEnd || 0;
|
||||
while (cchMax--) {
|
||||
var b = this.cpu.getByte(addr++);
|
||||
if (b == bEnd) break;
|
||||
s += String.fromCharCode(b);
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
/**
|
||||
* writeCPMString(s)
|
||||
*
|
||||
* @this {ROM8080}
|
||||
* @param {string} s
|
||||
*/
|
||||
ROM8080.prototype.writeCPMString = function(s)
|
||||
{
|
||||
s = s.replace(/\r/g, '');
|
||||
if (this.controlPrint) {
|
||||
this.controlPrint.value += s;
|
||||
this.controlPrint.scrollTop = this.controlPrint.scrollHeight;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* cloneROM(addr)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ if (NODE) {
|
|||
* The CPUStatePDP11 class uses the following (parmsCPU) properties:
|
||||
*
|
||||
* model: a number (eg, 1170) that should match one of the PDP11.MODEL_* values
|
||||
* resetAddr: reset address (default is 0)
|
||||
* addrReset: reset address (default is 0)
|
||||
*
|
||||
* This extends the CPU class and passes any remaining parmsCPU properties to the CPU class
|
||||
* constructor, along with a default speed (cycles per second) based on the specified (or default)
|
||||
|
|
@ -63,7 +63,7 @@ if (NODE) {
|
|||
function CPUStatePDP11(parmsCPU)
|
||||
{
|
||||
this.model = +parmsCPU['model'] || PDP11.MODEL_1170;
|
||||
this.resetAddr = parmsCPU['resetAddr'] || 0;
|
||||
this.addrReset = parmsCPU['addrReset'] || 0;
|
||||
|
||||
var nCyclesDefault = 0;
|
||||
switch(this.model) {
|
||||
|
|
@ -175,7 +175,7 @@ CPUStatePDP11.prototype.initRegs = function()
|
|||
this.flagN = 0x8000; // PSW N bit
|
||||
this.regPSW = 0x000f; // PSW other bits (TODO: What's the point of setting the flag bits here, too?)
|
||||
this.regsGen = [ // General R0 - R7
|
||||
0, 0, 0, 0, 0, 0, 0, this.resetAddr
|
||||
0, 0, 0, 0, 0, 0, 0, this.addrReset
|
||||
];
|
||||
this.regsAlt = [ // Alternate R0 - R5
|
||||
0, 0, 0, 0, 0, 0
|
||||
|
|
@ -359,6 +359,18 @@ CPUStatePDP11.prototype.setMMR3 = function(newMMR3)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* setReset(addr)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
*/
|
||||
CPUStatePDP11.prototype.setReset = function(addr)
|
||||
{
|
||||
this.addrReset = addr;
|
||||
this.setPC(addr);
|
||||
};
|
||||
|
||||
/**
|
||||
* getChecksum()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@
|
|||
if (NODE) {
|
||||
var str = require("../../shared/lib/strlib");
|
||||
var web = require("../../shared/lib/weblib");
|
||||
var DumpAPI = require("../../shared/lib/dumpapi");
|
||||
var Component = require("../../shared/lib/component");
|
||||
var State = require("../../shared/lib/state");
|
||||
var PDP11 = require("./defines");
|
||||
var MemoryPDP11 = require("./memory");
|
||||
var ROMPDP11 = require("./rom");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -49,6 +49,9 @@ if (NODE) {
|
|||
*
|
||||
* addr: starting physical address of RAM (default is 0)
|
||||
* size: amount of RAM, in bytes (default is 0, which means defer to motherboard switch settings)
|
||||
* file: name of optional data file to load into RAM (default is "")
|
||||
* load: optional file load address (overrides any load address specified in the data file; default is null)
|
||||
* exec: optional file exec address (overrides any exec address specified in the data file; default is null)
|
||||
*
|
||||
* NOTE: We make a note of the specified size, but no memory is initially allocated for the RAM until the
|
||||
* Computer component calls powerUp().
|
||||
|
|
@ -61,10 +64,37 @@ function RAMPDP11(parmsRAM)
|
|||
{
|
||||
Component.call(this, "RAM", parmsRAM, RAMPDP11);
|
||||
|
||||
this.abInit = null;
|
||||
this.aSymbols = null;
|
||||
|
||||
this.addrRAM = parmsRAM['addr'];
|
||||
this.sizeRAM = parmsRAM['size'];
|
||||
this.nFileLoad = parmsRAM['load'];
|
||||
this.nFileExec = parmsRAM['exec'];
|
||||
|
||||
this.fInstalled = (!!this.sizeRAM); // 0 is the default value for 'size' when none is specified
|
||||
this.fAllocated = false;
|
||||
|
||||
this.sFilePath = parmsRAM['file'];
|
||||
this.sFileName = str.getBaseName(this.sFilePath);
|
||||
|
||||
if (this.sFilePath) {
|
||||
var sFileURL = this.sFilePath;
|
||||
if (DEBUG) this.log('load("' + sFileURL + '")');
|
||||
/*
|
||||
* If the selected data file has a ".json" extension, then we assume it's pre-converted
|
||||
* JSON-encoded data, so we load it as-is; ditto for ROM files with a ".hex" extension.
|
||||
* Otherwise, we ask our server-side converter to return the file in a JSON-compatible format.
|
||||
*/
|
||||
var sFileExt = str.getExtension(this.sFileName);
|
||||
if (sFileExt != DumpAPI.FORMAT.JSON && sFileExt != DumpAPI.FORMAT.HEX) {
|
||||
sFileURL = web.getHost() + DumpAPI.ENDPOINT + '?' + DumpAPI.QUERY.FILE + '=' + this.sFilePath + '&' + DumpAPI.QUERY.FORMAT + '=' + DumpAPI.FORMAT.BYTES + '&' + DumpAPI.QUERY.DECIMAL + '=true';
|
||||
}
|
||||
var ram = this;
|
||||
web.getResource(sFileURL, null, true, function(sURL, sResponse, nErrorCode) {
|
||||
ram.doneLoad(sURL, sResponse, nErrorCode);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Component.subclass(RAMPDP11);
|
||||
|
|
@ -86,24 +116,6 @@ RAMPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
this.initRAM();
|
||||
};
|
||||
|
||||
/**
|
||||
* initRAM()
|
||||
*
|
||||
* @this {RAMPDP11}
|
||||
*/
|
||||
RAMPDP11.prototype.initRAM = function()
|
||||
{
|
||||
if (!this.fAllocated && this.sizeRAM) {
|
||||
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, MemoryPDP11.TYPE.RAM)) {
|
||||
this.fAllocated = true;
|
||||
}
|
||||
}
|
||||
if (!this.fAllocated) {
|
||||
Component.error("No RAM allocated");
|
||||
}
|
||||
this.setReady();
|
||||
};
|
||||
|
||||
/**
|
||||
* powerUp(data, fRepower)
|
||||
*
|
||||
|
|
@ -142,6 +154,80 @@ RAMPDP11.prototype.powerDown = function(fSave, fShutdown)
|
|||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* doneLoad(sURL, sData, nErrorCode)
|
||||
*
|
||||
* @this {RAMPDP11}
|
||||
* @param {string} sURL
|
||||
* @param {string} sData
|
||||
* @param {number} nErrorCode (response from server if anything other than 200)
|
||||
*/
|
||||
RAMPDP11.prototype.doneLoad = function(sURL, sData, nErrorCode)
|
||||
{
|
||||
if (nErrorCode) {
|
||||
this.notice("Unable to load RAM resource (error " + nErrorCode + ": " + sURL + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
Component.addMachineResource(this.idMachine, sURL, sData);
|
||||
|
||||
var resource = web.parseMemoryResource(sURL, sData);
|
||||
if (resource) {
|
||||
this.abInit = resource.aBytes;
|
||||
this.aSymbols = resource.aSymbols;
|
||||
if (this.nFileLoad == null && resource.nLoad != null) this.nFileLoad = resource.nLoad;
|
||||
if (this.nFileExec == null && resource.nExec != null) this.nFileExec = resource.nExec;
|
||||
} else {
|
||||
this.sFilePath = null;
|
||||
}
|
||||
this.initRAM();
|
||||
};
|
||||
|
||||
/**
|
||||
* initRAM()
|
||||
*
|
||||
* This function is called by both initBus() and doneLoad(), but it cannot copy the initial data into place
|
||||
* until after initBus() has received the Bus component AND doneLoad() has received the data. When both those
|
||||
* criteria are satisfied, the component becomes "ready".
|
||||
*
|
||||
* @this {RAMPDP11}
|
||||
*/
|
||||
RAMPDP11.prototype.initRAM = function()
|
||||
{
|
||||
if (!this.fAllocated && this.sizeRAM) {
|
||||
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, MemoryPDP11.TYPE.RAM)) {
|
||||
this.fAllocated = true;
|
||||
}
|
||||
}
|
||||
if (!this.isReady()) {
|
||||
if (!this.fAllocated) {
|
||||
Component.error("No RAM allocated");
|
||||
}
|
||||
else if (this.sFilePath) {
|
||||
/*
|
||||
* Too early...
|
||||
*/
|
||||
if (!this.abInit || !this.bus) return;
|
||||
|
||||
var addr = this.addrRAM;
|
||||
if (this.nFileLoad !== null) addr = this.nFileLoad;
|
||||
for (var i = 0; i < this.abInit.length; i++) {
|
||||
this.bus.setByteDirect(addr + i, this.abInit[i]);
|
||||
}
|
||||
|
||||
if (this.nFileExec !== null) {
|
||||
this.cpu.setReset(this.nFileExec);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Consider an option to retain this data and give the user a way of restoring the initial contents.
|
||||
*/
|
||||
delete this.abInit;
|
||||
}
|
||||
this.setReady();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* reset()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ if (NODE) {
|
|||
* size: amount of ROM, in bytes
|
||||
* alias: physical alias address (null if none)
|
||||
* file: name of ROM data file
|
||||
* writable: true to make ROM writable (default is false)
|
||||
*
|
||||
* NOTE: The ROM data will not be copied into place until the Bus is ready (see initBus()) AND the
|
||||
* ROM data file has finished loading (see doneLoad()).
|
||||
|
|
@ -58,10 +57,6 @@ if (NODE) {
|
|||
* Also, while the size parameter may seem redundant, I consider it useful to confirm that the ROM you received
|
||||
* is the ROM you expected.
|
||||
*
|
||||
* Finally, while making ROM "writable" may seem a contradiction in terms, I want to be able to load selected
|
||||
* binary files into memory purely for testing purposes, and the RAM component has no "file" option, so the
|
||||
* simplest solution was to add the option to load binary files into memory as "writable" ROMs.
|
||||
*
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @param {Object} parmsROM
|
||||
|
|
@ -70,10 +65,11 @@ function ROMPDP11(parmsROM)
|
|||
{
|
||||
Component.call(this, "ROM", parmsROM, ROMPDP11);
|
||||
|
||||
this.abROM = null;
|
||||
this.abInit = null;
|
||||
this.aSymbols = null;
|
||||
|
||||
this.addrROM = parmsROM['addr'];
|
||||
this.sizeROM = parmsROM['size'];
|
||||
this.fWritable = parmsROM['writable'];
|
||||
|
||||
/*
|
||||
* The new 'alias' property can now be EITHER a single physical address (like 'addr') OR an array of
|
||||
|
|
@ -184,87 +180,28 @@ ROMPDP11.prototype.powerDown = function(fSave, fShutdown)
|
|||
};
|
||||
|
||||
/**
|
||||
* doneLoad(sURL, sROMData, nErrorCode)
|
||||
* doneLoad(sURL, sData, nErrorCode)
|
||||
*
|
||||
* @this {ROMPDP11}
|
||||
* @param {string} sURL
|
||||
* @param {string} sROMData
|
||||
* @param {string} sData
|
||||
* @param {number} nErrorCode (response from server if anything other than 200)
|
||||
*/
|
||||
ROMPDP11.prototype.doneLoad = function(sURL, sROMData, nErrorCode)
|
||||
ROMPDP11.prototype.doneLoad = function(sURL, sData, nErrorCode)
|
||||
{
|
||||
if (nErrorCode) {
|
||||
this.notice("Unable to load system ROM (error " + nErrorCode + ": " + sURL + ")");
|
||||
this.notice("Unable to load ROM resource (error " + nErrorCode + ": " + sURL + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
Component.addMachineResource(this.idMachine, sURL, sROMData);
|
||||
Component.addMachineResource(this.idMachine, sURL, sData);
|
||||
|
||||
var i;
|
||||
if (sROMData.charAt(0) == "[" || sROMData.charAt(0) == "{") {
|
||||
try {
|
||||
/*
|
||||
* The most likely source of any exception will be here: parsing the JSON-encoded ROM.
|
||||
*/
|
||||
var a, ib;
|
||||
var rom = eval("(" + sROMData + ")");
|
||||
|
||||
if (a = rom['bytes']) {
|
||||
this.abROM = a;
|
||||
}
|
||||
else if (a = rom['words']) {
|
||||
/*
|
||||
* Convert all WORDs into BYTEs, so that subsequent code only has to deal with abROM.
|
||||
*/
|
||||
this.abROM = new Array(a.length * 2);
|
||||
for (i = 0, ib = 0; i < a.length; i++) {
|
||||
this.abROM[ib++] = a[i] & 0xff;
|
||||
this.abROM[ib++] = (a[i] >> 8) & 0xff;
|
||||
this.assert(!(a[i] & ~0xffff));
|
||||
}
|
||||
}
|
||||
else if (a = rom['data']) {
|
||||
/*
|
||||
* Convert all DWORDs into BYTEs, so that subsequent code only has to deal with abROM.
|
||||
*/
|
||||
this.abROM = new Array(a.length * 4);
|
||||
for (i = 0, ib = 0; i < a.length; i++) {
|
||||
this.abROM[ib++] = a[i] & 0xff;
|
||||
this.abROM[ib++] = (a[i] >> 8) & 0xff;
|
||||
this.abROM[ib++] = (a[i] >> 16) & 0xff;
|
||||
this.abROM[ib++] = (a[i] >> 24) & 0xff;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.abROM = rom;
|
||||
}
|
||||
|
||||
this.aSymbols = rom['symbols'];
|
||||
|
||||
if (!this.abROM.length) {
|
||||
Component.error("Empty ROM: " + sURL);
|
||||
return;
|
||||
}
|
||||
else if (this.abROM.length == 1) {
|
||||
Component.error(this.abROM[0]);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
this.notice("ROM data error: " + e.message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Parse the ROM data manually; we assume it's in "simplified" hex form (a series of hex byte-values
|
||||
* separated by whitespace).
|
||||
*/
|
||||
var sHexData = sROMData.replace(/\n/gm, " ").replace(/ +$/, "");
|
||||
var asHexData = sHexData.split(" ");
|
||||
this.abROM = new Array(asHexData.length);
|
||||
for (i = 0; i < asHexData.length; i++) {
|
||||
this.abROM[i] = str.parseInt(asHexData[i], 16);
|
||||
}
|
||||
var resource = web.parseMemoryResource(sURL, sData);
|
||||
if (resource) {
|
||||
this.abInit = resource.aBytes;
|
||||
this.aSymbols = resource.aSymbols;
|
||||
} else {
|
||||
this.sFilePath = null;
|
||||
}
|
||||
this.initROM();
|
||||
};
|
||||
|
|
@ -272,33 +209,35 @@ ROMPDP11.prototype.doneLoad = function(sURL, sROMData, nErrorCode)
|
|||
/**
|
||||
* initROM()
|
||||
*
|
||||
* This function is called by both initBus() and doneLoad(), but it cannot copy the the ROM data into place
|
||||
* until after initBus() has received the Bus component AND doneLoad() has received the abROM data. When both
|
||||
* those criteria are satisfied, the component becomes "ready".
|
||||
* This function is called by both initBus() and doneLoad(), but it cannot copy the initial data into place
|
||||
* until after initBus() has received the Bus component AND doneLoad() has received the data. When both those
|
||||
* criteria are satisfied, the component becomes "ready".
|
||||
*
|
||||
* @this {ROMPDP11}
|
||||
*/
|
||||
ROMPDP11.prototype.initROM = function()
|
||||
{
|
||||
if (!this.isReady()) {
|
||||
if (!this.sFilePath) {
|
||||
this.setReady();
|
||||
}
|
||||
else if (this.abROM && this.bus) {
|
||||
if (this.sFilePath) {
|
||||
/*
|
||||
* Too early...
|
||||
*/
|
||||
if (!this.abInit || !this.bus) return;
|
||||
|
||||
/*
|
||||
* If no explicit size was specified, then use whatever the actual size is.
|
||||
*/
|
||||
if (!this.sizeROM) {
|
||||
this.sizeROM = this.abROM.length;
|
||||
this.sizeROM = this.abInit.length;
|
||||
}
|
||||
if (this.abROM.length != this.sizeROM) {
|
||||
if (this.abInit.length != this.sizeROM) {
|
||||
/*
|
||||
* Note that setError() sets the component's fError flag, which in turn prevents setReady() from
|
||||
* marking the component ready. TODO: Revisit this decision. On the one hand, it sounds like a
|
||||
* good idea to stop the machine in its tracks whenever a setError() occurs, but there may also be
|
||||
* times when we'd like to forge ahead anyway.
|
||||
*/
|
||||
this.setError("ROM size (" + str.toHexLong(this.abROM.length) + ") does not match specified size (" + str.toHexLong(this.sizeROM) + ")");
|
||||
this.setError("ROM size (" + str.toHexLong(this.abInit.length) + ") does not match specified size (" + str.toHexLong(this.sizeROM) + ")");
|
||||
}
|
||||
else if (this.addROM(this.addrROM)) {
|
||||
|
||||
|
|
@ -312,7 +251,7 @@ ROMPDP11.prototype.initROM = function()
|
|||
this.cloneROM(aliases[i]);
|
||||
}
|
||||
/*
|
||||
* We used to hang onto the original ROM data so that we could restore any bytes the CPU overwrote,
|
||||
* We used to hang onto the initial ROM data so that we could restore any bytes the CPU overwrote,
|
||||
* using memory write-notification handlers, but with the introduction of read-only memory blocks, that's
|
||||
* no longer necessary.
|
||||
*
|
||||
|
|
@ -321,11 +260,11 @@ ROMPDP11.prototype.initROM = function()
|
|||
* whether they're ROM or RAM. However, the only way to modify a machine's ROM is with the Debugger,
|
||||
* and Debugger users should know better.
|
||||
*/
|
||||
delete this.abROM;
|
||||
delete this.abInit;
|
||||
}
|
||||
}
|
||||
this.setReady();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -337,11 +276,11 @@ ROMPDP11.prototype.initROM = function()
|
|||
*/
|
||||
ROMPDP11.prototype.addROM = function(addr)
|
||||
{
|
||||
if (this.bus.addMemory(addr, this.sizeROM, this.fWritable? MemoryPDP11.TYPE.RAM : MemoryPDP11.TYPE.ROM)) {
|
||||
if (DEBUG) this.log("addROM(): copying ROM to " + str.toHexLong(addr) + " (" + str.toHexLong(this.abROM.length) + " bytes)");
|
||||
if (this.bus.addMemory(addr, this.sizeROM, MemoryPDP11.TYPE.ROM)) {
|
||||
if (DEBUG) this.log("addROM(): copying ROM to " + str.toHexLong(addr) + " (" + str.toHexLong(this.abInit.length) + " bytes)");
|
||||
var i;
|
||||
for (i = 0; i < this.abROM.length; i++) {
|
||||
this.bus.setByteDirect(addr + i, this.abROM[i]);
|
||||
for (i = 0; i < this.abInit.length; i++) {
|
||||
this.bus.setByteDirect(addr + i, this.abInit[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,6 +283,90 @@ web.getResource = function(sURL, dataPost, fAsync, done)
|
|||
return response;
|
||||
};
|
||||
|
||||
/**
|
||||
* parseMemoryResource(sURL, sData)
|
||||
*
|
||||
* @param {string} sData
|
||||
* @return {Object|null} (resource)
|
||||
*/
|
||||
web.parseMemoryResource = function(sURL, sData)
|
||||
{
|
||||
var i;
|
||||
var resource = {
|
||||
aBytes: null,
|
||||
aSymbols: null,
|
||||
nLoad: null,
|
||||
nExec: null
|
||||
};
|
||||
if (sData.charAt(0) == "[" || sData.charAt(0) == "{") {
|
||||
try {
|
||||
var a, ib;
|
||||
var data = eval("(" + sData + ")");
|
||||
|
||||
resource.nLoad = data['load'];
|
||||
resource.nExec = data['exec'];
|
||||
|
||||
if (a = data['bytes']) {
|
||||
resource.aBytes = a;
|
||||
}
|
||||
else if (a = data['words']) {
|
||||
/*
|
||||
* Convert all words into bytes
|
||||
*/
|
||||
resource.aBytes = new Array(a.length * 2);
|
||||
for (i = 0, ib = 0; i < a.length; i++) {
|
||||
resource.aBytes[ib++] = a[i] & 0xff;
|
||||
resource.aBytes[ib++] = (a[i] >> 8) & 0xff;
|
||||
Component.assert(!(a[i] & ~0xffff));
|
||||
}
|
||||
}
|
||||
else if (a = data['data']) {
|
||||
/*
|
||||
* Convert all dwords (longs) into bytes
|
||||
*/
|
||||
resource.aBytes = new Array(a.length * 4);
|
||||
for (i = 0, ib = 0; i < a.length; i++) {
|
||||
resource.aBytes[ib++] = a[i] & 0xff;
|
||||
resource.aBytes[ib++] = (a[i] >> 8) & 0xff;
|
||||
resource.aBytes[ib++] = (a[i] >> 16) & 0xff;
|
||||
resource.aBytes[ib++] = (a[i] >> 24) & 0xff;
|
||||
}
|
||||
}
|
||||
else {
|
||||
resource.aBytes = data;
|
||||
}
|
||||
|
||||
resource.aSymbols = data['symbols'];
|
||||
|
||||
if (!resource.aBytes.length) {
|
||||
Component.error("Empty resource: " + sURL);
|
||||
resource = null;
|
||||
}
|
||||
else if (resource.aBytes.length == 1) {
|
||||
Component.error(resource.aBytes[0]);
|
||||
resource = null;
|
||||
}
|
||||
} catch (e) {
|
||||
Component.error("Resource data error: " + e.message);
|
||||
resource = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Parse the data manually; we'll assume it's in "simplified" hex form
|
||||
* (a series of hex byte-values separated by whitespace).
|
||||
*/
|
||||
var sHexData = sData.replace(/\n/gm, " ").replace(/ +$/, "");
|
||||
var asHexData = sHexData.split(" ");
|
||||
resource.aBytes = new Array(asHexData.length);
|
||||
for (i = 0; i < asHexData.length; i++) {
|
||||
resource.aBytes[i] = parseInt(asHexData[i], 16);
|
||||
Component.assert(!isNaN(resource.aBytes[i]));
|
||||
}
|
||||
}
|
||||
return resource;
|
||||
};
|
||||
|
||||
/**
|
||||
* sendReport(sApp, sVer, sURL, sUser, sType, sReport, sHostName)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -582,9 +582,9 @@
|
|||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="resetAddr">
|
||||
<xsl:variable name="addrReset">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@resetAddr"><xsl:value-of select="@resetAddr"/></xsl:when>
|
||||
<xsl:when test="@addrReset"><xsl:value-of select="@addrReset"/></xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
|
@ -612,7 +612,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class" select="'cpu'"/>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,resetAddr:<xsl:value-of select="$resetAddr"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,addrReset:<xsl:value-of select="$addrReset"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -933,16 +933,10 @@
|
|||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="writable">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@writable"><xsl:value-of select="@writable"/></xsl:when>
|
||||
<xsl:otherwise>false</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">rom</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>',writable:<xsl:value-of select="$writable"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>'</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -966,6 +960,24 @@
|
|||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="file">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@file"><xsl:value-of select="@file"/></xsl:when>
|
||||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="load">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@load"><xsl:value-of select="@load"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="exec">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@exec"><xsl:value-of select="@exec"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="test">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@test"><xsl:value-of select="@test"/></xsl:when>
|
||||
|
|
@ -975,7 +987,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">ram</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,file:'<xsl:value-of select="$file"/>',load:<xsl:value-of select="$load"/>,exec:<xsl:value-of select="$exec"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@
|
|||
}
|
||||
.pcjs-description, .pcjs-status {
|
||||
font-size: x-small;
|
||||
line-height: 2em;
|
||||
line-height: 2.8em;
|
||||
}
|
||||
.pcjs-key {
|
||||
border: 1px solid black;
|
||||
|
|
|
|||
|
|
@ -580,9 +580,9 @@
|
|||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="resetAddr">
|
||||
<xsl:variable name="addrReset">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@resetAddr"><xsl:value-of select="@resetAddr"/></xsl:when>
|
||||
<xsl:when test="@addrReset"><xsl:value-of select="@addrReset"/></xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
|
@ -610,7 +610,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class" select="'cpu'"/>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,resetAddr:<xsl:value-of select="$resetAddr"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,addrReset:<xsl:value-of select="$addrReset"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -931,16 +931,10 @@
|
|||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="writable">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@writable"><xsl:value-of select="@writable"/></xsl:when>
|
||||
<xsl:otherwise>false</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">rom</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>',writable:<xsl:value-of select="$writable"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>'</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -964,6 +958,24 @@
|
|||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="file">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@file"><xsl:value-of select="@file"/></xsl:when>
|
||||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="load">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@load"><xsl:value-of select="@load"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="exec">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@exec"><xsl:value-of select="@exec"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="test">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@test"><xsl:value-of select="@test"/></xsl:when>
|
||||
|
|
@ -973,7 +985,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">ram</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,file:'<xsl:value-of select="$file"/>',load:<xsl:value-of select="$load"/>,exec:<xsl:value-of select="$exec"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -85,7 +85,7 @@
|
|||
}
|
||||
.pcjs-description, .pcjs-status {
|
||||
font-size: x-small;
|
||||
line-height: 2em;
|
||||
line-height: 2.8em;
|
||||
}
|
||||
.pcjs-key {
|
||||
border: 1px solid black;
|
||||
|
|
|
|||
|
|
@ -580,9 +580,9 @@
|
|||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="resetAddr">
|
||||
<xsl:variable name="addrReset">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@resetAddr"><xsl:value-of select="@resetAddr"/></xsl:when>
|
||||
<xsl:when test="@addrReset"><xsl:value-of select="@addrReset"/></xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
|
@ -610,7 +610,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class" select="'cpu'"/>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,resetAddr:<xsl:value-of select="$resetAddr"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,addrReset:<xsl:value-of select="$addrReset"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -931,16 +931,10 @@
|
|||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="writable">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@writable"><xsl:value-of select="@writable"/></xsl:when>
|
||||
<xsl:otherwise>false</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">rom</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>',writable:<xsl:value-of select="$writable"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>'</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -964,6 +958,24 @@
|
|||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="file">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@file"><xsl:value-of select="@file"/></xsl:when>
|
||||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="load">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@load"><xsl:value-of select="@load"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="exec">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@exec"><xsl:value-of select="@exec"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="test">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@test"><xsl:value-of select="@test"/></xsl:when>
|
||||
|
|
@ -973,7 +985,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">ram</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,file:'<xsl:value-of select="$file"/>',load:<xsl:value-of select="$load"/>,exec:<xsl:value-of select="$exec"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@
|
|||
}
|
||||
.pcjs-description, .pcjs-status {
|
||||
font-size: x-small;
|
||||
line-height: 2em;
|
||||
line-height: 2.8em;
|
||||
}
|
||||
.pcjs-key {
|
||||
border: 1px solid black;
|
||||
|
|
|
|||
|
|
@ -580,9 +580,9 @@
|
|||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="resetAddr">
|
||||
<xsl:variable name="addrReset">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@resetAddr"><xsl:value-of select="@resetAddr"/></xsl:when>
|
||||
<xsl:when test="@addrReset"><xsl:value-of select="@addrReset"/></xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
|
@ -610,7 +610,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class" select="'cpu'"/>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,resetAddr:<xsl:value-of select="$resetAddr"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',stepping:'<xsl:value-of select="$stepping"/>',fpu:<xsl:value-of select="$fpu"/>,cycles:<xsl:value-of select="$cycles"/>,multiplier:<xsl:value-of select="$multiplier"/>,autoStart:<xsl:value-of select="$autoStart"/>,addrReset:<xsl:value-of select="$addrReset"/>,csStart:<xsl:value-of select="$csStart"/>,csInterval:<xsl:value-of select="$csInterval"/>,csStop:<xsl:value-of select="$csStop"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -931,16 +931,10 @@
|
|||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="writable">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@writable"><xsl:value-of select="@writable"/></xsl:when>
|
||||
<xsl:otherwise>false</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">rom</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>',writable:<xsl:value-of select="$writable"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,alias:<xsl:value-of select="$alias"/>,file:'<xsl:value-of select="$file"/>',notify:'<xsl:value-of select="$notify"/>'</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
@ -964,6 +958,24 @@
|
|||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="file">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@file"><xsl:value-of select="@file"/></xsl:when>
|
||||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="load">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@load"><xsl:value-of select="@load"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="exec">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@exec"><xsl:value-of select="@exec"/></xsl:when>
|
||||
<xsl:otherwise>null</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="test">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@test"><xsl:value-of select="@test"/></xsl:when>
|
||||
|
|
@ -973,7 +985,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">ram</xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
<xsl:with-param name="parms">,addr:<xsl:value-of select="$addr"/>,size:<xsl:value-of select="$size"/>,file:'<xsl:value-of select="$file"/>',load:<xsl:value-of select="$load"/>,exec:<xsl:value-of select="$exec"/>,test:<xsl:value-of select="$test"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue