8086emu 0.1.0
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/LICENSE +21 -0
- package/README.md +177 -0
- package/multi_cpu_emu.d.ts +317 -0
- package/multi_cpu_emu.js +855 -0
- package/multi_cpu_emu_bg.wasm +0 -0
- package/package.json +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Danish
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# multi-cpu-emu
|
|
2
|
+
|
|
3
|
+
A single Rust crate that emulates six classic microprocessors:
|
|
4
|
+
|
|
5
|
+
- **Intel 8086** — 16-bit, segmented, 1 MiB address space; includes an 8259 PIC
|
|
6
|
+
and 8253 PIT so timer interrupts (IRQ0 → `INT 8`) fire end-to-end
|
|
7
|
+
- **Intel 8085** — 8-bit, 64 KiB, accumulator-centric
|
|
8
|
+
- **Intel 8051 (MCS-51)** — 8-bit, SFRs, bit-addressable RAM, timers
|
|
9
|
+
- **MOS 6502** — 8-bit, decimal mode, NMI/IRQ/BRK vectoring
|
|
10
|
+
- **Zilog Z80** — 8-bit, IM 0/1/2, NMI/INT, full 8080 + Z80 ops
|
|
11
|
+
- **RISC-V rv32i (+M)** — 32-bit, base integer ISA plus the M-extension
|
|
12
|
+
|
|
13
|
+
Each core has a matching assembler, and the whole crate compiles to **one WASM
|
|
14
|
+
module** (via `wasm-bindgen`, feature `wasm`) plus a native `rlib`/`cdylib`.
|
|
15
|
+
A full dependency-free web IDE for students lives in `docs/` and deploys to
|
|
16
|
+
GitHub Pages with zero config.
|
|
17
|
+
|
|
18
|
+
Design was inspired by https://github.com/abuXsarkar/modern8086 (MIT) — used
|
|
19
|
+
only as an architecture/scope reference; all code here is written from scratch.
|
|
20
|
+
See `AGENTS.md` for the full architecture and per-ISA coverage.
|
|
21
|
+
|
|
22
|
+
## Build & test
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cargo test # ~86 integration tests across all three ISAs
|
|
26
|
+
cargo clippy --all-targets # should be warning-free
|
|
27
|
+
|
|
28
|
+
# wasm build (needs wasm-pack)
|
|
29
|
+
wasm-pack build --target web --out-dir docs/pkg --release --features wasm
|
|
30
|
+
|
|
31
|
+
# self-contained WASM smoke test (exercises all three ISAs + new features)
|
|
32
|
+
node tools/wasm-smoke.mjs
|
|
33
|
+
|
|
34
|
+
# serve the web demo
|
|
35
|
+
python3 -m http.server -d docs 8000 # then open http://localhost:8000
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Web IDE / GitHub Pages
|
|
39
|
+
|
|
40
|
+
The demo in `docs/` is a student-oriented IDE: ISA selector (8086/8085/8051),
|
|
41
|
+
sample programs, line-numbered editor with assemble-error highlighting, step /
|
|
42
|
+
step-over / run / stop / reset, **click-in-gutter breakpoints** with Step-Back
|
|
43
|
+
time-travel, live register + flag panels, a memory dump with the PC highlighted,
|
|
44
|
+
a **live memory-map** (showing loaded ROM / external SRAM / 8051 EA state), an
|
|
45
|
+
**8051 SFR readout** (click a register to edit it live), and a program-output
|
|
46
|
+
console.
|
|
47
|
+
|
|
48
|
+
Deployment is handled by the workflow in `.github/workflows/pages.yml`: on every
|
|
49
|
+
push to `main` it builds the wasm pkg, runs the native tests, and deploys
|
|
50
|
+
`docs/` to GitHub Pages.
|
|
51
|
+
|
|
52
|
+
One-time setup in GitHub: **Settings → Pages → Source: "GitHub Actions"** (the
|
|
53
|
+
first workflow run may enable the site automatically). The site then appears at
|
|
54
|
+
`https://<user>.github.io/8086emu/`.
|
|
55
|
+
|
|
56
|
+
Alternative (no workflow): **Settings → Pages → Deploy from a branch → `main`,
|
|
57
|
+
folder `/docs`** — works because all asset paths in `docs/` are relative and the
|
|
58
|
+
prebuilt `docs/pkg/` is committed. After any Rust change, rebuild and commit it:
|
|
59
|
+
`wasm-pack build --target web --out-dir docs/pkg --release --features wasm`.
|
|
60
|
+
Root `index.html` redirects to `docs/` for local convenience.
|
|
61
|
+
|
|
62
|
+
## Quick start
|
|
63
|
+
|
|
64
|
+
### Run headless from a shell (CLI)
|
|
65
|
+
|
|
66
|
+
The CLI lives in `examples/run.rs`; it assembles source and runs the program,
|
|
67
|
+
printing registers, flags, and output.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# build once
|
|
71
|
+
cargo build --release --example run
|
|
72
|
+
|
|
73
|
+
# 8086 hello world
|
|
74
|
+
cargo run --example run -- examples/hello.asm
|
|
75
|
+
|
|
76
|
+
# other ISAs, with a step cap
|
|
77
|
+
cargo run --example run -- --isa 8051 --max-steps 1000 examples/hello51.asm
|
|
78
|
+
|
|
79
|
+
# trace every instruction + peripheral (port) write
|
|
80
|
+
cargo run --example run -- --isa 8085 --verbose examples/traffic.asm
|
|
81
|
+
|
|
82
|
+
# automate checks (exit 0 = pass, 1 = fail, 2 = usage error)
|
|
83
|
+
cargo run --example run -- --grade tests/spec.txt examples/prog.asm
|
|
84
|
+
|
|
85
|
+
# measure emulation throughput (native numbers)
|
|
86
|
+
cargo run --example run -- --bench # default 10M steps
|
|
87
|
+
cargo run --example run -- --bench 2000000 --isa rv32
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Use it in the browser (WASM IDE)
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# serve the demo (from repo root)
|
|
94
|
+
python3 -m http.server -d docs 8000
|
|
95
|
+
# open http://localhost:8000 (root redirects to /docs/)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
In the IDE: pick an ISA → write code → `F7` assemble → `F5` run / `F8` step →
|
|
99
|
+
set breakpoints in the gutter → inspect registers, memory, and device panels.
|
|
100
|
+
|
|
101
|
+
**Browser throughput check** (open DevTools console on the IDE page; the
|
|
102
|
+
emulator is exposed as `window.emu`):
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
let t = performance.now();
|
|
106
|
+
let s = emu.run(1_000_000); // steps executed
|
|
107
|
+
let ms = performance.now() - t;
|
|
108
|
+
console.log(s, 'steps in', ms.toFixed(1), 'ms =>', Math.round(s / (ms/1000)), 'steps/sec');
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Both the CLI and the browser run the **same Rust core** (native vs WASM), so
|
|
112
|
+
bulk `run()` throughput is comparable; only per-instruction single-stepping
|
|
113
|
+
from JS is slower because of the JS↔WASM call boundary.
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
## Examples
|
|
117
|
+
|
|
118
|
+
| File | ISA | Shows |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| `examples/hello.asm` | 8086 | `INT 21h` string output |
|
|
121
|
+
| `examples/hello85.asm` | 8085 | `OUT 01h` printing |
|
|
122
|
+
| `examples/hello51.asm` | 8051 | `SBUF` serial output |
|
|
123
|
+
| `examples/8155.asm` | 8085 | 8155 external RAM/I/O |
|
|
124
|
+
| `examples/timer51.asm` | 8051 | timer + interrupt |
|
|
125
|
+
| `examples/ser.rs` | 8051 | native serial-RX injection |
|
|
126
|
+
| `examples/bios.asm` | 8086 | BIOS image that boots from the reset vector `FFFF:FFF0` |
|
|
127
|
+
|
|
128
|
+
## Layout
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
├── src/
|
|
132
|
+
│ ├── lib.rs # Emulator facade over the three cores
|
|
133
|
+
│ ├── cpu.rs # Cpu trait, Mem, Output, FlagSet, Reg, RunResult
|
|
134
|
+
│ ├── i8086.rs # 8086 CPU core (segmented, INT 21h/10h subset)
|
|
135
|
+
│ ├── i8085.rs # 8085 CPU core (full 8-bit ISA)
|
|
136
|
+
│ ├── mcs51.rs # 8051 CPU core (SFRs, bit ops, timers)
|
|
137
|
+
│ ├── asm/ # tokenizer + per-ISA assemblers
|
|
138
|
+
│ └── wasm.rs # wasm-bindgen surface (feature = "wasm")
|
|
139
|
+
├── examples/run.rs # native CLI runner
|
|
140
|
+
├── tests/emulation.rs # integration tests
|
|
141
|
+
├── docs/ # GitHub Pages IDE (index.html + app.js + style.css + pkg/)
|
|
142
|
+
└── index.html # redirects to docs/
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## WASM API
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
const emu = new Emulator("8086"); // "8086" | "8085" | "8051"
|
|
149
|
+
const code = emu.assemble(src); // throws on error
|
|
150
|
+
emu.load(code, 0x100); // write code + set PC
|
|
151
|
+
emu.set_pc(0x100); // (re)set the program counter
|
|
152
|
+
emu.run(1_000_000); // steps executed
|
|
153
|
+
emu.step(); emu.run_to(targetPc, 1_000_000); // step / run-to-line (Step-Over)
|
|
154
|
+
emu.pc(); emu.regs(); emu.flags(); // "AX=1234" / "ZF"
|
|
155
|
+
emu.mem(0, 64); // raw bytes
|
|
156
|
+
emu.out(); // program output (drains)
|
|
157
|
+
emu.halted(); emu.reset();
|
|
158
|
+
emu.snapshot(); emu.restore(bytes); // deterministic time-travel
|
|
159
|
+
|
|
160
|
+
// External memory (write-protected ROM / external SRAM / 8051 EA):
|
|
161
|
+
emu.set_rom_region(0xF0000, 0x10000); // mark ROM range
|
|
162
|
+
emu.load_rom(bytes, 0xF0000); // place a firmware image
|
|
163
|
+
emu.set_ea(false); // 8051: fetch code from XDATA
|
|
164
|
+
emu.set_sram(0x9000, 0x2000); // 8085: (re)map external SRAM
|
|
165
|
+
emu.rom_region(); emu.sram_region(); // live memory-map info
|
|
166
|
+
emu.ea_active(); emu.ext_code_region();
|
|
167
|
+
|
|
168
|
+
// 8051 peripheral registers:
|
|
169
|
+
emu.sfr(0xD0); emu.set_sfr(0xD0, 0x00); // read/write an SFR
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Program output conventions
|
|
173
|
+
|
|
174
|
+
- **8086** — `INT 21h` (AH=02, 06, 09, 4Ch) and `INT 10h` (AH=0Eh) write to the
|
|
175
|
+
output buffer.
|
|
176
|
+
- **8085** — `OUT 01h` prints the char in A.
|
|
177
|
+
- **8051** — writing to `SBUF` prints the char.
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
export class Emulator {
|
|
5
|
+
free(): void;
|
|
6
|
+
[Symbol.dispose](): void;
|
|
7
|
+
/**
|
|
8
|
+
* Assemble source for the current ISA; returns machine code bytes.
|
|
9
|
+
*/
|
|
10
|
+
assemble(source: string): Uint8Array;
|
|
11
|
+
/**
|
|
12
|
+
* Assemble and return per-line machine code as "ADDR BYTES" strings
|
|
13
|
+
* (one per source line, empty for lines that emit nothing).
|
|
14
|
+
*/
|
|
15
|
+
assemble_info(source: string): string[];
|
|
16
|
+
/**
|
|
17
|
+
* 8086 text cursor as [col, row]; [0,0] otherwise.
|
|
18
|
+
*/
|
|
19
|
+
cursor(): Uint8Array;
|
|
20
|
+
/**
|
|
21
|
+
* Total clock cycles executed (machine cycles / T-states). Drives the
|
|
22
|
+
* cycle-accurate timers (8086 PIT, 8051 timers, 8085 8155 timer).
|
|
23
|
+
*/
|
|
24
|
+
cycles(): bigint;
|
|
25
|
+
/**
|
|
26
|
+
* Disassemble `count` instructions starting at `addr`. Each returned line
|
|
27
|
+
* is "ADDR BYTES text" (use `Disasm::line`). Other ISAs return [].
|
|
28
|
+
*/
|
|
29
|
+
disasm(addr: number, count: number): string[];
|
|
30
|
+
/**
|
|
31
|
+
* 8051 EA pin state (true = internal code, false = external via XDATA).
|
|
32
|
+
*/
|
|
33
|
+
ea_active(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* 8051 external-code (XDATA) region (base, len) when EA is low, else null.
|
|
36
|
+
*/
|
|
37
|
+
ext_code_region(): Uint32Array | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Active flag names as short strings (e.g. "ZF", "CY").
|
|
40
|
+
*/
|
|
41
|
+
flags(): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Read a file back from the 8086 DOS virtual filesystem (empty if absent).
|
|
44
|
+
*/
|
|
45
|
+
fs_get(name: string): Uint8Array | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Preload a file into the 8086 DOS virtual filesystem.
|
|
48
|
+
*/
|
|
49
|
+
fs_put(name: string, data: Uint8Array): void;
|
|
50
|
+
/**
|
|
51
|
+
* 8086 graphics framebuffer, or None when in a text mode / non-8086 ISA.
|
|
52
|
+
*/
|
|
53
|
+
gfx(): GfxInfo | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* True once the CPU has executed HLT (or otherwise stopped).
|
|
56
|
+
*/
|
|
57
|
+
halted(): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Hardware interrupt: 8085 = "TRAP" | "RST75" | "RST65" | "RST55" |
|
|
60
|
+
* "INTR" (data = vector); 8051 = "INT0" | "INT1". Throws on unknown kind.
|
|
61
|
+
*/
|
|
62
|
+
interrupt(kind: string, data: number): void;
|
|
63
|
+
/**
|
|
64
|
+
* Load raw machine code at `origin` and set PC there.
|
|
65
|
+
*/
|
|
66
|
+
load(code: Uint8Array, origin: number): void;
|
|
67
|
+
/**
|
|
68
|
+
* Load a ROM image and mark its range read-only. 8051 routes to external
|
|
69
|
+
* code (XDATA) when EA is low.
|
|
70
|
+
*/
|
|
71
|
+
load_rom(data: Uint8Array, addr: number): void;
|
|
72
|
+
/**
|
|
73
|
+
* Linear memory read of `len` bytes starting at `addr`.
|
|
74
|
+
*/
|
|
75
|
+
mem(addr: number, len: number): Uint8Array;
|
|
76
|
+
/**
|
|
77
|
+
* Write bytes into memory (IDE memory poking).
|
|
78
|
+
*/
|
|
79
|
+
mem_write(addr: number, data: Uint8Array): void;
|
|
80
|
+
/**
|
|
81
|
+
* Create an emulator for one of: "8086", "8085", "8051", "6502", "Z80", "rv32".
|
|
82
|
+
* Throws if the ISA name is unknown.
|
|
83
|
+
*/
|
|
84
|
+
constructor(isa: string);
|
|
85
|
+
/**
|
|
86
|
+
* Drain the program output buffer.
|
|
87
|
+
*/
|
|
88
|
+
out(): string;
|
|
89
|
+
/**
|
|
90
|
+
* Current program counter (instruction pointer).
|
|
91
|
+
*/
|
|
92
|
+
pc(): number;
|
|
93
|
+
/**
|
|
94
|
+
* Current reload/count of an 8086 PIT channel (0..2). Other ISAs: 0.
|
|
95
|
+
*/
|
|
96
|
+
pit_count(n: number): number;
|
|
97
|
+
/**
|
|
98
|
+
* Queue a key for the 8086's INT 21h keyboard reads (AH=01/06/07/08/0C).
|
|
99
|
+
*/
|
|
100
|
+
port_read(port: number): number;
|
|
101
|
+
/**
|
|
102
|
+
* Write an I/O port byte (8085/8086: port space 0-255; 8051: P0-P3 pins).
|
|
103
|
+
*/
|
|
104
|
+
port_write(port: number, val: number): void;
|
|
105
|
+
/**
|
|
106
|
+
* Queue a type-ahead character for INT 21h/keyboard reads (8086).
|
|
107
|
+
*/
|
|
108
|
+
push_key(ch: number): void;
|
|
109
|
+
/**
|
|
110
|
+
* Register dump as "NAME=value" strings (e.g. "AX=1234").
|
|
111
|
+
*/
|
|
112
|
+
regs(): string[];
|
|
113
|
+
/**
|
|
114
|
+
* Reset the CPU to its initial state (registers, flags, PC, memory preserved).
|
|
115
|
+
*/
|
|
116
|
+
reset(): void;
|
|
117
|
+
/**
|
|
118
|
+
* Restore a previously captured `snapshot()` (state must match the ISA).
|
|
119
|
+
*/
|
|
120
|
+
restore(data: Uint8Array): void;
|
|
121
|
+
/**
|
|
122
|
+
* Write-protected ROM region (base, len) if configured, else null.
|
|
123
|
+
*/
|
|
124
|
+
rom_region(): Uint32Array | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Run up to `max_steps` instructions; returns steps executed.
|
|
127
|
+
*/
|
|
128
|
+
run(max_steps: number): number;
|
|
129
|
+
/**
|
|
130
|
+
* Run until PC lands on one of `bps` (that instruction is NOT executed),
|
|
131
|
+
* or halt / blocked on input / max steps. Returns steps executed.
|
|
132
|
+
*/
|
|
133
|
+
run_bp(max_steps: number, bps: Uint32Array): number;
|
|
134
|
+
/**
|
|
135
|
+
* Run until `target` is the next instruction to execute (not executed),
|
|
136
|
+
* or halt / blocked on input / max steps. Returns steps executed.
|
|
137
|
+
*/
|
|
138
|
+
run_to(target_pc: number, max_steps: number): number;
|
|
139
|
+
/**
|
|
140
|
+
* 8086 text-mode framebuffer (80x25 char/attr pairs at 0xB8000); [] otherwise.
|
|
141
|
+
*/
|
|
142
|
+
screen(): Uint8Array;
|
|
143
|
+
/**
|
|
144
|
+
* Inject a received serial byte into the 8051 (sets SBUF + RI).
|
|
145
|
+
*/
|
|
146
|
+
serial_rx(ch: number): void;
|
|
147
|
+
/**
|
|
148
|
+
* Set the emulated DOS/BIOS date-time clock (INT 21h 2Ah/2Ch, INT 1Ah).
|
|
149
|
+
*/
|
|
150
|
+
set_clock(year: number, month: number, day: number, hour: number, min: number, sec: number): void;
|
|
151
|
+
/**
|
|
152
|
+
* 8051 EA pin: false => fetch code from external program memory (XDATA).
|
|
153
|
+
*/
|
|
154
|
+
set_ea(ea: boolean): void;
|
|
155
|
+
/**
|
|
156
|
+
* Set the Z80 interrupt mode (0/1 -> 0x0038, 2 -> I*0x100 + data).
|
|
157
|
+
*/
|
|
158
|
+
set_interrupt_mode(m: number): void;
|
|
159
|
+
/**
|
|
160
|
+
* Set the program counter (entry point after load).
|
|
161
|
+
*/
|
|
162
|
+
set_pc(addr: number): void;
|
|
163
|
+
/**
|
|
164
|
+
* Set a register by name (e.g. "AX", "PC", "R0"). Used by the IDE watch
|
|
165
|
+
* window for click-to-edit. Ignored for names the ISA does not expose.
|
|
166
|
+
*/
|
|
167
|
+
set_reg(name: string, val: number): void;
|
|
168
|
+
/**
|
|
169
|
+
* Mark `[base, base+len)` of main memory as read-only ROM (8086/8085).
|
|
170
|
+
*/
|
|
171
|
+
set_rom_region(base: number, len: number): void;
|
|
172
|
+
/**
|
|
173
|
+
* Write an 8051 SFR / IRAM byte (peripheral-register editor).
|
|
174
|
+
*/
|
|
175
|
+
set_sfr(addr: number, v: number): void;
|
|
176
|
+
/**
|
|
177
|
+
* Set the 8085 SID (Serial Input Data) pin read by RIM (bit 7). 8085 only.
|
|
178
|
+
*/
|
|
179
|
+
set_sid(v: boolean): void;
|
|
180
|
+
/**
|
|
181
|
+
* 8085: (re)configure the external SRAM chip window (default 8 KiB @ 0x9000).
|
|
182
|
+
*/
|
|
183
|
+
set_sram(base: number, len: number): void;
|
|
184
|
+
/**
|
|
185
|
+
* Read an 8051 SFR / IRAM byte (peripheral-register readout).
|
|
186
|
+
*/
|
|
187
|
+
sfr(addr: number): number;
|
|
188
|
+
/**
|
|
189
|
+
* Deterministic serialization of full CPU state (for save/restore and step-back).
|
|
190
|
+
*/
|
|
191
|
+
snapshot(): Uint8Array;
|
|
192
|
+
/**
|
|
193
|
+
* Read the 8085 SOD (Serial Output Data) pin set by SIM (bit 7). 8085 only.
|
|
194
|
+
*/
|
|
195
|
+
sod(): number;
|
|
196
|
+
/**
|
|
197
|
+
* External SRAM window (base, len) if configured (8055), else null.
|
|
198
|
+
*/
|
|
199
|
+
sram_region(): Uint32Array | undefined;
|
|
200
|
+
/**
|
|
201
|
+
* Execute one instruction.
|
|
202
|
+
*/
|
|
203
|
+
step(): void;
|
|
204
|
+
/**
|
|
205
|
+
* Current 8086 video mode (0 when not 8086 / unknown). MR=13h -> pixel graphics.
|
|
206
|
+
*/
|
|
207
|
+
video_mode(): number;
|
|
208
|
+
/**
|
|
209
|
+
* True while the 8086 is blocked on an INT 21h read with an empty buffer.
|
|
210
|
+
*/
|
|
211
|
+
waiting_input(): boolean;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Graphics framebuffer descriptor (8086 pixel modes). `base` is the linear
|
|
216
|
+
* memory address of the pixel data; `w`/`h` are the dimensions in pixels.
|
|
217
|
+
*/
|
|
218
|
+
export class GfxInfo {
|
|
219
|
+
private constructor();
|
|
220
|
+
free(): void;
|
|
221
|
+
[Symbol.dispose](): void;
|
|
222
|
+
base: number;
|
|
223
|
+
h: number;
|
|
224
|
+
w: number;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
228
|
+
|
|
229
|
+
export interface InitOutput {
|
|
230
|
+
readonly memory: WebAssembly.Memory;
|
|
231
|
+
readonly __wbg_emulator_free: (a: number, b: number) => void;
|
|
232
|
+
readonly __wbg_get_gfxinfo_base: (a: number) => number;
|
|
233
|
+
readonly __wbg_get_gfxinfo_h: (a: number) => number;
|
|
234
|
+
readonly __wbg_get_gfxinfo_w: (a: number) => number;
|
|
235
|
+
readonly __wbg_gfxinfo_free: (a: number, b: number) => void;
|
|
236
|
+
readonly __wbg_set_gfxinfo_base: (a: number, b: number) => void;
|
|
237
|
+
readonly __wbg_set_gfxinfo_h: (a: number, b: number) => void;
|
|
238
|
+
readonly __wbg_set_gfxinfo_w: (a: number, b: number) => void;
|
|
239
|
+
readonly emulator_assemble: (a: number, b: number, c: number) => [number, number, number, number];
|
|
240
|
+
readonly emulator_assemble_info: (a: number, b: number, c: number) => [number, number, number, number];
|
|
241
|
+
readonly emulator_cursor: (a: number) => [number, number];
|
|
242
|
+
readonly emulator_cycles: (a: number) => bigint;
|
|
243
|
+
readonly emulator_disasm: (a: number, b: number, c: number) => [number, number];
|
|
244
|
+
readonly emulator_ea_active: (a: number) => number;
|
|
245
|
+
readonly emulator_ext_code_region: (a: number) => [number, number];
|
|
246
|
+
readonly emulator_flags: (a: number) => [number, number];
|
|
247
|
+
readonly emulator_fs_get: (a: number, b: number, c: number) => [number, number, number, number];
|
|
248
|
+
readonly emulator_fs_put: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
249
|
+
readonly emulator_gfx: (a: number) => number;
|
|
250
|
+
readonly emulator_halted: (a: number) => number;
|
|
251
|
+
readonly emulator_interrupt: (a: number, b: number, c: number, d: number) => [number, number];
|
|
252
|
+
readonly emulator_load: (a: number, b: number, c: number, d: number) => void;
|
|
253
|
+
readonly emulator_load_rom: (a: number, b: number, c: number, d: number) => void;
|
|
254
|
+
readonly emulator_mem: (a: number, b: number, c: number) => [number, number];
|
|
255
|
+
readonly emulator_mem_write: (a: number, b: number, c: number, d: number) => void;
|
|
256
|
+
readonly emulator_new: (a: number, b: number) => [number, number, number];
|
|
257
|
+
readonly emulator_out: (a: number) => [number, number];
|
|
258
|
+
readonly emulator_pc: (a: number) => number;
|
|
259
|
+
readonly emulator_pit_count: (a: number, b: number) => number;
|
|
260
|
+
readonly emulator_port_read: (a: number, b: number) => number;
|
|
261
|
+
readonly emulator_port_write: (a: number, b: number, c: number) => void;
|
|
262
|
+
readonly emulator_push_key: (a: number, b: number) => void;
|
|
263
|
+
readonly emulator_regs: (a: number) => [number, number];
|
|
264
|
+
readonly emulator_reset: (a: number) => void;
|
|
265
|
+
readonly emulator_restore: (a: number, b: number, c: number) => void;
|
|
266
|
+
readonly emulator_rom_region: (a: number) => [number, number];
|
|
267
|
+
readonly emulator_run: (a: number, b: number) => number;
|
|
268
|
+
readonly emulator_run_bp: (a: number, b: number, c: number, d: number) => number;
|
|
269
|
+
readonly emulator_run_to: (a: number, b: number, c: number) => number;
|
|
270
|
+
readonly emulator_screen: (a: number) => [number, number];
|
|
271
|
+
readonly emulator_serial_rx: (a: number, b: number) => [number, number];
|
|
272
|
+
readonly emulator_set_clock: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
|
|
273
|
+
readonly emulator_set_ea: (a: number, b: number) => void;
|
|
274
|
+
readonly emulator_set_interrupt_mode: (a: number, b: number) => [number, number];
|
|
275
|
+
readonly emulator_set_pc: (a: number, b: number) => void;
|
|
276
|
+
readonly emulator_set_reg: (a: number, b: number, c: number, d: number) => void;
|
|
277
|
+
readonly emulator_set_rom_region: (a: number, b: number, c: number) => void;
|
|
278
|
+
readonly emulator_set_sfr: (a: number, b: number, c: number) => void;
|
|
279
|
+
readonly emulator_set_sid: (a: number, b: number) => void;
|
|
280
|
+
readonly emulator_set_sram: (a: number, b: number, c: number) => void;
|
|
281
|
+
readonly emulator_sfr: (a: number, b: number) => number;
|
|
282
|
+
readonly emulator_snapshot: (a: number) => [number, number];
|
|
283
|
+
readonly emulator_sod: (a: number) => number;
|
|
284
|
+
readonly emulator_sram_region: (a: number) => [number, number];
|
|
285
|
+
readonly emulator_step: (a: number) => void;
|
|
286
|
+
readonly emulator_video_mode: (a: number) => number;
|
|
287
|
+
readonly emulator_waiting_input: (a: number) => number;
|
|
288
|
+
readonly __wbindgen_externrefs: WebAssembly.Table;
|
|
289
|
+
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
290
|
+
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
291
|
+
readonly __externref_table_dealloc: (a: number) => void;
|
|
292
|
+
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
293
|
+
readonly __externref_drop_slice: (a: number, b: number) => void;
|
|
294
|
+
readonly __wbindgen_start: () => void;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Instantiates the given `module`, which can either be bytes or
|
|
301
|
+
* a precompiled `WebAssembly.Module`.
|
|
302
|
+
*
|
|
303
|
+
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
|
304
|
+
*
|
|
305
|
+
* @returns {InitOutput}
|
|
306
|
+
*/
|
|
307
|
+
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
|
311
|
+
* for everything else, calls `WebAssembly.instantiate` directly.
|
|
312
|
+
*
|
|
313
|
+
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
|
314
|
+
*
|
|
315
|
+
* @returns {Promise<InitOutput>}
|
|
316
|
+
*/
|
|
317
|
+
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|
package/multi_cpu_emu.js
ADDED
|
@@ -0,0 +1,855 @@
|
|
|
1
|
+
/* @ts-self-types="./multi_cpu_emu.d.ts" */
|
|
2
|
+
|
|
3
|
+
export class Emulator {
|
|
4
|
+
__destroy_into_raw() {
|
|
5
|
+
const ptr = this.__wbg_ptr;
|
|
6
|
+
this.__wbg_ptr = 0;
|
|
7
|
+
EmulatorFinalization.unregister(this);
|
|
8
|
+
return ptr;
|
|
9
|
+
}
|
|
10
|
+
free() {
|
|
11
|
+
const ptr = this.__destroy_into_raw();
|
|
12
|
+
wasm.__wbg_emulator_free(ptr, 0);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Assemble source for the current ISA; returns machine code bytes.
|
|
16
|
+
* @param {string} source
|
|
17
|
+
* @returns {Uint8Array}
|
|
18
|
+
*/
|
|
19
|
+
assemble(source) {
|
|
20
|
+
const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
21
|
+
const len0 = WASM_VECTOR_LEN;
|
|
22
|
+
const ret = wasm.emulator_assemble(this.__wbg_ptr, ptr0, len0);
|
|
23
|
+
if (ret[3]) {
|
|
24
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
25
|
+
}
|
|
26
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
27
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
28
|
+
return v2;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Assemble and return per-line machine code as "ADDR BYTES" strings
|
|
32
|
+
* (one per source line, empty for lines that emit nothing).
|
|
33
|
+
* @param {string} source
|
|
34
|
+
* @returns {string[]}
|
|
35
|
+
*/
|
|
36
|
+
assemble_info(source) {
|
|
37
|
+
const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
38
|
+
const len0 = WASM_VECTOR_LEN;
|
|
39
|
+
const ret = wasm.emulator_assemble_info(this.__wbg_ptr, ptr0, len0);
|
|
40
|
+
if (ret[3]) {
|
|
41
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
42
|
+
}
|
|
43
|
+
var v2 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
44
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
45
|
+
return v2;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 8086 text cursor as [col, row]; [0,0] otherwise.
|
|
49
|
+
* @returns {Uint8Array}
|
|
50
|
+
*/
|
|
51
|
+
cursor() {
|
|
52
|
+
const ret = wasm.emulator_cursor(this.__wbg_ptr);
|
|
53
|
+
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
54
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
55
|
+
return v1;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Total clock cycles executed (machine cycles / T-states). Drives the
|
|
59
|
+
* cycle-accurate timers (8086 PIT, 8051 timers, 8085 8155 timer).
|
|
60
|
+
* @returns {bigint}
|
|
61
|
+
*/
|
|
62
|
+
cycles() {
|
|
63
|
+
const ret = wasm.emulator_cycles(this.__wbg_ptr);
|
|
64
|
+
return BigInt.asUintN(64, ret);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Disassemble `count` instructions starting at `addr`. Each returned line
|
|
68
|
+
* is "ADDR BYTES text" (use `Disasm::line`). Other ISAs return [].
|
|
69
|
+
* @param {number} addr
|
|
70
|
+
* @param {number} count
|
|
71
|
+
* @returns {string[]}
|
|
72
|
+
*/
|
|
73
|
+
disasm(addr, count) {
|
|
74
|
+
const ret = wasm.emulator_disasm(this.__wbg_ptr, addr, count);
|
|
75
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
76
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
77
|
+
return v1;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 8051 EA pin state (true = internal code, false = external via XDATA).
|
|
81
|
+
* @returns {boolean}
|
|
82
|
+
*/
|
|
83
|
+
ea_active() {
|
|
84
|
+
const ret = wasm.emulator_ea_active(this.__wbg_ptr);
|
|
85
|
+
return ret !== 0;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 8051 external-code (XDATA) region (base, len) when EA is low, else null.
|
|
89
|
+
* @returns {Uint32Array | undefined}
|
|
90
|
+
*/
|
|
91
|
+
ext_code_region() {
|
|
92
|
+
const ret = wasm.emulator_ext_code_region(this.__wbg_ptr);
|
|
93
|
+
let v1;
|
|
94
|
+
if (ret[0] !== 0) {
|
|
95
|
+
v1 = getArrayU32FromWasm0(ret[0], ret[1]).slice();
|
|
96
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
97
|
+
}
|
|
98
|
+
return v1;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Active flag names as short strings (e.g. "ZF", "CY").
|
|
102
|
+
* @returns {string[]}
|
|
103
|
+
*/
|
|
104
|
+
flags() {
|
|
105
|
+
const ret = wasm.emulator_flags(this.__wbg_ptr);
|
|
106
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
107
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
108
|
+
return v1;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Read a file back from the 8086 DOS virtual filesystem (empty if absent).
|
|
112
|
+
* @param {string} name
|
|
113
|
+
* @returns {Uint8Array | undefined}
|
|
114
|
+
*/
|
|
115
|
+
fs_get(name) {
|
|
116
|
+
const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
117
|
+
const len0 = WASM_VECTOR_LEN;
|
|
118
|
+
const ret = wasm.emulator_fs_get(this.__wbg_ptr, ptr0, len0);
|
|
119
|
+
if (ret[3]) {
|
|
120
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
121
|
+
}
|
|
122
|
+
let v2;
|
|
123
|
+
if (ret[0] !== 0) {
|
|
124
|
+
v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
125
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
126
|
+
}
|
|
127
|
+
return v2;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Preload a file into the 8086 DOS virtual filesystem.
|
|
131
|
+
* @param {string} name
|
|
132
|
+
* @param {Uint8Array} data
|
|
133
|
+
*/
|
|
134
|
+
fs_put(name, data) {
|
|
135
|
+
const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
136
|
+
const len0 = WASM_VECTOR_LEN;
|
|
137
|
+
const ptr1 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
|
138
|
+
const len1 = WASM_VECTOR_LEN;
|
|
139
|
+
const ret = wasm.emulator_fs_put(this.__wbg_ptr, ptr0, len0, ptr1, len1);
|
|
140
|
+
if (ret[1]) {
|
|
141
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 8086 graphics framebuffer, or None when in a text mode / non-8086 ISA.
|
|
146
|
+
* @returns {GfxInfo | undefined}
|
|
147
|
+
*/
|
|
148
|
+
gfx() {
|
|
149
|
+
const ret = wasm.emulator_gfx(this.__wbg_ptr);
|
|
150
|
+
return ret === 0 ? undefined : GfxInfo.__wrap(ret);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* True once the CPU has executed HLT (or otherwise stopped).
|
|
154
|
+
* @returns {boolean}
|
|
155
|
+
*/
|
|
156
|
+
halted() {
|
|
157
|
+
const ret = wasm.emulator_halted(this.__wbg_ptr);
|
|
158
|
+
return ret !== 0;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Hardware interrupt: 8085 = "TRAP" | "RST75" | "RST65" | "RST55" |
|
|
162
|
+
* "INTR" (data = vector); 8051 = "INT0" | "INT1". Throws on unknown kind.
|
|
163
|
+
* @param {string} kind
|
|
164
|
+
* @param {number} data
|
|
165
|
+
*/
|
|
166
|
+
interrupt(kind, data) {
|
|
167
|
+
const ptr0 = passStringToWasm0(kind, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
168
|
+
const len0 = WASM_VECTOR_LEN;
|
|
169
|
+
const ret = wasm.emulator_interrupt(this.__wbg_ptr, ptr0, len0, data);
|
|
170
|
+
if (ret[1]) {
|
|
171
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Load raw machine code at `origin` and set PC there.
|
|
176
|
+
* @param {Uint8Array} code
|
|
177
|
+
* @param {number} origin
|
|
178
|
+
*/
|
|
179
|
+
load(code, origin) {
|
|
180
|
+
const ptr0 = passArray8ToWasm0(code, wasm.__wbindgen_malloc);
|
|
181
|
+
const len0 = WASM_VECTOR_LEN;
|
|
182
|
+
wasm.emulator_load(this.__wbg_ptr, ptr0, len0, origin);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Load a ROM image and mark its range read-only. 8051 routes to external
|
|
186
|
+
* code (XDATA) when EA is low.
|
|
187
|
+
* @param {Uint8Array} data
|
|
188
|
+
* @param {number} addr
|
|
189
|
+
*/
|
|
190
|
+
load_rom(data, addr) {
|
|
191
|
+
const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
|
192
|
+
const len0 = WASM_VECTOR_LEN;
|
|
193
|
+
wasm.emulator_load_rom(this.__wbg_ptr, ptr0, len0, addr);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Linear memory read of `len` bytes starting at `addr`.
|
|
197
|
+
* @param {number} addr
|
|
198
|
+
* @param {number} len
|
|
199
|
+
* @returns {Uint8Array}
|
|
200
|
+
*/
|
|
201
|
+
mem(addr, len) {
|
|
202
|
+
const ret = wasm.emulator_mem(this.__wbg_ptr, addr, len);
|
|
203
|
+
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
204
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
205
|
+
return v1;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Write bytes into memory (IDE memory poking).
|
|
209
|
+
* @param {number} addr
|
|
210
|
+
* @param {Uint8Array} data
|
|
211
|
+
*/
|
|
212
|
+
mem_write(addr, data) {
|
|
213
|
+
const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
|
214
|
+
const len0 = WASM_VECTOR_LEN;
|
|
215
|
+
wasm.emulator_mem_write(this.__wbg_ptr, addr, ptr0, len0);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Create an emulator for one of: "8086", "8085", "8051", "6502", "Z80", "rv32".
|
|
219
|
+
* Throws if the ISA name is unknown.
|
|
220
|
+
* @param {string} isa
|
|
221
|
+
*/
|
|
222
|
+
constructor(isa) {
|
|
223
|
+
const ptr0 = passStringToWasm0(isa, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
224
|
+
const len0 = WASM_VECTOR_LEN;
|
|
225
|
+
const ret = wasm.emulator_new(ptr0, len0);
|
|
226
|
+
if (ret[2]) {
|
|
227
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
228
|
+
}
|
|
229
|
+
this.__wbg_ptr = ret[0];
|
|
230
|
+
EmulatorFinalization.register(this, this.__wbg_ptr, this);
|
|
231
|
+
return this;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Drain the program output buffer.
|
|
235
|
+
* @returns {string}
|
|
236
|
+
*/
|
|
237
|
+
out() {
|
|
238
|
+
let deferred1_0;
|
|
239
|
+
let deferred1_1;
|
|
240
|
+
try {
|
|
241
|
+
const ret = wasm.emulator_out(this.__wbg_ptr);
|
|
242
|
+
deferred1_0 = ret[0];
|
|
243
|
+
deferred1_1 = ret[1];
|
|
244
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
245
|
+
} finally {
|
|
246
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Current program counter (instruction pointer).
|
|
251
|
+
* @returns {number}
|
|
252
|
+
*/
|
|
253
|
+
pc() {
|
|
254
|
+
const ret = wasm.emulator_pc(this.__wbg_ptr);
|
|
255
|
+
return ret >>> 0;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Current reload/count of an 8086 PIT channel (0..2). Other ISAs: 0.
|
|
259
|
+
* @param {number} n
|
|
260
|
+
* @returns {number}
|
|
261
|
+
*/
|
|
262
|
+
pit_count(n) {
|
|
263
|
+
const ret = wasm.emulator_pit_count(this.__wbg_ptr, n);
|
|
264
|
+
return ret;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Queue a key for the 8086's INT 21h keyboard reads (AH=01/06/07/08/0C).
|
|
268
|
+
* @param {number} port
|
|
269
|
+
* @returns {number}
|
|
270
|
+
*/
|
|
271
|
+
port_read(port) {
|
|
272
|
+
const ret = wasm.emulator_port_read(this.__wbg_ptr, port);
|
|
273
|
+
return ret;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Write an I/O port byte (8085/8086: port space 0-255; 8051: P0-P3 pins).
|
|
277
|
+
* @param {number} port
|
|
278
|
+
* @param {number} val
|
|
279
|
+
*/
|
|
280
|
+
port_write(port, val) {
|
|
281
|
+
wasm.emulator_port_write(this.__wbg_ptr, port, val);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Queue a type-ahead character for INT 21h/keyboard reads (8086).
|
|
285
|
+
* @param {number} ch
|
|
286
|
+
*/
|
|
287
|
+
push_key(ch) {
|
|
288
|
+
wasm.emulator_push_key(this.__wbg_ptr, ch);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Register dump as "NAME=value" strings (e.g. "AX=1234").
|
|
292
|
+
* @returns {string[]}
|
|
293
|
+
*/
|
|
294
|
+
regs() {
|
|
295
|
+
const ret = wasm.emulator_regs(this.__wbg_ptr);
|
|
296
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
297
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
298
|
+
return v1;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Reset the CPU to its initial state (registers, flags, PC, memory preserved).
|
|
302
|
+
*/
|
|
303
|
+
reset() {
|
|
304
|
+
wasm.emulator_reset(this.__wbg_ptr);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Restore a previously captured `snapshot()` (state must match the ISA).
|
|
308
|
+
* @param {Uint8Array} data
|
|
309
|
+
*/
|
|
310
|
+
restore(data) {
|
|
311
|
+
const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
|
312
|
+
const len0 = WASM_VECTOR_LEN;
|
|
313
|
+
wasm.emulator_restore(this.__wbg_ptr, ptr0, len0);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Write-protected ROM region (base, len) if configured, else null.
|
|
317
|
+
* @returns {Uint32Array | undefined}
|
|
318
|
+
*/
|
|
319
|
+
rom_region() {
|
|
320
|
+
const ret = wasm.emulator_rom_region(this.__wbg_ptr);
|
|
321
|
+
let v1;
|
|
322
|
+
if (ret[0] !== 0) {
|
|
323
|
+
v1 = getArrayU32FromWasm0(ret[0], ret[1]).slice();
|
|
324
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
325
|
+
}
|
|
326
|
+
return v1;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Run up to `max_steps` instructions; returns steps executed.
|
|
330
|
+
* @param {number} max_steps
|
|
331
|
+
* @returns {number}
|
|
332
|
+
*/
|
|
333
|
+
run(max_steps) {
|
|
334
|
+
const ret = wasm.emulator_run(this.__wbg_ptr, max_steps);
|
|
335
|
+
return ret >>> 0;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Run until PC lands on one of `bps` (that instruction is NOT executed),
|
|
339
|
+
* or halt / blocked on input / max steps. Returns steps executed.
|
|
340
|
+
* @param {number} max_steps
|
|
341
|
+
* @param {Uint32Array} bps
|
|
342
|
+
* @returns {number}
|
|
343
|
+
*/
|
|
344
|
+
run_bp(max_steps, bps) {
|
|
345
|
+
const ptr0 = passArray32ToWasm0(bps, wasm.__wbindgen_malloc);
|
|
346
|
+
const len0 = WASM_VECTOR_LEN;
|
|
347
|
+
const ret = wasm.emulator_run_bp(this.__wbg_ptr, max_steps, ptr0, len0);
|
|
348
|
+
return ret >>> 0;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Run until `target` is the next instruction to execute (not executed),
|
|
352
|
+
* or halt / blocked on input / max steps. Returns steps executed.
|
|
353
|
+
* @param {number} target_pc
|
|
354
|
+
* @param {number} max_steps
|
|
355
|
+
* @returns {number}
|
|
356
|
+
*/
|
|
357
|
+
run_to(target_pc, max_steps) {
|
|
358
|
+
const ret = wasm.emulator_run_to(this.__wbg_ptr, target_pc, max_steps);
|
|
359
|
+
return ret >>> 0;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* 8086 text-mode framebuffer (80x25 char/attr pairs at 0xB8000); [] otherwise.
|
|
363
|
+
* @returns {Uint8Array}
|
|
364
|
+
*/
|
|
365
|
+
screen() {
|
|
366
|
+
const ret = wasm.emulator_screen(this.__wbg_ptr);
|
|
367
|
+
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
368
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
369
|
+
return v1;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Inject a received serial byte into the 8051 (sets SBUF + RI).
|
|
373
|
+
* @param {number} ch
|
|
374
|
+
*/
|
|
375
|
+
serial_rx(ch) {
|
|
376
|
+
const ret = wasm.emulator_serial_rx(this.__wbg_ptr, ch);
|
|
377
|
+
if (ret[1]) {
|
|
378
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Set the emulated DOS/BIOS date-time clock (INT 21h 2Ah/2Ch, INT 1Ah).
|
|
383
|
+
* @param {number} year
|
|
384
|
+
* @param {number} month
|
|
385
|
+
* @param {number} day
|
|
386
|
+
* @param {number} hour
|
|
387
|
+
* @param {number} min
|
|
388
|
+
* @param {number} sec
|
|
389
|
+
*/
|
|
390
|
+
set_clock(year, month, day, hour, min, sec) {
|
|
391
|
+
const ret = wasm.emulator_set_clock(this.__wbg_ptr, year, month, day, hour, min, sec);
|
|
392
|
+
if (ret[1]) {
|
|
393
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* 8051 EA pin: false => fetch code from external program memory (XDATA).
|
|
398
|
+
* @param {boolean} ea
|
|
399
|
+
*/
|
|
400
|
+
set_ea(ea) {
|
|
401
|
+
wasm.emulator_set_ea(this.__wbg_ptr, ea);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Set the Z80 interrupt mode (0/1 -> 0x0038, 2 -> I*0x100 + data).
|
|
405
|
+
* @param {number} m
|
|
406
|
+
*/
|
|
407
|
+
set_interrupt_mode(m) {
|
|
408
|
+
const ret = wasm.emulator_set_interrupt_mode(this.__wbg_ptr, m);
|
|
409
|
+
if (ret[1]) {
|
|
410
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Set the program counter (entry point after load).
|
|
415
|
+
* @param {number} addr
|
|
416
|
+
*/
|
|
417
|
+
set_pc(addr) {
|
|
418
|
+
wasm.emulator_set_pc(this.__wbg_ptr, addr);
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Set a register by name (e.g. "AX", "PC", "R0"). Used by the IDE watch
|
|
422
|
+
* window for click-to-edit. Ignored for names the ISA does not expose.
|
|
423
|
+
* @param {string} name
|
|
424
|
+
* @param {number} val
|
|
425
|
+
*/
|
|
426
|
+
set_reg(name, val) {
|
|
427
|
+
const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
428
|
+
const len0 = WASM_VECTOR_LEN;
|
|
429
|
+
wasm.emulator_set_reg(this.__wbg_ptr, ptr0, len0, val);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Mark `[base, base+len)` of main memory as read-only ROM (8086/8085).
|
|
433
|
+
* @param {number} base
|
|
434
|
+
* @param {number} len
|
|
435
|
+
*/
|
|
436
|
+
set_rom_region(base, len) {
|
|
437
|
+
wasm.emulator_set_rom_region(this.__wbg_ptr, base, len);
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Write an 8051 SFR / IRAM byte (peripheral-register editor).
|
|
441
|
+
* @param {number} addr
|
|
442
|
+
* @param {number} v
|
|
443
|
+
*/
|
|
444
|
+
set_sfr(addr, v) {
|
|
445
|
+
wasm.emulator_set_sfr(this.__wbg_ptr, addr, v);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Set the 8085 SID (Serial Input Data) pin read by RIM (bit 7). 8085 only.
|
|
449
|
+
* @param {boolean} v
|
|
450
|
+
*/
|
|
451
|
+
set_sid(v) {
|
|
452
|
+
wasm.emulator_set_sid(this.__wbg_ptr, v);
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* 8085: (re)configure the external SRAM chip window (default 8 KiB @ 0x9000).
|
|
456
|
+
* @param {number} base
|
|
457
|
+
* @param {number} len
|
|
458
|
+
*/
|
|
459
|
+
set_sram(base, len) {
|
|
460
|
+
wasm.emulator_set_sram(this.__wbg_ptr, base, len);
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Read an 8051 SFR / IRAM byte (peripheral-register readout).
|
|
464
|
+
* @param {number} addr
|
|
465
|
+
* @returns {number}
|
|
466
|
+
*/
|
|
467
|
+
sfr(addr) {
|
|
468
|
+
const ret = wasm.emulator_sfr(this.__wbg_ptr, addr);
|
|
469
|
+
return ret;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Deterministic serialization of full CPU state (for save/restore and step-back).
|
|
473
|
+
* @returns {Uint8Array}
|
|
474
|
+
*/
|
|
475
|
+
snapshot() {
|
|
476
|
+
const ret = wasm.emulator_snapshot(this.__wbg_ptr);
|
|
477
|
+
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
478
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
479
|
+
return v1;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Read the 8085 SOD (Serial Output Data) pin set by SIM (bit 7). 8085 only.
|
|
483
|
+
* @returns {number}
|
|
484
|
+
*/
|
|
485
|
+
sod() {
|
|
486
|
+
const ret = wasm.emulator_sod(this.__wbg_ptr);
|
|
487
|
+
return ret;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* External SRAM window (base, len) if configured (8055), else null.
|
|
491
|
+
* @returns {Uint32Array | undefined}
|
|
492
|
+
*/
|
|
493
|
+
sram_region() {
|
|
494
|
+
const ret = wasm.emulator_sram_region(this.__wbg_ptr);
|
|
495
|
+
let v1;
|
|
496
|
+
if (ret[0] !== 0) {
|
|
497
|
+
v1 = getArrayU32FromWasm0(ret[0], ret[1]).slice();
|
|
498
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
499
|
+
}
|
|
500
|
+
return v1;
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Execute one instruction.
|
|
504
|
+
*/
|
|
505
|
+
step() {
|
|
506
|
+
wasm.emulator_step(this.__wbg_ptr);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Current 8086 video mode (0 when not 8086 / unknown). MR=13h -> pixel graphics.
|
|
510
|
+
* @returns {number}
|
|
511
|
+
*/
|
|
512
|
+
video_mode() {
|
|
513
|
+
const ret = wasm.emulator_video_mode(this.__wbg_ptr);
|
|
514
|
+
return ret;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* True while the 8086 is blocked on an INT 21h read with an empty buffer.
|
|
518
|
+
* @returns {boolean}
|
|
519
|
+
*/
|
|
520
|
+
waiting_input() {
|
|
521
|
+
const ret = wasm.emulator_waiting_input(this.__wbg_ptr);
|
|
522
|
+
return ret !== 0;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
if (Symbol.dispose) Emulator.prototype[Symbol.dispose] = Emulator.prototype.free;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Graphics framebuffer descriptor (8086 pixel modes). `base` is the linear
|
|
529
|
+
* memory address of the pixel data; `w`/`h` are the dimensions in pixels.
|
|
530
|
+
*/
|
|
531
|
+
export class GfxInfo {
|
|
532
|
+
static __wrap(ptr) {
|
|
533
|
+
const obj = Object.create(GfxInfo.prototype);
|
|
534
|
+
obj.__wbg_ptr = ptr;
|
|
535
|
+
GfxInfoFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
536
|
+
return obj;
|
|
537
|
+
}
|
|
538
|
+
__destroy_into_raw() {
|
|
539
|
+
const ptr = this.__wbg_ptr;
|
|
540
|
+
this.__wbg_ptr = 0;
|
|
541
|
+
GfxInfoFinalization.unregister(this);
|
|
542
|
+
return ptr;
|
|
543
|
+
}
|
|
544
|
+
free() {
|
|
545
|
+
const ptr = this.__destroy_into_raw();
|
|
546
|
+
wasm.__wbg_gfxinfo_free(ptr, 0);
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* @returns {number}
|
|
550
|
+
*/
|
|
551
|
+
get base() {
|
|
552
|
+
const ret = wasm.__wbg_get_gfxinfo_base(this.__wbg_ptr);
|
|
553
|
+
return ret >>> 0;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* @returns {number}
|
|
557
|
+
*/
|
|
558
|
+
get h() {
|
|
559
|
+
const ret = wasm.__wbg_get_gfxinfo_h(this.__wbg_ptr);
|
|
560
|
+
return ret >>> 0;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* @returns {number}
|
|
564
|
+
*/
|
|
565
|
+
get w() {
|
|
566
|
+
const ret = wasm.__wbg_get_gfxinfo_w(this.__wbg_ptr);
|
|
567
|
+
return ret >>> 0;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* @param {number} arg0
|
|
571
|
+
*/
|
|
572
|
+
set base(arg0) {
|
|
573
|
+
wasm.__wbg_set_gfxinfo_base(this.__wbg_ptr, arg0);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* @param {number} arg0
|
|
577
|
+
*/
|
|
578
|
+
set h(arg0) {
|
|
579
|
+
wasm.__wbg_set_gfxinfo_h(this.__wbg_ptr, arg0);
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* @param {number} arg0
|
|
583
|
+
*/
|
|
584
|
+
set w(arg0) {
|
|
585
|
+
wasm.__wbg_set_gfxinfo_w(this.__wbg_ptr, arg0);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
if (Symbol.dispose) GfxInfo.prototype[Symbol.dispose] = GfxInfo.prototype.free;
|
|
589
|
+
function __wbg_get_imports() {
|
|
590
|
+
const import0 = {
|
|
591
|
+
__proto__: null,
|
|
592
|
+
__wbg___wbindgen_throw_bb96b2010945f0bc: function(arg0, arg1) {
|
|
593
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
594
|
+
},
|
|
595
|
+
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
596
|
+
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
597
|
+
const ret = getStringFromWasm0(arg0, arg1);
|
|
598
|
+
return ret;
|
|
599
|
+
},
|
|
600
|
+
__wbindgen_init_externref_table: function() {
|
|
601
|
+
const table = wasm.__wbindgen_externrefs;
|
|
602
|
+
const offset = table.grow(4);
|
|
603
|
+
table.set(0, undefined);
|
|
604
|
+
table.set(offset + 0, undefined);
|
|
605
|
+
table.set(offset + 1, null);
|
|
606
|
+
table.set(offset + 2, true);
|
|
607
|
+
table.set(offset + 3, false);
|
|
608
|
+
},
|
|
609
|
+
};
|
|
610
|
+
return {
|
|
611
|
+
__proto__: null,
|
|
612
|
+
"./multi_cpu_emu_bg.js": import0,
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
const EmulatorFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
617
|
+
? { register: () => {}, unregister: () => {} }
|
|
618
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_emulator_free(ptr, 1));
|
|
619
|
+
const GfxInfoFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
620
|
+
? { register: () => {}, unregister: () => {} }
|
|
621
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_gfxinfo_free(ptr, 1));
|
|
622
|
+
|
|
623
|
+
function getArrayJsValueFromWasm0(ptr, len) {
|
|
624
|
+
ptr = ptr >>> 0;
|
|
625
|
+
const mem = getDataViewMemory0();
|
|
626
|
+
const result = [];
|
|
627
|
+
for (let i = ptr; i < ptr + 4 * len; i += 4) {
|
|
628
|
+
result.push(wasm.__wbindgen_externrefs.get(mem.getUint32(i, true)));
|
|
629
|
+
}
|
|
630
|
+
wasm.__externref_drop_slice(ptr, len);
|
|
631
|
+
return result;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function getArrayU32FromWasm0(ptr, len) {
|
|
635
|
+
ptr = ptr >>> 0;
|
|
636
|
+
return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function getArrayU8FromWasm0(ptr, len) {
|
|
640
|
+
ptr = ptr >>> 0;
|
|
641
|
+
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
let cachedDataViewMemory0 = null;
|
|
645
|
+
function getDataViewMemory0() {
|
|
646
|
+
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
|
647
|
+
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
|
648
|
+
}
|
|
649
|
+
return cachedDataViewMemory0;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function getStringFromWasm0(ptr, len) {
|
|
653
|
+
return decodeText(ptr >>> 0, len);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
let cachedUint32ArrayMemory0 = null;
|
|
657
|
+
function getUint32ArrayMemory0() {
|
|
658
|
+
if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) {
|
|
659
|
+
cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer);
|
|
660
|
+
}
|
|
661
|
+
return cachedUint32ArrayMemory0;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
let cachedUint8ArrayMemory0 = null;
|
|
665
|
+
function getUint8ArrayMemory0() {
|
|
666
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
667
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
668
|
+
}
|
|
669
|
+
return cachedUint8ArrayMemory0;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
function passArray32ToWasm0(arg, malloc) {
|
|
673
|
+
const ptr = malloc(arg.length * 4, 4) >>> 0;
|
|
674
|
+
getUint32ArrayMemory0().set(arg, ptr / 4);
|
|
675
|
+
WASM_VECTOR_LEN = arg.length;
|
|
676
|
+
return ptr;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function passArray8ToWasm0(arg, malloc) {
|
|
680
|
+
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
|
681
|
+
getUint8ArrayMemory0().set(arg, ptr / 1);
|
|
682
|
+
WASM_VECTOR_LEN = arg.length;
|
|
683
|
+
return ptr;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
687
|
+
if (realloc === undefined) {
|
|
688
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
689
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
690
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
691
|
+
WASM_VECTOR_LEN = buf.length;
|
|
692
|
+
return ptr;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
let len = arg.length;
|
|
696
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
697
|
+
|
|
698
|
+
const mem = getUint8ArrayMemory0();
|
|
699
|
+
|
|
700
|
+
let offset = 0;
|
|
701
|
+
|
|
702
|
+
for (; offset < len; offset++) {
|
|
703
|
+
const code = arg.charCodeAt(offset);
|
|
704
|
+
if (code > 0x7F) break;
|
|
705
|
+
mem[ptr + offset] = code;
|
|
706
|
+
}
|
|
707
|
+
if (offset !== len) {
|
|
708
|
+
if (offset !== 0) {
|
|
709
|
+
arg = arg.slice(offset);
|
|
710
|
+
}
|
|
711
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
712
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
713
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
714
|
+
|
|
715
|
+
offset += ret.written;
|
|
716
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
WASM_VECTOR_LEN = offset;
|
|
720
|
+
return ptr;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
function takeFromExternrefTable0(idx) {
|
|
724
|
+
const value = wasm.__wbindgen_externrefs.get(idx);
|
|
725
|
+
wasm.__externref_table_dealloc(idx);
|
|
726
|
+
return value;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
730
|
+
cachedTextDecoder.decode();
|
|
731
|
+
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
|
732
|
+
let numBytesDecoded = 0;
|
|
733
|
+
function decodeText(ptr, len) {
|
|
734
|
+
numBytesDecoded += len;
|
|
735
|
+
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
|
736
|
+
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
737
|
+
cachedTextDecoder.decode();
|
|
738
|
+
numBytesDecoded = len;
|
|
739
|
+
}
|
|
740
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
const cachedTextEncoder = new TextEncoder();
|
|
744
|
+
|
|
745
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
746
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
747
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
748
|
+
view.set(buf);
|
|
749
|
+
return {
|
|
750
|
+
read: arg.length,
|
|
751
|
+
written: buf.length
|
|
752
|
+
};
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
let WASM_VECTOR_LEN = 0;
|
|
757
|
+
|
|
758
|
+
let wasmModule, wasmInstance, wasm;
|
|
759
|
+
function __wbg_finalize_init(instance, module) {
|
|
760
|
+
wasmInstance = instance;
|
|
761
|
+
wasm = instance.exports;
|
|
762
|
+
wasmModule = module;
|
|
763
|
+
cachedDataViewMemory0 = null;
|
|
764
|
+
cachedUint32ArrayMemory0 = null;
|
|
765
|
+
cachedUint8ArrayMemory0 = null;
|
|
766
|
+
wasm.__wbindgen_start();
|
|
767
|
+
return wasm;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
async function __wbg_load(module, imports) {
|
|
771
|
+
if (typeof Response === 'function' && module instanceof Response) {
|
|
772
|
+
if (!module.ok) {
|
|
773
|
+
throw new Error(`failed to fetch Wasm: ${module.status} ${module.statusText} fetching '${module.url}'`);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
|
777
|
+
try {
|
|
778
|
+
return await WebAssembly.instantiateStreaming(module, imports);
|
|
779
|
+
} catch (e) {
|
|
780
|
+
const validResponse = expectedResponseType(module.type);
|
|
781
|
+
|
|
782
|
+
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
|
783
|
+
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
|
784
|
+
|
|
785
|
+
} else { throw e; }
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
const bytes = await module.arrayBuffer();
|
|
790
|
+
return await WebAssembly.instantiate(bytes, imports);
|
|
791
|
+
} else {
|
|
792
|
+
const instance = await WebAssembly.instantiate(module, imports);
|
|
793
|
+
|
|
794
|
+
if (instance instanceof WebAssembly.Instance) {
|
|
795
|
+
return { instance, module };
|
|
796
|
+
} else {
|
|
797
|
+
return instance;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
function expectedResponseType(type) {
|
|
802
|
+
switch (type) {
|
|
803
|
+
case 'basic': case 'cors': case 'default': return true;
|
|
804
|
+
}
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
function initSync(module) {
|
|
810
|
+
if (wasm !== undefined) return wasm;
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
if (module !== undefined) {
|
|
814
|
+
if (Object.getPrototypeOf(module) === Object.prototype) {
|
|
815
|
+
({module} = module)
|
|
816
|
+
} else {
|
|
817
|
+
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
const imports = __wbg_get_imports();
|
|
822
|
+
if (!(module instanceof WebAssembly.Module)) {
|
|
823
|
+
module = new WebAssembly.Module(module);
|
|
824
|
+
}
|
|
825
|
+
const instance = new WebAssembly.Instance(module, imports);
|
|
826
|
+
return __wbg_finalize_init(instance, module);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
async function __wbg_init(module_or_path) {
|
|
830
|
+
if (wasm !== undefined) return wasm;
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
if (module_or_path !== undefined) {
|
|
834
|
+
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
|
835
|
+
({module_or_path} = module_or_path)
|
|
836
|
+
} else {
|
|
837
|
+
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (module_or_path === undefined) {
|
|
842
|
+
module_or_path = new URL('multi_cpu_emu_bg.wasm', import.meta.url);
|
|
843
|
+
}
|
|
844
|
+
const imports = __wbg_get_imports();
|
|
845
|
+
|
|
846
|
+
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
|
847
|
+
module_or_path = fetch(module_or_path);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
|
851
|
+
|
|
852
|
+
return __wbg_finalize_init(instance, module);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
export { initSync, __wbg_init as default };
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "8086emu",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"collaborators": [
|
|
5
|
+
"Danish"
|
|
6
|
+
],
|
|
7
|
+
"description": "8086 / 8085 / 8051 / 6502 / Z80 / RISC-V emulator cores in one Rust crate, compiles to WASM",
|
|
8
|
+
"version": "0.1.0",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/danish9661/8086emu"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"multi_cpu_emu_bg.wasm",
|
|
16
|
+
"multi_cpu_emu.js",
|
|
17
|
+
"multi_cpu_emu.d.ts"
|
|
18
|
+
],
|
|
19
|
+
"main": "multi_cpu_emu.js",
|
|
20
|
+
"types": "multi_cpu_emu.d.ts",
|
|
21
|
+
"sideEffects": [
|
|
22
|
+
"./snippets/*"
|
|
23
|
+
]
|
|
24
|
+
}
|