rk86 2.0.12 → 2.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/rk86.js +475 -16
package/package.json
CHANGED
package/rk86.js
CHANGED
|
@@ -1588,9 +1588,420 @@ var init_catalog_data = __esm(() => {
|
|
|
1588
1588
|
];
|
|
1589
1589
|
});
|
|
1590
1590
|
|
|
1591
|
+
// node_modules/asm8080/dist/asm8.js
|
|
1592
|
+
var REG8 = {
|
|
1593
|
+
B: 0,
|
|
1594
|
+
C: 1,
|
|
1595
|
+
D: 2,
|
|
1596
|
+
E: 3,
|
|
1597
|
+
H: 4,
|
|
1598
|
+
L: 5,
|
|
1599
|
+
M: 6,
|
|
1600
|
+
A: 7
|
|
1601
|
+
};
|
|
1602
|
+
var REG_PAIR = {
|
|
1603
|
+
B: 0,
|
|
1604
|
+
D: 1,
|
|
1605
|
+
H: 2,
|
|
1606
|
+
SP: 3
|
|
1607
|
+
};
|
|
1608
|
+
var REG_PAIR_PUSH = {
|
|
1609
|
+
B: 0,
|
|
1610
|
+
D: 1,
|
|
1611
|
+
H: 2,
|
|
1612
|
+
PSW: 3
|
|
1613
|
+
};
|
|
1614
|
+
var IMPLIED = {
|
|
1615
|
+
NOP: 0,
|
|
1616
|
+
HLT: 118,
|
|
1617
|
+
RET: 201,
|
|
1618
|
+
XCHG: 235,
|
|
1619
|
+
EI: 251,
|
|
1620
|
+
DI: 243,
|
|
1621
|
+
CMA: 47,
|
|
1622
|
+
STC: 55,
|
|
1623
|
+
CMC: 63,
|
|
1624
|
+
DAA: 39,
|
|
1625
|
+
RLC: 7,
|
|
1626
|
+
RRC: 15,
|
|
1627
|
+
RAL: 23,
|
|
1628
|
+
RAR: 31,
|
|
1629
|
+
PCHL: 233,
|
|
1630
|
+
SPHL: 249,
|
|
1631
|
+
XTHL: 227,
|
|
1632
|
+
RNZ: 192,
|
|
1633
|
+
RZ: 200,
|
|
1634
|
+
RNC: 208,
|
|
1635
|
+
RC: 216,
|
|
1636
|
+
RPO: 224,
|
|
1637
|
+
RPE: 232,
|
|
1638
|
+
RP: 240,
|
|
1639
|
+
RM: 248
|
|
1640
|
+
};
|
|
1641
|
+
var ALU_REG = {
|
|
1642
|
+
ADD: 128,
|
|
1643
|
+
ADC: 136,
|
|
1644
|
+
SUB: 144,
|
|
1645
|
+
SBB: 152,
|
|
1646
|
+
ANA: 160,
|
|
1647
|
+
XRA: 168,
|
|
1648
|
+
ORA: 176,
|
|
1649
|
+
CMP: 184
|
|
1650
|
+
};
|
|
1651
|
+
var ALU_IMM = {
|
|
1652
|
+
ADI: 198,
|
|
1653
|
+
ACI: 206,
|
|
1654
|
+
SUI: 214,
|
|
1655
|
+
SBI: 222,
|
|
1656
|
+
ANI: 230,
|
|
1657
|
+
XRI: 238,
|
|
1658
|
+
ORI: 246,
|
|
1659
|
+
CPI: 254
|
|
1660
|
+
};
|
|
1661
|
+
var ADDR16 = {
|
|
1662
|
+
JMP: 195,
|
|
1663
|
+
JNZ: 194,
|
|
1664
|
+
JZ: 202,
|
|
1665
|
+
JNC: 210,
|
|
1666
|
+
JC: 218,
|
|
1667
|
+
JPO: 226,
|
|
1668
|
+
JPE: 234,
|
|
1669
|
+
JP: 242,
|
|
1670
|
+
JM: 250,
|
|
1671
|
+
CALL: 205,
|
|
1672
|
+
CNZ: 196,
|
|
1673
|
+
CZ: 204,
|
|
1674
|
+
CNC: 212,
|
|
1675
|
+
CC: 220,
|
|
1676
|
+
CPO: 228,
|
|
1677
|
+
CPE: 236,
|
|
1678
|
+
CP: 244,
|
|
1679
|
+
CM: 252,
|
|
1680
|
+
LDA: 58,
|
|
1681
|
+
STA: 50,
|
|
1682
|
+
LHLD: 42,
|
|
1683
|
+
SHLD: 34
|
|
1684
|
+
};
|
|
1685
|
+
function instrSize(m) {
|
|
1686
|
+
if (m in IMPLIED)
|
|
1687
|
+
return 1;
|
|
1688
|
+
if (m in ALU_REG)
|
|
1689
|
+
return 1;
|
|
1690
|
+
if (m === "MOV" || m === "INR" || m === "DCR")
|
|
1691
|
+
return 1;
|
|
1692
|
+
if (m === "PUSH" || m === "POP")
|
|
1693
|
+
return 1;
|
|
1694
|
+
if (m === "DAD" || m === "INX" || m === "DCX")
|
|
1695
|
+
return 1;
|
|
1696
|
+
if (m === "LDAX" || m === "STAX")
|
|
1697
|
+
return 1;
|
|
1698
|
+
if (m === "RST")
|
|
1699
|
+
return 1;
|
|
1700
|
+
if (m === "MVI")
|
|
1701
|
+
return 2;
|
|
1702
|
+
if (m in ALU_IMM)
|
|
1703
|
+
return 2;
|
|
1704
|
+
if (m === "IN" || m === "OUT")
|
|
1705
|
+
return 2;
|
|
1706
|
+
if (m === "LXI")
|
|
1707
|
+
return 3;
|
|
1708
|
+
if (m in ADDR16)
|
|
1709
|
+
return 3;
|
|
1710
|
+
throw new Error(`unknown mnemonic: ${m}`);
|
|
1711
|
+
}
|
|
1712
|
+
function stripComment(line) {
|
|
1713
|
+
let inQ = false;
|
|
1714
|
+
let qc = "";
|
|
1715
|
+
for (let i = 0;i < line.length; i++) {
|
|
1716
|
+
const c = line[i];
|
|
1717
|
+
if (inQ) {
|
|
1718
|
+
if (c === qc)
|
|
1719
|
+
inQ = false;
|
|
1720
|
+
} else if (c === '"' || c === "'") {
|
|
1721
|
+
inQ = true;
|
|
1722
|
+
qc = c;
|
|
1723
|
+
} else if (c === ";")
|
|
1724
|
+
return line.slice(0, i);
|
|
1725
|
+
}
|
|
1726
|
+
return line;
|
|
1727
|
+
}
|
|
1728
|
+
function splitOperands(s) {
|
|
1729
|
+
const r = [];
|
|
1730
|
+
let current = "";
|
|
1731
|
+
let inQ = false;
|
|
1732
|
+
let qc = "";
|
|
1733
|
+
for (const c of s) {
|
|
1734
|
+
if (inQ) {
|
|
1735
|
+
current += c;
|
|
1736
|
+
if (c === qc)
|
|
1737
|
+
inQ = false;
|
|
1738
|
+
} else if (c === '"' || c === "'") {
|
|
1739
|
+
inQ = true;
|
|
1740
|
+
qc = c;
|
|
1741
|
+
current += c;
|
|
1742
|
+
} else if (c === ",") {
|
|
1743
|
+
r.push(current.trim());
|
|
1744
|
+
current = "";
|
|
1745
|
+
} else
|
|
1746
|
+
current += c;
|
|
1747
|
+
}
|
|
1748
|
+
if (current.trim())
|
|
1749
|
+
r.push(current.trim());
|
|
1750
|
+
return r;
|
|
1751
|
+
}
|
|
1752
|
+
function parseLine(line) {
|
|
1753
|
+
let s = stripComment(line).trim();
|
|
1754
|
+
if (!s)
|
|
1755
|
+
return { operands: [] };
|
|
1756
|
+
let label;
|
|
1757
|
+
const ci = s.indexOf(":");
|
|
1758
|
+
if (ci > 0 && /^[A-Za-z_]\w*$/.test(s.slice(0, ci).trim())) {
|
|
1759
|
+
label = s.slice(0, ci).trim();
|
|
1760
|
+
s = s.slice(ci + 1).trim();
|
|
1761
|
+
}
|
|
1762
|
+
if (!s)
|
|
1763
|
+
return { label, operands: [] };
|
|
1764
|
+
const si = s.search(/\s/);
|
|
1765
|
+
const first = si < 0 ? s : s.slice(0, si);
|
|
1766
|
+
const rest = si < 0 ? "" : s.slice(si).trim();
|
|
1767
|
+
if (!label && rest) {
|
|
1768
|
+
const parts = rest.split(/\s+/);
|
|
1769
|
+
if (parts[0].toUpperCase() === "EQU") {
|
|
1770
|
+
return {
|
|
1771
|
+
label: first,
|
|
1772
|
+
mnemonic: "EQU",
|
|
1773
|
+
operands: [parts.slice(1).join(" ")],
|
|
1774
|
+
isEqu: true
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
return { label, mnemonic: first, operands: rest ? splitOperands(rest) : [] };
|
|
1779
|
+
}
|
|
1780
|
+
function evalAtom(s, symbols) {
|
|
1781
|
+
s = s.trim();
|
|
1782
|
+
if (s.length === 3 && s[0] === "'" && s[2] === "'")
|
|
1783
|
+
return s.charCodeAt(1);
|
|
1784
|
+
if (/^[0-9][0-9A-Fa-f]*[hH]$/.test(s))
|
|
1785
|
+
return parseInt(s.slice(0, -1), 16);
|
|
1786
|
+
if (/^[0-9]+$/.test(s))
|
|
1787
|
+
return parseInt(s, 10);
|
|
1788
|
+
const k = s.toUpperCase();
|
|
1789
|
+
if (symbols.has(k))
|
|
1790
|
+
return symbols.get(k);
|
|
1791
|
+
throw new Error(`unknown symbol: ${s}`);
|
|
1792
|
+
}
|
|
1793
|
+
function evalExpr(expr, symbols) {
|
|
1794
|
+
expr = expr.trim();
|
|
1795
|
+
const tokens = [];
|
|
1796
|
+
const ops = ["+"];
|
|
1797
|
+
let current = "";
|
|
1798
|
+
for (const c of expr) {
|
|
1799
|
+
if ((c === "+" || c === "-") && current.trim()) {
|
|
1800
|
+
tokens.push(current.trim());
|
|
1801
|
+
ops.push(c);
|
|
1802
|
+
current = "";
|
|
1803
|
+
} else {
|
|
1804
|
+
current += c;
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
if (current.trim())
|
|
1808
|
+
tokens.push(current.trim());
|
|
1809
|
+
let r = 0;
|
|
1810
|
+
for (let i = 0;i < tokens.length; i++) {
|
|
1811
|
+
const v = evalAtom(tokens[i], symbols);
|
|
1812
|
+
r = ops[i] === "+" ? r + v : r - v;
|
|
1813
|
+
}
|
|
1814
|
+
return r & 65535;
|
|
1815
|
+
}
|
|
1816
|
+
function encode(m, ops, symbols) {
|
|
1817
|
+
if (m in IMPLIED)
|
|
1818
|
+
return [IMPLIED[m]];
|
|
1819
|
+
if (m in ALU_REG)
|
|
1820
|
+
return [ALU_REG[m] | REG8[ops[0].toUpperCase()]];
|
|
1821
|
+
if (m in ALU_IMM)
|
|
1822
|
+
return [ALU_IMM[m], evalExpr(ops[0], symbols) & 255];
|
|
1823
|
+
if (m in ADDR16) {
|
|
1824
|
+
const v = evalExpr(ops[0], symbols);
|
|
1825
|
+
return [ADDR16[m], v & 255, v >> 8 & 255];
|
|
1826
|
+
}
|
|
1827
|
+
if (m === "MOV")
|
|
1828
|
+
return [64 | REG8[ops[0].toUpperCase()] << 3 | REG8[ops[1].toUpperCase()]];
|
|
1829
|
+
if (m === "MVI") {
|
|
1830
|
+
const v = evalExpr(ops[1], symbols);
|
|
1831
|
+
return [6 | REG8[ops[0].toUpperCase()] << 3, v & 255];
|
|
1832
|
+
}
|
|
1833
|
+
if (m === "INR")
|
|
1834
|
+
return [4 | REG8[ops[0].toUpperCase()] << 3];
|
|
1835
|
+
if (m === "DCR")
|
|
1836
|
+
return [5 | REG8[ops[0].toUpperCase()] << 3];
|
|
1837
|
+
if (m === "LXI") {
|
|
1838
|
+
const v = evalExpr(ops[1], symbols);
|
|
1839
|
+
return [1 | REG_PAIR[ops[0].toUpperCase()] << 4, v & 255, v >> 8 & 255];
|
|
1840
|
+
}
|
|
1841
|
+
if (m === "DAD")
|
|
1842
|
+
return [9 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1843
|
+
if (m === "INX")
|
|
1844
|
+
return [3 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1845
|
+
if (m === "DCX")
|
|
1846
|
+
return [11 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1847
|
+
if (m === "PUSH")
|
|
1848
|
+
return [197 | REG_PAIR_PUSH[ops[0].toUpperCase()] << 4];
|
|
1849
|
+
if (m === "POP")
|
|
1850
|
+
return [193 | REG_PAIR_PUSH[ops[0].toUpperCase()] << 4];
|
|
1851
|
+
if (m === "LDAX")
|
|
1852
|
+
return [10 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1853
|
+
if (m === "STAX")
|
|
1854
|
+
return [2 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1855
|
+
if (m === "IN")
|
|
1856
|
+
return [219, evalExpr(ops[0], symbols) & 255];
|
|
1857
|
+
if (m === "OUT")
|
|
1858
|
+
return [211, evalExpr(ops[0], symbols) & 255];
|
|
1859
|
+
if (m === "RST") {
|
|
1860
|
+
const n = evalExpr(ops[0], symbols);
|
|
1861
|
+
return [199 | n << 3];
|
|
1862
|
+
}
|
|
1863
|
+
throw new Error(`cannot encode: ${m} ${ops.join(", ")}`);
|
|
1864
|
+
}
|
|
1865
|
+
function dbBytes(operands, symbols) {
|
|
1866
|
+
const out = [];
|
|
1867
|
+
for (const op of operands) {
|
|
1868
|
+
if (op.startsWith('"') && op.endsWith('"') || op.startsWith("'") && op.endsWith("'")) {
|
|
1869
|
+
for (const ch of op.slice(1, -1))
|
|
1870
|
+
out.push(ch.charCodeAt(0));
|
|
1871
|
+
} else {
|
|
1872
|
+
out.push(evalExpr(op, symbols) & 255);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
return out;
|
|
1876
|
+
}
|
|
1877
|
+
function dwBytes(operands, symbols) {
|
|
1878
|
+
const out = [];
|
|
1879
|
+
for (const op of operands) {
|
|
1880
|
+
const v = evalExpr(op, symbols) & 65535;
|
|
1881
|
+
out.push(v & 255, v >> 8 & 255);
|
|
1882
|
+
}
|
|
1883
|
+
return out;
|
|
1884
|
+
}
|
|
1885
|
+
function countDb(operands) {
|
|
1886
|
+
let n = 0;
|
|
1887
|
+
for (const op of operands) {
|
|
1888
|
+
if (op.startsWith('"') && op.endsWith('"') || op.startsWith("'") && op.endsWith("'"))
|
|
1889
|
+
n += op.length - 2;
|
|
1890
|
+
else
|
|
1891
|
+
n++;
|
|
1892
|
+
}
|
|
1893
|
+
return n;
|
|
1894
|
+
}
|
|
1895
|
+
function asm(source) {
|
|
1896
|
+
const lines = source.split(`
|
|
1897
|
+
`);
|
|
1898
|
+
const symbols = new Map;
|
|
1899
|
+
let pc = 0;
|
|
1900
|
+
for (const line of lines) {
|
|
1901
|
+
const parts = parseLine(line);
|
|
1902
|
+
if (parts.label) {
|
|
1903
|
+
if (parts.isEqu) {
|
|
1904
|
+
symbols.set(parts.label.toUpperCase(), evalExpr(parts.operands[0], symbols));
|
|
1905
|
+
continue;
|
|
1906
|
+
}
|
|
1907
|
+
symbols.set(parts.label.toUpperCase(), pc);
|
|
1908
|
+
}
|
|
1909
|
+
if (!parts.mnemonic)
|
|
1910
|
+
continue;
|
|
1911
|
+
const m = parts.mnemonic.toUpperCase();
|
|
1912
|
+
if (m === "EQU")
|
|
1913
|
+
continue;
|
|
1914
|
+
if (m === "ORG") {
|
|
1915
|
+
pc = evalExpr(parts.operands[0], symbols);
|
|
1916
|
+
continue;
|
|
1917
|
+
}
|
|
1918
|
+
if (m === "SECTION")
|
|
1919
|
+
continue;
|
|
1920
|
+
if (m === "END")
|
|
1921
|
+
break;
|
|
1922
|
+
if (m === "DB") {
|
|
1923
|
+
pc += countDb(parts.operands);
|
|
1924
|
+
continue;
|
|
1925
|
+
}
|
|
1926
|
+
if (m === "DW") {
|
|
1927
|
+
pc += parts.operands.length * 2;
|
|
1928
|
+
continue;
|
|
1929
|
+
}
|
|
1930
|
+
pc += instrSize(m);
|
|
1931
|
+
}
|
|
1932
|
+
const sections = [];
|
|
1933
|
+
let current = null;
|
|
1934
|
+
const sectionNames = new Set;
|
|
1935
|
+
for (const line of lines) {
|
|
1936
|
+
const parts = parseLine(line);
|
|
1937
|
+
if (parts.isEqu || !parts.mnemonic)
|
|
1938
|
+
continue;
|
|
1939
|
+
const m = parts.mnemonic.toUpperCase();
|
|
1940
|
+
if (m === "EQU")
|
|
1941
|
+
continue;
|
|
1942
|
+
if (m === "ORG") {
|
|
1943
|
+
if (current && current.data.length) {
|
|
1944
|
+
current.end = current.start + current.data.length - 1;
|
|
1945
|
+
sections.push(current);
|
|
1946
|
+
}
|
|
1947
|
+
const addr = evalExpr(parts.operands[0], symbols);
|
|
1948
|
+
current = { start: addr, end: addr, data: [] };
|
|
1949
|
+
continue;
|
|
1950
|
+
}
|
|
1951
|
+
if (m === "SECTION") {
|
|
1952
|
+
if (!current)
|
|
1953
|
+
throw new Error("SECTION before ORG");
|
|
1954
|
+
const name = parts.operands[0];
|
|
1955
|
+
if (!name)
|
|
1956
|
+
throw new Error("SECTION requires a name");
|
|
1957
|
+
if (sectionNames.has(name.toUpperCase()))
|
|
1958
|
+
throw new Error(`duplicate section name: ${name}`);
|
|
1959
|
+
sectionNames.add(name.toUpperCase());
|
|
1960
|
+
current.name = name;
|
|
1961
|
+
continue;
|
|
1962
|
+
}
|
|
1963
|
+
if (m === "END")
|
|
1964
|
+
break;
|
|
1965
|
+
if (!current)
|
|
1966
|
+
throw new Error("code before ORG");
|
|
1967
|
+
const bytes = m === "DB" ? dbBytes(parts.operands, symbols) : m === "DW" ? dwBytes(parts.operands, symbols) : encode(m, parts.operands, symbols);
|
|
1968
|
+
current.data.push(...bytes);
|
|
1969
|
+
}
|
|
1970
|
+
if (current && current.data.length) {
|
|
1971
|
+
current.end = current.start + current.data.length - 1;
|
|
1972
|
+
sections.push(current);
|
|
1973
|
+
}
|
|
1974
|
+
return sections;
|
|
1975
|
+
}
|
|
1976
|
+
if (false) {}
|
|
1977
|
+
|
|
1591
1978
|
// src/lib/terminal/rk86_terminal.ts
|
|
1592
1979
|
import { existsSync } from "fs";
|
|
1593
1980
|
import { readFile } from "fs/promises";
|
|
1981
|
+
// packages/rk86/package.json
|
|
1982
|
+
var package_default = {
|
|
1983
|
+
name: "rk86",
|
|
1984
|
+
version: "2.0.14",
|
|
1985
|
+
description: "\u042D\u043C\u0443\u043B\u044F\u0442\u043E\u0440 \u0420\u0430\u0434\u0438\u043E-86\u0420\u041A (Intel 8080) \u0434\u043B\u044F \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0430",
|
|
1986
|
+
bin: {
|
|
1987
|
+
rk86: "rk86.js"
|
|
1988
|
+
},
|
|
1989
|
+
type: "module",
|
|
1990
|
+
keywords: [
|
|
1991
|
+
"rk86",
|
|
1992
|
+
"radio-86rk",
|
|
1993
|
+
"emulator",
|
|
1994
|
+
"intel-8080",
|
|
1995
|
+
"i8080",
|
|
1996
|
+
"retro"
|
|
1997
|
+
],
|
|
1998
|
+
author: "Alexander Demin",
|
|
1999
|
+
license: "MIT",
|
|
2000
|
+
repository: {
|
|
2001
|
+
type: "git",
|
|
2002
|
+
url: "https://github.com/begoon/rk86-js-web"
|
|
2003
|
+
}
|
|
2004
|
+
};
|
|
1594
2005
|
|
|
1595
2006
|
// src/lib/core/hex.ts
|
|
1596
2007
|
function hex(v, prefix) {
|
|
@@ -3007,7 +3418,7 @@ class Runner {
|
|
|
3007
3418
|
}
|
|
3008
3419
|
}
|
|
3009
3420
|
execute(options = {}) {
|
|
3010
|
-
const { terminate_address, on_terminate, exit_on_halt } = options;
|
|
3421
|
+
const { terminate_address, on_terminate, exit_on_halt, armed } = options;
|
|
3011
3422
|
clearTimeout(this.execute_timer);
|
|
3012
3423
|
if (!this.paused) {
|
|
3013
3424
|
let batch_ticks = 0;
|
|
@@ -3035,6 +3446,8 @@ class Runner {
|
|
|
3035
3446
|
this.machine.ui.on_visualizer_hit(this.machine.memory.read_raw(this.machine.cpu.pc));
|
|
3036
3447
|
}
|
|
3037
3448
|
batch_instructions += 1;
|
|
3449
|
+
if (armed?.value === false)
|
|
3450
|
+
continue;
|
|
3038
3451
|
if (terminate_address !== undefined && this.machine.cpu.pc === terminate_address) {
|
|
3039
3452
|
on_terminate?.();
|
|
3040
3453
|
return;
|
|
@@ -3624,10 +4037,12 @@ function printHelp() {
|
|
|
3624
4037
|
\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435: bunx rk86 [\u043E\u043F\u0446\u0438\u0438] [\u0444\u0430\u0439\u043B]
|
|
3625
4038
|
|
|
3626
4039
|
\u041E\u043F\u0446\u0438\u0438:
|
|
4040
|
+
-v \u0432\u0435\u0440\u0441\u0438\u044F
|
|
3627
4041
|
-h \u0441\u043F\u0440\u0430\u0432\u043A\u0430
|
|
3628
4042
|
-l \u0441\u043F\u0438\u0441\u043E\u043A \u0444\u0430\u0439\u043B\u043E\u0432 \u0438\u0437 \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0430
|
|
3629
4043
|
-m <\u0444\u0430\u0439\u043B> \u043C\u043E\u043D\u0438\u0442\u043E\u0440 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0439 mon32.bin)
|
|
3630
4044
|
-p \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u0431\u0435\u0437 \u0437\u0430\u043F\u0443\u0441\u043A\u0430
|
|
4045
|
+
-g <\u0430\u0434\u0440\u0435\u0441> \u0430\u0434\u0440\u0435\u0441 \u0437\u0430\u043F\u0443\u0441\u043A\u0430 (\u043D\u0435\u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C \u0441 -p)
|
|
3631
4046
|
--exit-halt \u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u0438 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0438 HLT
|
|
3632
4047
|
--exit-address [\u0430\u0434\u0440\u0435\u0441] \u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u0438 \u043F\u0435\u0440\u0435\u0445\u043E\u0434\u0435 \u043D\u0430 \u0430\u0434\u0440\u0435\u0441 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: 0xFFFE)
|
|
3633
4048
|
|
|
@@ -3639,6 +4054,8 @@ function printHelp() {
|
|
|
3639
4054
|
bunx rk86 --exit-halt prog.bin \u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u0438 HLT
|
|
3640
4055
|
bunx rk86 --exit-address prog.bin \u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u0438 JMP FFFEh
|
|
3641
4056
|
bunx rk86 -l \u0441\u043F\u0438\u0441\u043E\u043A \u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0445 \u0444\u0430\u0439\u043B\u043E\u0432
|
|
4057
|
+
bunx rk86 --exit-halt prog.asm \u0441\u043E\u0431\u0440\u0430\u0442\u044C \u0438 \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C .asm \u0444\u0430\u0439\u043B
|
|
4058
|
+
bunx rk86 -g 0x100 prog.bin \u0437\u0430\u043F\u0443\u0441\u043A \u0441 \u0430\u0434\u0440\u0435\u0441\u0430 100h
|
|
3642
4059
|
|
|
3643
4060
|
\u0423\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435:
|
|
3644
4061
|
Ctrl+C \u0432\u044B\u0445\u043E\u0434`);
|
|
@@ -3676,6 +4093,10 @@ function arg(args, name, defaultValue, matcher, convertor) {
|
|
|
3676
4093
|
}
|
|
3677
4094
|
async function main() {
|
|
3678
4095
|
const args = process.argv.slice(2);
|
|
4096
|
+
if (flag(args, "-v") || flag(args, "--version")) {
|
|
4097
|
+
console.log(`rk86 ${package_default.version}`);
|
|
4098
|
+
process.exit(0);
|
|
4099
|
+
}
|
|
3679
4100
|
if (flag(args, "-h") || flag(args, "--help")) {
|
|
3680
4101
|
printHelp();
|
|
3681
4102
|
process.exit(0);
|
|
@@ -3685,6 +4106,11 @@ async function main() {
|
|
|
3685
4106
|
process.exit(0);
|
|
3686
4107
|
}
|
|
3687
4108
|
const loadOnly = flag(args, "-p");
|
|
4109
|
+
const goAddr = arg(args, "-g", undefined, /^0x[0-9a-fA-F]+$/i, (v) => parseInt(v, 16));
|
|
4110
|
+
if (loadOnly && goAddr !== undefined) {
|
|
4111
|
+
console.error("\u043E\u0448\u0438\u0431\u043A\u0430: -p \u0438 -g \u043D\u0435\u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C\u044B");
|
|
4112
|
+
process.exit(1);
|
|
4113
|
+
}
|
|
3688
4114
|
const exitOnHalt = flag(args, "--exit-halt");
|
|
3689
4115
|
const exitAddrValue = arg(args, "--exit-address", "0xFFFE", /^0x[0-9a-fA-F]+$/i, (v) => parseInt(v, 16));
|
|
3690
4116
|
const exitAddr = exitAddrValue !== undefined;
|
|
@@ -3711,18 +4137,44 @@ async function main() {
|
|
|
3711
4137
|
let entryPoint;
|
|
3712
4138
|
let loadInfo = "";
|
|
3713
4139
|
if (programFile) {
|
|
3714
|
-
const
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
4140
|
+
const ext = file_ext(programFile).toLowerCase();
|
|
4141
|
+
if (ext === "asm") {
|
|
4142
|
+
const source = await readFile(programFile, "utf-8");
|
|
4143
|
+
const sections = asm(source);
|
|
4144
|
+
if (sections.length === 0) {
|
|
4145
|
+
console.error("\u043E\u0448\u0438\u0431\u043A\u0430: \u0430\u0441\u0441\u0435\u043C\u0431\u043B\u0435\u0440 \u043D\u0435 \u0432\u0435\u0440\u043D\u0443\u043B \u0441\u0435\u043A\u0446\u0438\u0439");
|
|
4146
|
+
process.exit(1);
|
|
4147
|
+
}
|
|
4148
|
+
const lines = [];
|
|
4149
|
+
for (const section of sections) {
|
|
4150
|
+
const data = section.data;
|
|
4151
|
+
for (let i = 0;i < data.length; i++) {
|
|
4152
|
+
machine.memory.write(section.start + i, data[i]);
|
|
4153
|
+
}
|
|
4154
|
+
const name = section.name ? ` [${section.name}]` : "";
|
|
4155
|
+
lines.push(`${hex16(section.start)}-${hex16(section.end)}${name} (${data.length} \u0431\u0430\u0439\u0442)`);
|
|
4156
|
+
}
|
|
4157
|
+
entryPoint = goAddr ?? sections[0].start;
|
|
4158
|
+
loadInfo = `\u0441\u043E\u0431\u0440\u0430\u043D: ${programFile}
|
|
4159
|
+
` + lines.join(`
|
|
4160
|
+
`) + `
|
|
4161
|
+
\u0437\u0430\u043F\u0443\u0441\u043A: G${hex16(entryPoint)}`;
|
|
3720
4162
|
} else {
|
|
3721
|
-
const
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
4163
|
+
const content = await fetchFile(programFile);
|
|
4164
|
+
const { ok, json } = parse(content);
|
|
4165
|
+
if (ok) {
|
|
4166
|
+
rk86_snapshot_restore(json, machine);
|
|
4167
|
+
entryPoint = parseInt(json.cpu.pc);
|
|
4168
|
+
loadInfo = `\u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D: ${programFile} (PC=${hex16(entryPoint)})`;
|
|
4169
|
+
} else {
|
|
4170
|
+
const file = parse_rk86_binary(programFile, content);
|
|
4171
|
+
machine.memory.load_file(file);
|
|
4172
|
+
entryPoint = file.entry;
|
|
4173
|
+
loadInfo = `\u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D: ${programFile} (${hex16(file.start)}-${hex16(file.end)}, G${hex16(file.entry)})`;
|
|
4174
|
+
}
|
|
3725
4175
|
}
|
|
4176
|
+
if (goAddr !== undefined)
|
|
4177
|
+
entryPoint = goAddr;
|
|
3726
4178
|
}
|
|
3727
4179
|
process.stdout.write("\x1B[?25l");
|
|
3728
4180
|
process.stdout.write("\x1B[2J");
|
|
@@ -3732,17 +4184,24 @@ async function main() {
|
|
|
3732
4184
|
machine.screen.start(renderer);
|
|
3733
4185
|
const onTerminate = exitOnHalt || exitAddr ? () => {
|
|
3734
4186
|
renderer.update();
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
4187
|
+
setTimeout(() => {
|
|
4188
|
+
console.log();
|
|
4189
|
+
console.log("\u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0430 \u0440\u0430\u0431\u043E\u0442\u0443 \u043D\u0430", hex16(machine.cpu.pc));
|
|
4190
|
+
process.exit(0);
|
|
4191
|
+
}, 1000);
|
|
3738
4192
|
} : undefined;
|
|
4193
|
+
const armed = { value: entryPoint === undefined };
|
|
3739
4194
|
machine.runner.execute({
|
|
3740
4195
|
terminate_address: exitAddr ? exitAddrValue : undefined,
|
|
3741
4196
|
exit_on_halt: exitOnHalt,
|
|
3742
|
-
on_terminate: onTerminate
|
|
4197
|
+
on_terminate: onTerminate,
|
|
4198
|
+
armed
|
|
3743
4199
|
});
|
|
3744
4200
|
if (entryPoint !== undefined && !loadOnly) {
|
|
3745
|
-
setTimeout(() =>
|
|
4201
|
+
setTimeout(() => {
|
|
4202
|
+
machine.cpu.jump(entryPoint);
|
|
4203
|
+
armed.value = true;
|
|
4204
|
+
}, 500);
|
|
3746
4205
|
}
|
|
3747
4206
|
process.on("exit", () => {
|
|
3748
4207
|
process.stdout.write("\x1B[?25h");
|