peterpeter8585 commited on
Commit
8df6da4
·
verified ·
1 Parent(s): be5b27f

Upload 553 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
.cargo/config.toml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ [build]
2
+ target-dir = "build"
.devcontainer/Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM library/node:lts-bookworm
2
+
3
+ ARG DEBIAN_FRONTEND=noninteractive
4
+ RUN apt update && \
5
+ apt-get install -y nodejs nasm gdb unzip p7zip-full openjdk-17-jre wget python3 qemu-system-x86 git-core build-essential libc6-dev-i386-cross libc6-dev-i386 clang curl time
6
+ RUN npm install -g jshint
7
+ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
8
+ RUN /root/.cargo/bin/rustup toolchain install stable && \
9
+ /root/.cargo/bin/rustup target add wasm32-unknown-unknown && \
10
+ /root/.cargo/bin/rustup component add rustfmt-preview && \
11
+ /root/.cargo/bin/rustup update && /root/.cargo/bin/rustup update nightly
.devcontainer/devcontainer.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "v86 dev container",
3
+ "build": {
4
+ "dockerfile": "Dockerfile",
5
+ "args": {
6
+ "VARIANT": "ubuntu"
7
+ }
8
+ },
9
+ "features": {
10
+ "ghcr.io/devcontainers-contrib/features/curl-apt-get:1": {},
11
+ "ghcr.io/jungaretti/features/ripgrep:1": {}
12
+ },
13
+ "customizations": {
14
+ "vscode": {
15
+ "extensions": [
16
+ "ms-azuretools.vscode-docker",
17
+ "yzhang.markdown-all-in-one",
18
+ "DavidAnson.vscode-markdownlint",
19
+ "christian-kohler.npm-intellisense",
20
+ "dbaeumer.vscode-eslint",
21
+ "dustypomerleau.rust-syntax",
22
+ "serayuzgur.crates",
23
+ "ms-vscode.makefile-tools",
24
+ "rust-lang.rust-analyzer"
25
+ ]
26
+ }
27
+ }
28
+ }
.editorconfig ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ root=true
2
+
3
+ [*.js]
4
+ charset = utf-8
5
+ indent_style = space
6
+ indent_size = 4
.gitattributes CHANGED
@@ -1,35 +1,4 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ lib/zstd/* linguist-vendored
2
+ lib/softfloat/* linguist-vendored
3
+ bios/seabios-debug.bin filter=lfs diff=lfs merge=lfs -text
4
+ bios/seabios.bin filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.github/ISSUE_TEMPLATE/issue.md ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Issue
3
+ about: Bug reports or feature requests
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ <!--
11
+ Welcome to v86's issue tracker!
12
+
13
+ We use this tracker for bug reports or feature requests. For user support, questions or general comments, use the chat at https://gitter.im/copy/v86 or the forum at https://github.com/copy/v86/discussions
14
+
15
+ Please don't ask for support for any version of Windows. There are many existing issues at https://github.com/copy/v86/issues?q=is%253Aissue+windows. See also docs/windows-nt.md and docs/windows-9x.md.
16
+
17
+ Before reporting OS incompatibilities, check existing issues and the compatibility section of the readme.
18
+
19
+ When reporting issues, please provide the following information:
20
+ - Version of v86 (see the bottom of index.html or the output of `git describe --tags HEAD`)
21
+ - Browser/OS
22
+ - The browser's console output: Open debug.html and press ctrl+shift+k (firefox) or ctrl+shift+j (chromium)
23
+ - If relevant, upload the disk images to allow developers to reproduce the problem locally
24
+ -->
.github/workflows/ci.yml ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ eslint:
9
+ name: eslint
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout repository
13
+ uses: actions/checkout@v4
14
+
15
+ - name: Run eslint
16
+ run: sudo npm install -g eslint; make eslint
17
+
18
+ test:
19
+ runs-on: ubuntu-latest
20
+ name: Build and test
21
+ timeout-minutes: 60
22
+ steps:
23
+ - name: Checkout repository
24
+ uses: actions/checkout@v4
25
+ with:
26
+ fetch-depth: 0
27
+ filter: tree:0
28
+
29
+ - name: Setup Node.js version
30
+ uses: actions/setup-node@v4
31
+ with:
32
+ node-version: '20'
33
+ check-latest: true
34
+ registry-url: 'https://registry.npmjs.org'
35
+
36
+ - name: Setup toolchain
37
+ run: |
38
+ rustup toolchain install stable --profile minimal
39
+ rustup target add wasm32-unknown-unknown
40
+ rustup component add rustfmt
41
+
42
+ - name: Install APT packages
43
+ run: |
44
+ sudo apt-get update -y
45
+ sudo apt-get install nasm gdb qemu-system-x86 libc6-dev-i386 -y
46
+
47
+ - name: Build all-debug
48
+ run: make all-debug
49
+
50
+ - name: Build all
51
+ run: make all
52
+
53
+ - name: Build fallback
54
+ run: make build/v86-fallback.wasm
55
+
56
+ - name: rustfmt check
57
+ run: make rustfmt
58
+
59
+ - name: Fetch kvm-unit-test cache
60
+ uses: actions/cache@v4
61
+ id: cache-kvm-unit-test
62
+ with:
63
+ path: tests/kvm-unit-tests/
64
+ key: ${{ runner.os }}-kvm-unit-test
65
+
66
+ - name: Build kvm-unit-test
67
+ if: steps.cache-kvm-unit-test.outputs.cache-hit != 'true'
68
+ run: (cd tests/kvm-unit-tests && ./configure && make x86/realmode.flat)
69
+
70
+ - name: Run kvm-unit-test
71
+ run: tests/kvm-unit-tests/run.mjs tests/kvm-unit-tests/x86/realmode.flat
72
+
73
+ - name: Fetch namsmtests cache
74
+ uses: actions/cache@v4
75
+ id: cache-nasmtests
76
+ with:
77
+ path: tests/nasm/build/
78
+ key: ${{ runner.os }}-nasmtests
79
+
80
+ - name: Run nasmtests
81
+ run: MAX_PARALLEL_TESTS=1 make nasmtests
82
+
83
+ - name: Run nasmtests-force-jit
84
+ run: MAX_PARALLEL_TESTS=1 make nasmtests-force-jit
85
+
86
+ - name: Run rust-test
87
+ run: make rust-test
88
+
89
+ - name: Fetch image cache
90
+ uses: actions/cache@v4
91
+ id: cache-images
92
+ with:
93
+ path: images/
94
+ key: ${{ runner.os }}-images-v2
95
+
96
+ - name: Download uncached images
97
+ if: steps.cache-images.outputs.cache-hit != 'true'
98
+ run: mkdir -p images && curl --compressed --output-dir images --remote-name-all https://i.copy.sh/{linux.iso,linux3.iso,linux4.iso,buildroot-bzimage68.bin,TinyCore-11.0.iso,oberon.img,msdos.img,openbsd-floppy.img,kolibri.img,windows101.img,os8.img,freedos722.img,mobius-fd-release5.img,msdos622.img}
99
+
100
+ - name: Run api-tests
101
+ run: make api-tests
102
+
103
+ - name: Run qemutests
104
+ run: make qemutests
105
+
106
+ - name: Run qemutests-release
107
+ run: make qemutests-release
108
+
109
+ - name: Run jitpagingtests
110
+ run: make jitpagingtests
111
+
112
+ - name: Run integration tests
113
+ run: MAX_PARALLEL_TESTS=1 make tests
114
+
115
+ - name: Run devices tests
116
+ run: make devices-test
117
+
118
+ - name: Run expect tests
119
+ run: make expect-tests
120
+
121
+ - name: Update package.json version
122
+ run: make update-package-json-version
123
+
124
+ - name: Upload the artifact
125
+ uses: actions/upload-artifact@v4
126
+ with:
127
+ name: v86
128
+ path: |
129
+ package.json
130
+ LICENSE
131
+ Readme.md
132
+ build/libv86*.js
133
+ build/libv86*.js.map
134
+ build/v86*.wasm
135
+ build/*.mjs
136
+
137
+ upload:
138
+ name: Upload release
139
+ runs-on: ubuntu-latest
140
+ needs: test
141
+ if: github.ref == 'refs/heads/master'
142
+
143
+ permissions:
144
+ id-token: write
145
+ contents: write
146
+
147
+ steps:
148
+ - name: Delete old release and tag
149
+ uses: dev-drprasad/delete-tag-and-release@v1.0.1
150
+ with:
151
+ delete_release: true
152
+ tag_name: latest
153
+ github_token: ${{ secrets.GITHUB_TOKEN }}
154
+
155
+ - name: Get artifacts
156
+ uses: actions/download-artifact@v4
157
+ with:
158
+ name: v86
159
+
160
+ - name: Display structure of downloaded files
161
+ run: ls -R
162
+
163
+ - uses: actions/setup-node@v4
164
+ with:
165
+ node-version: '20.x'
166
+ registry-url: 'https://registry.npmjs.org'
167
+
168
+ - name: Release to GitHub
169
+ uses: ncipollo/release-action@v1
170
+ with:
171
+ name: Latest Release
172
+ tag: latest
173
+ commit: master
174
+ body: ${{ github.event.head_commit.message }}
175
+ artifacts: "build/libv86*.js,build/libv86*.js.map,build/*.mjs,build/v86*.wasm"
176
+ prerelease: true
177
+
178
+ - run: npm publish --provenance --access public
179
+ env:
180
+ NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
.gitignore ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.swp
2
+ *.swo
3
+ tests/qemu/test-i386
4
+ tests/jit-paging/test-jit
5
+ *.map
6
+ build/
7
+ closure-compiler/
8
+ images/
9
+ *.bak
10
+ *.orig
11
+ *.wasm
12
+ *.o
13
+ *.bin
14
+ *.img
15
+ *.fixture
16
+ *.fuse_hidden*
17
+ *.DS_Store
18
+ node_modules/
19
+ Cargo.lock
20
+ build-head
21
+ src/rust/gen/interpreter.rs
22
+ src/rust/gen/interpreter0f.rs
23
+ src/rust/gen/analyzer.rs
24
+ src/rust/gen/analyzer0f.rs
25
+ src/rust/gen/jit.rs
26
+ src/rust/gen/jit0f.rs
27
+ bios/seabios
28
+ bench-results
.rustfmt.toml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ use_field_init_shorthand = true
2
+ match_block_trailing_comma = true
3
+ fn_single_line = true
4
+ imports_indent = "Block"
5
+ control_brace_style = "ClosingNextLine"
6
+ single_line_if_else_max_width = 92
.vscode/tasks.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
3
+ // for the documentation about the tasks.json format
4
+ "version": "2.0.0",
5
+ "tasks": [
6
+ {
7
+ "label": "Fetch images",
8
+ "type": "shell",
9
+ "command": "wget -P images/ https://i.copy.sh/{linux3.iso,linux.iso,linux4.iso,buildroot-bzimage.bin,openbsd-floppy.img,kolibri.img,windows101.img,os8.img,freedos722.img}"
10
+ }
11
+ ]
12
+ }
Cargo.toml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [package]
2
+ name = "v86"
3
+ version = "0.1.0"
4
+ publish = false
5
+ edition = "2021"
6
+
7
+ [features]
8
+ default = []
9
+ profiler = []
10
+
11
+ [lib]
12
+ crate-type = ["cdylib"]
13
+ path = "src/rust/lib.rs"
14
+
15
+ [profile.test]
16
+ lto = false
17
+ opt-level = 2
18
+ overflow-checks = false
19
+
20
+ [profile.dev]
21
+ lto = true
22
+ opt-level = 2
23
+ panic = "abort"
24
+ overflow-checks = false
25
+
26
+ [profile.release]
27
+ lto = true
28
+ opt-level = 3
29
+ incremental = false
30
+ panic = "abort"
LICENSE ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2012, The v86 contributors
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
LICENSE.MIT ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ QEMU Floppy disk emulator (Intel 82078)
2
+
3
+ Copyright (c) 2003, 2007 Jocelyn Mayer
4
+ Copyright (c) 2008 Hervé Poussineau
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
Makefile ADDED
@@ -0,0 +1,398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CLOSURE_DIR=closure-compiler
2
+ CLOSURE=$(CLOSURE_DIR)/compiler.jar
3
+ NASM_TEST_DIR=./tests/nasm
4
+
5
+ INSTRUCTION_TABLES=src/rust/gen/jit.rs src/rust/gen/jit0f.rs \
6
+ src/rust/gen/interpreter.rs src/rust/gen/interpreter0f.rs \
7
+ src/rust/gen/analyzer.rs src/rust/gen/analyzer0f.rs \
8
+
9
+ # Only the dependencies common to both generate_{jit,interpreter}.js
10
+ GEN_DEPENDENCIES=$(filter-out gen/generate_interpreter.js gen/generate_jit.js gen/generate_analyzer.js, $(wildcard gen/*.js))
11
+ JIT_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_jit.js
12
+ INTERPRETER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_interpreter.js
13
+ ANALYZER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_analyzer.js
14
+
15
+ STRIP_DEBUG_FLAG=
16
+ ifeq ($(STRIP_DEBUG),true)
17
+ STRIP_DEBUG_FLAG=--v86-strip-debug
18
+ endif
19
+
20
+ WASM_OPT ?= false
21
+
22
+ default: build/v86-debug.wasm
23
+ all: build/v86_all.js build/libv86.js build/libv86.mjs build/v86.wasm
24
+ all-debug: build/libv86-debug.js build/libv86-debug.mjs build/v86-debug.wasm
25
+ browser: build/v86_all.js
26
+
27
+ # Used for nodejs builds and in order to profile code.
28
+ # `debug` gives identifiers a readable name, make sure it doesn't have any side effects.
29
+ CLOSURE_READABLE=--formatting PRETTY_PRINT --debug
30
+
31
+ CLOSURE_SOURCE_MAP=\
32
+ --source_map_format V3\
33
+ --create_source_map '%outname%.map'
34
+
35
+ CLOSURE_FLAGS=\
36
+ --generate_exports\
37
+ --externs src/externs.js\
38
+ --warning_level VERBOSE\
39
+ --jscomp_error accessControls\
40
+ --jscomp_error checkRegExp\
41
+ --jscomp_error checkTypes\
42
+ --jscomp_error checkVars\
43
+ --jscomp_error conformanceViolations\
44
+ --jscomp_error const\
45
+ --jscomp_error constantProperty\
46
+ --jscomp_error deprecated\
47
+ --jscomp_error deprecatedAnnotations\
48
+ --jscomp_error duplicateMessage\
49
+ --jscomp_error es5Strict\
50
+ --jscomp_error externsValidation\
51
+ --jscomp_error globalThis\
52
+ --jscomp_error invalidCasts\
53
+ --jscomp_error misplacedTypeAnnotation\
54
+ --jscomp_error missingProperties\
55
+ --jscomp_error missingReturn\
56
+ --jscomp_error msgDescriptions\
57
+ --jscomp_error nonStandardJsDocs\
58
+ --jscomp_error suspiciousCode\
59
+ --jscomp_error strictModuleDepCheck\
60
+ --jscomp_error typeInvalidation\
61
+ --jscomp_error undefinedVars\
62
+ --jscomp_error unknownDefines\
63
+ --jscomp_error visibility\
64
+ --use_types_for_optimization\
65
+ --assume_function_wrapper\
66
+ --summary_detail_level 3\
67
+ --language_in ECMASCRIPT_2020\
68
+ --language_out ECMASCRIPT_2020
69
+
70
+ CARGO_FLAGS_SAFE=\
71
+ --target wasm32-unknown-unknown \
72
+ -- \
73
+ -C linker=tools/rust-lld-wrapper \
74
+ -C link-args="--import-table --global-base=4096 $(STRIP_DEBUG_FLAG)" \
75
+ -C link-args="build/softfloat.o" \
76
+ -C link-args="build/zstddeclib.o" \
77
+ --verbose
78
+
79
+ CARGO_FLAGS=$(CARGO_FLAGS_SAFE) -C target-feature=+bulk-memory -C target-feature=+multivalue -C target-feature=+simd128
80
+
81
+ CORE_FILES=cjs.js const.js io.js main.js lib.js buffer.js ide.js pci.js floppy.js \
82
+ dma.js pit.js vga.js ps2.js rtc.js uart.js \
83
+ acpi.js iso9660.js \
84
+ state.js ne2k.js sb16.js virtio.js virtio_console.js virtio_net.js virtio_balloon.js \
85
+ bus.js log.js cpu.js \
86
+ elf.js kernel.js
87
+ LIB_FILES=9p.js filesystem.js marshall.js
88
+ BROWSER_FILES=screen.js keyboard.js mouse.js speaker.js serial.js \
89
+ network.js starter.js worker_bus.js dummy_screen.js \
90
+ inbrowser_network.js fake_network.js wisp_network.js fetch_network.js \
91
+ print_stats.js filestorage.js
92
+
93
+ RUST_FILES=$(shell find src/rust/ -name '*.rs') \
94
+ src/rust/gen/interpreter.rs src/rust/gen/interpreter0f.rs \
95
+ src/rust/gen/jit.rs src/rust/gen/jit0f.rs \
96
+ src/rust/gen/analyzer.rs src/rust/gen/analyzer0f.rs
97
+
98
+ CORE_FILES:=$(addprefix src/,$(CORE_FILES))
99
+ LIB_FILES:=$(addprefix lib/,$(LIB_FILES))
100
+ BROWSER_FILES:=$(addprefix src/browser/,$(BROWSER_FILES))
101
+
102
+ build/v86_all.js: $(CLOSURE) src/*.js src/browser/*.js lib/*.js
103
+ mkdir -p build
104
+ -ls -lh build/v86_all.js
105
+ java -jar $(CLOSURE) \
106
+ --js_output_file build/v86_all.js\
107
+ --define=DEBUG=false\
108
+ $(CLOSURE_SOURCE_MAP)\
109
+ $(CLOSURE_FLAGS)\
110
+ --compilation_level ADVANCED\
111
+ --js $(CORE_FILES)\
112
+ --js $(LIB_FILES)\
113
+ --js $(BROWSER_FILES)\
114
+ --js src/browser/main.js
115
+ ls -lh build/v86_all.js
116
+
117
+ build/v86_all_debug.js: $(CLOSURE) src/*.js src/browser/*.js lib/*.js
118
+ mkdir -p build
119
+ java -jar $(CLOSURE) \
120
+ --js_output_file build/v86_all_debug.js\
121
+ --define=DEBUG=true\
122
+ $(CLOSURE_SOURCE_MAP)\
123
+ $(CLOSURE_FLAGS)\
124
+ --compilation_level ADVANCED\
125
+ --js $(CORE_FILES)\
126
+ --js $(LIB_FILES)\
127
+ --js $(BROWSER_FILES)\
128
+ --js src/browser/main.js
129
+
130
+ build/libv86.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js
131
+ mkdir -p build
132
+ -ls -lh build/libv86.js
133
+ java -jar $(CLOSURE) \
134
+ --js_output_file build/libv86.js\
135
+ --define=DEBUG=false\
136
+ $(CLOSURE_FLAGS)\
137
+ --compilation_level SIMPLE\
138
+ --jscomp_off=missingProperties\
139
+ --output_wrapper ';(function(){%output%}).call(this);'\
140
+ --js $(CORE_FILES)\
141
+ --js $(BROWSER_FILES)\
142
+ --js $(LIB_FILES)
143
+ ls -lh build/libv86.js
144
+
145
+ build/libv86.mjs: $(CLOSURE) src/*.js lib/*.js src/browser/*.js
146
+ mkdir -p build
147
+ -ls -lh build/libv86.js
148
+ java -jar $(CLOSURE) \
149
+ --js_output_file build/libv86.mjs\
150
+ --define=DEBUG=false\
151
+ $(CLOSURE_FLAGS)\
152
+ --compilation_level SIMPLE\
153
+ --jscomp_off=missingProperties\
154
+ --output_wrapper ';let module = {exports:{}}; %output%; export default module.exports.V86; export let {V86, CPU} = module.exports;'\
155
+ --js $(CORE_FILES)\
156
+ --js $(BROWSER_FILES)\
157
+ --js $(LIB_FILES)\
158
+ --chunk_output_type=ES_MODULES\
159
+ --emit_use_strict=false
160
+ ls -lh build/libv86.mjs
161
+
162
+ build/libv86-debug.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js
163
+ mkdir -p build
164
+ java -jar $(CLOSURE) \
165
+ --js_output_file build/libv86-debug.js\
166
+ --define=DEBUG=true\
167
+ $(CLOSURE_FLAGS)\
168
+ $(CLOSURE_READABLE)\
169
+ --compilation_level SIMPLE\
170
+ --jscomp_off=missingProperties\
171
+ --output_wrapper ';(function(){%output%}).call(this);'\
172
+ --js $(CORE_FILES)\
173
+ --js $(BROWSER_FILES)\
174
+ --js $(LIB_FILES)
175
+
176
+ build/libv86-debug.mjs: $(CLOSURE) src/*.js lib/*.js src/browser/*.js
177
+ mkdir -p build
178
+ java -jar $(CLOSURE) \
179
+ --js_output_file build/libv86-debug.mjs\
180
+ --define=DEBUG=true\
181
+ $(CLOSURE_FLAGS)\
182
+ --compilation_level SIMPLE\
183
+ --jscomp_off=missingProperties\
184
+ --output_wrapper ';let module = {exports:{}}; %output%; export default module.exports.V86; export let {V86, CPU} = module.exports;'\
185
+ --js $(CORE_FILES)\
186
+ --js $(BROWSER_FILES)\
187
+ --js $(LIB_FILES)\
188
+ --chunk_output_type=ES_MODULES\
189
+ --emit_use_strict=false
190
+ ls -lh build/libv86-debug.mjs
191
+
192
+ src/rust/gen/jit.rs: $(JIT_DEPENDENCIES)
193
+ ./gen/generate_jit.js --output-dir build/ --table jit
194
+ src/rust/gen/jit0f.rs: $(JIT_DEPENDENCIES)
195
+ ./gen/generate_jit.js --output-dir build/ --table jit0f
196
+
197
+ src/rust/gen/interpreter.rs: $(INTERPRETER_DEPENDENCIES)
198
+ ./gen/generate_interpreter.js --output-dir build/ --table interpreter
199
+ src/rust/gen/interpreter0f.rs: $(INTERPRETER_DEPENDENCIES)
200
+ ./gen/generate_interpreter.js --output-dir build/ --table interpreter0f
201
+
202
+ src/rust/gen/analyzer.rs: $(ANALYZER_DEPENDENCIES)
203
+ ./gen/generate_analyzer.js --output-dir build/ --table analyzer
204
+ src/rust/gen/analyzer0f.rs: $(ANALYZER_DEPENDENCIES)
205
+ ./gen/generate_analyzer.js --output-dir build/ --table analyzer0f
206
+
207
+ build/v86.wasm: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml
208
+ mkdir -p build/
209
+ -BLOCK_SIZE=K ls -l build/v86.wasm
210
+ cargo rustc --release $(CARGO_FLAGS)
211
+ cp build/wasm32-unknown-unknown/release/v86.wasm build/v86.wasm
212
+ -$(WASM_OPT) && wasm-opt -O2 --strip-debug build/v86.wasm -o build/v86.wasm
213
+ BLOCK_SIZE=K ls -l build/v86.wasm
214
+
215
+ build/v86-debug.wasm: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml
216
+ mkdir -p build/
217
+ -BLOCK_SIZE=K ls -l build/v86-debug.wasm
218
+ cargo rustc $(CARGO_FLAGS)
219
+ cp build/wasm32-unknown-unknown/debug/v86.wasm build/v86-debug.wasm
220
+ BLOCK_SIZE=K ls -l build/v86-debug.wasm
221
+
222
+ build/v86-fallback.wasm: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml
223
+ mkdir -p build/
224
+ cargo rustc --release $(CARGO_FLAGS_SAFE)
225
+ cp build/wasm32-unknown-unknown/release/v86.wasm build/v86-fallback.wasm || true
226
+
227
+ debug-with-profiler: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml
228
+ mkdir -p build/
229
+ cargo rustc --features profiler $(CARGO_FLAGS)
230
+ cp build/wasm32-unknown-unknown/debug/v86.wasm build/v86-debug.wasm || true
231
+
232
+ with-profiler: $(RUST_FILES) build/softfloat.o build/zstddeclib.o Cargo.toml
233
+ mkdir -p build/
234
+ cargo rustc --release --features profiler $(CARGO_FLAGS)
235
+ cp build/wasm32-unknown-unknown/release/v86.wasm build/v86.wasm || true
236
+
237
+ watch:
238
+ cargo watch -x 'rustc $(CARGO_FLAGS)' -s 'cp build/wasm32-unknown-unknown/debug/v86.wasm build/v86-debug.wasm'
239
+
240
+ build/softfloat.o: lib/softfloat/softfloat.c
241
+ mkdir -p build
242
+ clang -c -Wall \
243
+ --target=wasm32 -O3 -flto -nostdlib -fvisibility=hidden -ffunction-sections -fdata-sections \
244
+ -DSOFTFLOAT_FAST_INT64 -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 -DSOFTFLOAT_FAST_DIV64TO32 \
245
+ -o build/softfloat.o \
246
+ lib/softfloat/softfloat.c
247
+
248
+ build/zstddeclib.o: lib/zstd/zstddeclib.c
249
+ mkdir -p build
250
+ clang -c -Wall \
251
+ --target=wasm32 -O3 -flto -nostdlib -fvisibility=hidden -ffunction-sections -fdata-sections \
252
+ -DZSTDLIB_VISIBILITY="" \
253
+ -o build/zstddeclib.o \
254
+ lib/zstd/zstddeclib.c
255
+
256
+ clean:
257
+ -rm build/libv86.js
258
+ -rm build/libv86.mjs
259
+ -rm build/libv86-debug.js
260
+ -rm build/libv86-debug.mjs
261
+ -rm build/v86_all.js
262
+ -rm build/v86.wasm
263
+ -rm build/v86-debug.wasm
264
+ -rm $(INSTRUCTION_TABLES)
265
+ -rm build/*.map
266
+ -rm build/*.wast
267
+ -rm build/*.o
268
+ $(MAKE) -C $(NASM_TEST_DIR) clean
269
+
270
+ run:
271
+ python3 -m http.server 2> /dev/null
272
+
273
+ update_version:
274
+ set -e ;\
275
+ COMMIT=`git log --format="%h" -n 1` ;\
276
+ DATE=`git log --date="format:%b %e, %Y %H:%m" --format="%cd" -n 1` ;\
277
+ SEARCH='<code>Version: <a id="version" href="https://github.com/copy/v86/commits/[a-f0-9]\+">[a-f0-9]\+</a> ([^(]\+)</code>' ;\
278
+ REPLACE='<code>Version: <a id="version" href="https://github.com/copy/v86/commits/'$$COMMIT'">'$$COMMIT'</a> ('$$DATE')</code>' ;\
279
+ sed -i "s@$$SEARCH@$$REPLACE@g" index.html ;\
280
+ SEARCH='<script src="build/v86_all.js?[a-f0-9]\+"></script>' ;\
281
+ REPLACE='<script src="build/v86_all.js?'$$COMMIT'"></script>' ;\
282
+ sed -i "s@$$SEARCH@$$REPLACE@g" index.html ;\
283
+ grep $$COMMIT index.html
284
+
285
+
286
+ $(CLOSURE):
287
+ mkdir -p $(CLOSURE_DIR)
288
+ # don't upgrade until https://github.com/google/closure-compiler/issues/3972 is fixed
289
+ wget -nv -O $(CLOSURE) https://repo1.maven.org/maven2/com/google/javascript/closure-compiler/v20210601/closure-compiler-v20210601.jar
290
+
291
+ build/integration-test-fs/fs.json: images/buildroot-bzimage68.bin
292
+ mkdir -p build/integration-test-fs/flat
293
+ cp images/buildroot-bzimage68.bin build/integration-test-fs/bzImage
294
+ touch build/integration-test-fs/initrd
295
+ cd build/integration-test-fs && tar cfv fs.tar bzImage initrd
296
+ ./tools/fs2json.py build/integration-test-fs/fs.tar --out build/integration-test-fs/fs.json
297
+ ./tools/copy-to-sha256.py build/integration-test-fs/fs.tar build/integration-test-fs/flat
298
+ rm build/integration-test-fs/fs.tar build/integration-test-fs/bzImage build/integration-test-fs/initrd
299
+
300
+ tests: build/v86-debug.wasm build/integration-test-fs/fs.json
301
+ LOG_LEVEL=3 ./tests/full/run.js
302
+
303
+ tests-release: build/libv86.js build/v86.wasm build/integration-test-fs/fs.json
304
+ TEST_RELEASE_BUILD=1 ./tests/full/run.js
305
+
306
+ nasmtests: build/v86-debug.wasm
307
+ $(NASM_TEST_DIR)/create_tests.js
308
+ $(NASM_TEST_DIR)/gen_fixtures.js
309
+ $(NASM_TEST_DIR)/run.js
310
+
311
+ nasmtests-force-jit: build/v86-debug.wasm
312
+ $(NASM_TEST_DIR)/create_tests.js
313
+ $(NASM_TEST_DIR)/gen_fixtures.js
314
+ $(NASM_TEST_DIR)/run.js --force-jit
315
+
316
+ jitpagingtests: build/v86-debug.wasm
317
+ $(MAKE) -C tests/jit-paging test-jit
318
+ ./tests/jit-paging/run.js
319
+
320
+ qemutests: build/v86-debug.wasm
321
+ $(MAKE) -C tests/qemu test-i386
322
+ LOG_LEVEL=3 ./tests/qemu/run.js build/qemu-test-result
323
+ ./tests/qemu/run-qemu.js > build/qemu-test-reference
324
+ diff build/qemu-test-result build/qemu-test-reference
325
+
326
+ qemutests-release: build/libv86.mjs build/v86.wasm
327
+ $(MAKE) -C tests/qemu test-i386
328
+ TEST_RELEASE_BUILD=1 time ./tests/qemu/run.js build/qemu-test-result
329
+ ./tests/qemu/run-qemu.js > build/qemu-test-reference
330
+ diff build/qemu-test-result build/qemu-test-reference
331
+
332
+ kvm-unit-test: build/v86-debug.wasm
333
+ (cd tests/kvm-unit-tests && ./configure && make x86/realmode.flat)
334
+ tests/kvm-unit-tests/run.mjs tests/kvm-unit-tests/x86/realmode.flat
335
+
336
+ kvm-unit-test-release: build/libv86.mjs build/v86.wasm
337
+ (cd tests/kvm-unit-tests && ./configure && make x86/realmode.flat)
338
+ TEST_RELEASE_BUILD=1 tests/kvm-unit-tests/run.mjs tests/kvm-unit-tests/x86/realmode.flat
339
+
340
+ expect-tests: build/v86-debug.wasm build/libwabt.cjs
341
+ make -C tests/expect/tests
342
+ ./tests/expect/run.js
343
+
344
+ devices-test: build/v86-debug.wasm
345
+ ./tests/devices/virtio_9p.js
346
+ ./tests/devices/virtio_console.js
347
+ ./tests/devices/fetch_network.js
348
+ USE_VIRTIO=1 ./tests/devices/fetch_network.js
349
+ ./tests/devices/wisp_network.js
350
+ ./tests/devices/virtio_balloon.js
351
+
352
+ rust-test: $(RUST_FILES)
353
+ env RUSTFLAGS="-D warnings" RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture
354
+ ./tests/rust/verify-wasmgen-dummy-output.js
355
+
356
+ rust-test-intensive:
357
+ QUICKCHECK_TESTS=100000000 make rust-test
358
+
359
+ api-tests: build/v86-debug.wasm
360
+ ./tests/api/clean-shutdown.js
361
+ ./tests/api/state.js
362
+ ./tests/api/reset.js
363
+ ./tests/api/floppy.js
364
+ ./tests/api/cdrom-insert-eject.js
365
+ ./tests/api/serial.js
366
+ ./tests/api/reboot.js
367
+ ./tests/api/pic.js
368
+
369
+ all-tests: eslint kvm-unit-test qemutests qemutests-release jitpagingtests api-tests nasmtests nasmtests-force-jit rust-test tests expect-tests
370
+ # Skipping:
371
+ # - devices-test (hangs)
372
+
373
+ eslint:
374
+ eslint src tests gen lib examples tools
375
+
376
+ rustfmt: $(RUST_FILES)
377
+ cargo fmt --all -- --check --config fn_single_line=true,control_brace_style=ClosingNextLine
378
+
379
+ build/capstone-x86.min.js:
380
+ mkdir -p build
381
+ wget -nv -P build https://github.com/AlexAltea/capstone.js/releases/download/v3.0.5-rc1/capstone-x86.min.js
382
+
383
+ build/libwabt.cjs:
384
+ mkdir -p build
385
+ wget -nv -P build https://github.com/WebAssembly/wabt/archive/1.0.6.zip
386
+ unzip -j -d build/ build/1.0.6.zip wabt-1.0.6/demo/libwabt.js
387
+ mv build/libwabt.js build/libwabt.cjs
388
+ rm build/1.0.6.zip
389
+
390
+ build/xterm.js:
391
+ curl https://cdn.jsdelivr.net/npm/xterm@5.2.1/lib/xterm.min.js > build/xterm.js
392
+ curl https://cdn.jsdelivr.net/npm/xterm@5.2.1/lib/xterm.js.map > build/xterm.js.map
393
+ curl https://cdn.jsdelivr.net/npm/xterm@5.2.1/css/xterm.css > build/xterm.css
394
+
395
+ update-package-json-version:
396
+ git describe --tags --exclude latest | sed 's/-/./' | tr - + | tee build/version
397
+ jq --arg version "$$(cat build/version)" '.version = $$version' package.json > package.json.tmp
398
+ mv package.json.tmp package.json
Readme.md ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [![Join the chat at https://gitter.im/copy/v86](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/copy/v86) or #v86 on [irc.libera.chat](https://libera.chat/)
2
+
3
+ v86 emulates an x86-compatible CPU and hardware. Machine code is translated to
4
+ WebAssembly modules at runtime in order to achieve decent performance. Here's a
5
+ list of emulated hardware:
6
+
7
+ - An x86-compatible CPU. The instruction set is around Pentium 4 level,
8
+ including full SSE3 support. Some features are missing, in particular:
9
+ - Task gates, far calls in protected mode
10
+ - Some 16 bit protected mode features
11
+ - Single stepping (trap flag, debug registers)
12
+ - Some exceptions, especially floating point and SSE
13
+ - Multicore
14
+ - 64-bit extensions
15
+ - A floating point unit (FPU). Calculations are done using the Berkeley
16
+ SoftFloat library and therefore should be precise (but slow). Trigonometric
17
+ and log functions are emulated using 64-bit floats and may be less precise.
18
+ Not all FPU exceptions are supported.
19
+ - A floppy disk controller (8272A).
20
+ - An 8042 Keyboard Controller, PS2. With mouse support.
21
+ - An 8254 Programmable Interval Timer (PIT).
22
+ - An 8259 Programmable Interrupt Controller (PIC).
23
+ - Partial APIC support.
24
+ - A CMOS Real Time Clock (RTC).
25
+ - A generic VGA card with SVGA support and Bochs VBE Extensions.
26
+ - A PCI bus. This one is partly incomplete and not used by every device.
27
+ - An IDE disk controller.
28
+ - A built-in ISO 9660 CD-ROM generator.
29
+ - An NE2000 (RTL8390) PCI network card.
30
+ - Various virtio devices: Filesystem, network and balloon.
31
+ - A SoundBlaster 16 sound card.
32
+
33
+ ## Demos
34
+
35
+ [9front](https://copy.sh/v86/?profile=9front) —
36
+ [Arch Linux](https://copy.sh/v86/?profile=archlinux) —
37
+ [Android-x86 1.6-r2](https://copy.sh/v86?profile=android) —
38
+ [Android-x86 4.4-r2](https://copy.sh/v86?profile=android4) —
39
+ [BasicLinux](https://copy.sh/v86/?profile=basiclinux) —
40
+ [Buildroot Linux](https://copy.sh/v86/?profile=buildroot) —
41
+ [Damn Small Linux](https://copy.sh/v86/?profile=dsl) —
42
+ [ELKS](https://copy.sh/v86/?profile=elks) —
43
+ [FreeDOS](https://copy.sh/v86/?profile=freedos) —
44
+ [FreeBSD](https://copy.sh/v86/?profile=freebsd) —
45
+ [FiwixOS](https://copy.sh/v86/?profile=fiwix) —
46
+ [Haiku](https://copy.sh/v86/?profile=haiku) —
47
+ [SkiffOS](https://copy.sh/v86/?profile=copy/skiffos) —
48
+ [ReactOS](https://copy.sh/v86/?profile=reactos) —
49
+ [Windows 2000](https://copy.sh/v86/?profile=windows2000) —
50
+ [Windows 98](https://copy.sh/v86/?profile=windows98) —
51
+ [Windows 95](https://copy.sh/v86/?profile=windows95) —
52
+ [Windows 1.01](https://copy.sh/v86/?profile=windows1) —
53
+ [MS-DOS 6.22](https://copy.sh/v86/?profile=msdos) —
54
+ [OpenBSD](https://copy.sh/v86/?profile=openbsd) —
55
+ [Oberon](https://copy.sh/v86/?profile=oberon) —
56
+ [KolibriOS](https://copy.sh/v86/?profile=kolibrios) —
57
+ [SkiftOS](https://copy.sh/v86?profile=skift) —
58
+ [QNX](https://copy.sh/v86/?profile=qnx)
59
+
60
+ ## Documentation
61
+
62
+ [How it works](docs/how-it-works.md) —
63
+ [Networking](docs/networking.md) —
64
+ [Alpine Linux guest setup](tools/docker/alpine/) —
65
+ [Arch Linux guest setup](docs/archlinux.md) —
66
+ [Windows NT guest setup](docs/windows-nt.md) —
67
+ [Windows 9x guest setup](docs/windows-9x.md) —
68
+ [9p filesystem](docs/filesystem.md) —
69
+ [Linux rootfs on 9p](docs/linux-9p-image.md) —
70
+ [Profiling](docs/profiling.md) —
71
+ [CPU Idling](docs/cpu-idling.md)
72
+
73
+ ## Compatibility
74
+
75
+ Here's an overview of the operating systems supported in v86:
76
+
77
+ - Linux works pretty well. 64-bit kernels are not supported.
78
+ - [Buildroot](https://buildroot.uclibc.org) can be used to build a minimal image.
79
+ [humphd/browser-vm](https://github.com/humphd/browser-vm) and
80
+ [darin755/browser-buildroot](https://github.com/Darin755/browser-buildroot) have some useful scripts for building one.
81
+ - [SkiffOS](https://github.com/skiffos/SkiffOS/tree/master/configs/browser/v86) (based on Buildroot) can cross-compile a custom image.
82
+ - Ubuntu and other Debian derivatives works up to the latest version that supported i386 (16.04 LTS or 18.04 LTS for some variants).
83
+ - Alpine Linux works. An image can be built from a Dockerfile, see [tools/docker/alpine/](tools/docker/alpine/).
84
+ - Arch Linux 32 works. See [archlinux.md](docs/archlinux.md) for building an image.
85
+ - ReactOS works.
86
+ - FreeDOS, Windows 1.01 and MS-DOS run very well.
87
+ - KolibriOS works.
88
+ - Haiku works.
89
+ - Android-x86 has been tested up to 4.4-r2.
90
+ - Windows 1, 3.x, 95, 98, ME, NT and 2000 work reasonably well.
91
+ - In Windows 2000 and higher the PC type has to be changed from ACPI PC to Standard PC
92
+ - There are some known boot issues ([#250](https://github.com/copy/v86/issues/250), [#433](https://github.com/copy/v86/issues/433), [#507](https://github.com/copy/v86/issues/507), [#555](https://github.com/copy/v86/issues/555), [#620](https://github.com/copy/v86/issues/620), [#645](https://github.com/copy/v86/issues/645))
93
+ - See [Windows 9x guest setup](docs/windows-9x.md)
94
+ - Windows XP, Vista and 8 work under certain conditions (see [#86](https://github.com/copy/v86/issues/86), [#208](https://github.com/copy/v86/issues/208))
95
+ - See [Windows NT guest setup](docs/windows-nt.md)
96
+ - Many hobby operating systems work.
97
+ - 9front works.
98
+ - Plan 9 doesn't work.
99
+ - QNX works.
100
+ - OS/2 doesn't work.
101
+ - FreeBSD works.
102
+ - OpenBSD works with a specific boot configuration. At the `boot>` prompt type
103
+ `boot -c`, then at the `UKC>` prompt `disable mpbios` and `exit`.
104
+ - NetBSD works only with a custom kernel, see [#350](https://github.com/copy/v86/issues/350).
105
+ - SerenityOS works (only 32-bit versions).
106
+ - [SkiftOS](https://skiftos.org/) works.
107
+
108
+ You can get some information on the disk images here: https://github.com/copy/images.
109
+
110
+ ## How to build, run and embed?
111
+
112
+ You need:
113
+
114
+ - make
115
+ - Rust with the wasm32-unknown-unknown target
116
+ - A version of clang compatible with Rust
117
+ - java (for Closure Compiler, not necessary when using `debug.html`)
118
+ - nodejs (a recent version is required, v16.11.1 is known to be working)
119
+ - To run tests: nasm, gdb, qemu-system, gcc, libc-i386 and rustfmt
120
+
121
+ See [tools/docker/test-image/Dockerfile](tools/docker/test-image/Dockerfile)
122
+ for a full setup on Debian or
123
+ [WSL](https://docs.microsoft.com/en-us/windows/wsl/install).
124
+
125
+ - Run `make` to build the debug build (at `debug.html`).
126
+ - Run `make all` to build the optimized build (at `index.html`).
127
+ - ROM and disk images are loaded via XHR, so if you want to try out `index.html`
128
+ locally, make sure to serve it from a local webserver. You can use `make run`
129
+ to serve the files using Python's http module.
130
+ - If you only want to embed v86 in a webpage you can use libv86.js. For usage,
131
+ check out the [examples](examples/). You can download it from the release section.
132
+
133
+ ### Alternatively, to build using Docker
134
+
135
+ - If you have Docker installed, you can run the whole system inside a container.
136
+ - See `tools/docker/exec` to find the Dockerfile required for this.
137
+ - You can run `docker build -f tools/docker/exec/Dockerfile -t v86:alpine-3.19 .` from the root directory to generate docker image.
138
+ - Then you can simply run `docker run -it -p 8000:8000 v86:alpine-3.19` to start the server.
139
+ - Check `localhost:8000` for hosted server.
140
+
141
+ ### Running via Dev Container
142
+
143
+ - If you are using an IDE that supports Dev Containers, such as GitHub Codespaces, the Visual Studio Code Remote Container extension, or possibly others such as Jetbrains' IntelliJ IDEA, you can setup the development environment in a Dev Container.
144
+ - Follow the instructions from your development environment to setup the container.
145
+ - Run the Task "Fetch images" in order to download images for testing.
146
+
147
+ ## Testing
148
+
149
+ The disk images for testing are not included in this repository. You can
150
+ download them directly from the website using:
151
+
152
+ `curl --compressed --output-dir images/ --remote-name-all https://i.copy.sh/{linux.iso,linux3.iso,linux4.iso,buildroot-bzimage68.bin,TinyCore-11.0.iso,oberon.img,msdos.img,openbsd-floppy.img,kolibri.img,windows101.img,os8.img,freedos722.img,mobius-fd-release5.img,msdos622.img}`
153
+
154
+ Run integration tests: `make tests`
155
+
156
+ Run all tests: `make jshint rustfmt kvm-unit-test nasmtests nasmtests-force-jit expect-tests jitpagingtests qemutests rust-test tests`
157
+
158
+ See [tests/Readme.md](tests/Readme.md) for more information.
159
+
160
+ ## API examples
161
+
162
+ - [Basic](examples/basic.html)
163
+ - [Programatically using the serial terminal](examples/serial.html)
164
+ - [A Lua interpreter](examples/lua.html)
165
+ - [Two instances in one window](examples/two_instances.html)
166
+ - [Networking between browser windows/tabs using the Broadcast Channel API](examples/broadcast-network.html)
167
+ - [TCP Terminal (fetch-based networking)](examples/tcp_terminal.html)
168
+ - [Saving and restoring emulator state](examples/save_restore.html)
169
+
170
+ Using v86 for your own purposes is as easy as:
171
+
172
+ ```javascript
173
+ var emulator = new V86({
174
+ screen_container: document.getElementById("screen_container"),
175
+ bios: {
176
+ url: "../../bios/seabios.bin",
177
+ },
178
+ vga_bios: {
179
+ url: "../../bios/vgabios.bin",
180
+ },
181
+ cdrom: {
182
+ url: "../../images/linux.iso",
183
+ },
184
+ autostart: true,
185
+ });
186
+ ```
187
+
188
+ See [starter.js](src/browser/starter.js).
189
+
190
+ ## License
191
+
192
+ v86 is distributed under the terms of the Simplified BSD License, see
193
+ [LICENSE](LICENSE). The following third-party dependencies are included in the
194
+ repository under their own licenses:
195
+
196
+ - [`lib/softfloat/softfloat.c`](lib/softfloat/softfloat.c)
197
+ - [`lib/zstd/zstddeclib.c`](lib/zstd/zstddeclib.c)
198
+ - [`tests/kvm-unit-tests/`](tests/kvm-unit-tests)
199
+ - [`tests/qemutests/`](tests/qemutests)
200
+ - [`src/floppy.js/`](src/floppy.js) contains parts ported from qemu under the MIT license, see LICENSE.MIT.
201
+
202
+ ## Credits
203
+
204
+ - CPU test cases via [QEMU](https://wiki.qemu.org/Main_Page)
205
+ - More tests via [kvm-unit-tests](https://www.linux-kvm.org/page/KVM-unit-tests)
206
+ - [zstd](https://github.com/facebook/zstd) support is included for better compression of state images
207
+ - [Berkeley SoftFloat](http://www.jhauser.us/arithmetic/SoftFloat.html) is included to precisely emulate 80-bit floating point numbers
208
+ - [The jor1k project](https://github.com/s-macke/jor1k) for 9p, filesystem and uart drivers
209
+ - [WinWorld](https://winworldpc.com/) sources of some old operating systems
210
+ - [OS/2 Museum](https://www.os2museum.com/) sources of some old operating systems
211
+ - [ArchiveOS](https://archiveos.org/) sources of several operating systems
212
+
213
+ ## More questions?
214
+
215
+ Shoot me an email to `copy@copy.sh`. Please report bugs on GitHub.
bios/.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ *.gz
bios/COPYING.LESSER ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
bios/bochs-bios.bin ADDED
Binary file (65.5 kB). View file
 
bios/bochs-vgabios.bin ADDED
Binary file (43 kB). View file
 
bios/fetch-and-build-seabios.sh ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ set -e
2
+ git clone https://git.seabios.org/seabios.git || true
3
+ (cd seabios && git checkout rel-1.16.2)
4
+
5
+ cp seabios.config seabios/.config
6
+ make -C seabios
7
+ cp seabios/out/bios.bin seabios.bin
8
+ cp seabios/out/vgabios.bin vgabios.bin
9
+
10
+ cp seabios-debug.config seabios/.config
11
+ make -C seabios
12
+ cp seabios/out/bios.bin seabios-debug.bin
13
+ cp seabios/out/vgabios.bin vgabios-debug.bin
bios/seabios-debug.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:24174391d6612384bfaabe315d5b8405b16740a37bfd69367dc37fc321bcde1a
3
+ size 262144
bios/seabios-debug.config ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Automatically generated file; DO NOT EDIT.
3
+ # SeaBIOS Configuration
4
+ #
5
+
6
+ #
7
+ # General Features
8
+ #
9
+ # CONFIG_COREBOOT is not set
10
+ CONFIG_QEMU=y
11
+ # CONFIG_CSM is not set
12
+ CONFIG_QEMU_HARDWARE=y
13
+ CONFIG_XEN=y
14
+ CONFIG_THREADS=y
15
+ # CONFIG_RELOCATE_INIT is not set
16
+ # CONFIG_BOOTMENU is not set
17
+ CONFIG_BOOTORDER=y
18
+ CONFIG_HOST_BIOS_GEOMETRY=y
19
+ CONFIG_ENTRY_EXTRASTACK=y
20
+ CONFIG_MALLOC_UPPERMEMORY=y
21
+ CONFIG_ROM_SIZE=0
22
+
23
+ #
24
+ # Hardware support
25
+ #
26
+ CONFIG_ATA=y
27
+ CONFIG_ATA_DMA=y
28
+ CONFIG_ATA_PIO32=y
29
+ CONFIG_AHCI=y
30
+ CONFIG_SDCARD=y
31
+ CONFIG_VIRTIO_BLK=y
32
+ CONFIG_VIRTIO_SCSI=y
33
+ CONFIG_PVSCSI=y
34
+ CONFIG_ESP_SCSI=y
35
+ CONFIG_LSI_SCSI=y
36
+ CONFIG_MEGASAS=y
37
+ CONFIG_MPT_SCSI=y
38
+ CONFIG_FLOPPY=y
39
+ CONFIG_FLASH_FLOPPY=y
40
+ # CONFIG_NVME is not set
41
+ CONFIG_PS2PORT=y
42
+ # CONFIG_USB is not set
43
+ CONFIG_SERIAL=y
44
+ # CONFIG_SERCON is not set
45
+ CONFIG_LPT=y
46
+ CONFIG_RTC_TIMER=y
47
+ CONFIG_HARDWARE_IRQ=y
48
+ CONFIG_USE_SMM=y
49
+ CONFIG_CALL32_SMM=y
50
+ CONFIG_MTRR_INIT=y
51
+ CONFIG_PMTIMER=y
52
+ CONFIG_TSC_TIMER=y
53
+
54
+ #
55
+ # BIOS interfaces
56
+ #
57
+ CONFIG_DRIVES=y
58
+ CONFIG_CDROM_BOOT=y
59
+ CONFIG_CDROM_EMU=y
60
+ CONFIG_PCIBIOS=y
61
+ CONFIG_APMBIOS=y
62
+ CONFIG_PNPBIOS=y
63
+ CONFIG_OPTIONROMS=y
64
+ CONFIG_PMM=y
65
+ CONFIG_BOOT=y
66
+ CONFIG_KEYBOARD=y
67
+ CONFIG_KBD_CALL_INT15_4F=y
68
+ CONFIG_MOUSE=y
69
+ CONFIG_S3_RESUME=y
70
+ CONFIG_VGAHOOKS=y
71
+ # CONFIG_DISABLE_A20 is not set
72
+ # CONFIG_WRITABLE_UPPERMEMORY is not set
73
+ CONFIG_TCGBIOS=y
74
+
75
+ #
76
+ # BIOS Tables
77
+ #
78
+ CONFIG_PIRTABLE=y
79
+ CONFIG_MPTABLE=y
80
+ # CONFIG_SMBIOS is not set
81
+ CONFIG_ACPI=y
82
+ CONFIG_ACPI_DSDT=y
83
+ CONFIG_FW_ROMFILE_LOAD=y
84
+ CONFIG_ACPI_PARSE=y
85
+
86
+ #
87
+ # VGA ROM
88
+ #
89
+ # CONFIG_NO_VGABIOS is not set
90
+ # CONFIG_VGA_STANDARD_VGA is not set
91
+ # CONFIG_VGA_CIRRUS is not set
92
+ # CONFIG_VGA_ATI is not set
93
+ CONFIG_VGA_BOCHS=y
94
+ # CONFIG_VGA_GEODEGX2 is not set
95
+ # CONFIG_VGA_GEODELX is not set
96
+ # CONFIG_DISPLAY_BOCHS is not set
97
+ # CONFIG_VGA_RAMFB is not set
98
+ CONFIG_VGA_BOCHS_STDVGA=y
99
+ # CONFIG_VGA_BOCHS_VMWARE is not set
100
+ # CONFIG_VGA_BOCHS_QXL is not set
101
+ # CONFIG_VGA_BOCHS_VIRTIO is not set
102
+ CONFIG_BUILD_VGABIOS=y
103
+ CONFIG_VGA_STDVGA_PORTS=y
104
+ CONFIG_VGA_FIXUP_ASM=y
105
+ CONFIG_VGA_ALLOCATE_EXTRA_STACK=y
106
+ CONFIG_VGA_EXTRA_STACK_SIZE=512
107
+ CONFIG_VGA_VBE=y
108
+ CONFIG_VGA_PCI=y
109
+ CONFIG_OVERRIDE_PCI_ID=y
110
+ CONFIG_VGA_VID=0x1234
111
+ CONFIG_VGA_DID=0x1111
112
+
113
+ #
114
+ # Debugging
115
+ #
116
+ CONFIG_DEBUG_LEVEL=8
117
+ # CONFIG_DEBUG_SERIAL is not set
118
+ # CONFIG_DEBUG_SERIAL_MMIO is not set
119
+ CONFIG_DEBUG_IO=y
bios/seabios.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:73e3f359102e3a9982c35fce98eb7cd08f18303ac7f1ba6ebfbe6cdc1c244d98
3
+ size 131072
bios/seabios.config ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Automatically generated file; DO NOT EDIT.
3
+ # SeaBIOS Configuration
4
+ #
5
+
6
+ #
7
+ # General Features
8
+ #
9
+ # CONFIG_COREBOOT is not set
10
+ CONFIG_QEMU=y
11
+ # CONFIG_CSM is not set
12
+ CONFIG_QEMU_HARDWARE=y
13
+ CONFIG_XEN=y
14
+ CONFIG_THREADS=y
15
+ # CONFIG_RELOCATE_INIT is not set
16
+ # CONFIG_BOOTMENU is not set
17
+ CONFIG_BOOTORDER=y
18
+ CONFIG_HOST_BIOS_GEOMETRY=y
19
+ CONFIG_ENTRY_EXTRASTACK=y
20
+ CONFIG_MALLOC_UPPERMEMORY=y
21
+ CONFIG_ROM_SIZE=0
22
+
23
+ #
24
+ # Hardware support
25
+ #
26
+ CONFIG_ATA=y
27
+ CONFIG_ATA_DMA=y
28
+ CONFIG_ATA_PIO32=y
29
+ CONFIG_AHCI=y
30
+ CONFIG_SDCARD=y
31
+ CONFIG_VIRTIO_BLK=y
32
+ CONFIG_VIRTIO_SCSI=y
33
+ CONFIG_PVSCSI=y
34
+ CONFIG_ESP_SCSI=y
35
+ CONFIG_LSI_SCSI=y
36
+ CONFIG_MEGASAS=y
37
+ CONFIG_MPT_SCSI=y
38
+ CONFIG_FLOPPY=y
39
+ CONFIG_FLASH_FLOPPY=y
40
+ # CONFIG_NVME is not set
41
+ CONFIG_PS2PORT=y
42
+ # CONFIG_USB is not set
43
+ CONFIG_SERIAL=y
44
+ # CONFIG_SERCON is not set
45
+ CONFIG_LPT=y
46
+ CONFIG_RTC_TIMER=y
47
+ CONFIG_HARDWARE_IRQ=y
48
+ CONFIG_USE_SMM=y
49
+ CONFIG_CALL32_SMM=y
50
+ CONFIG_MTRR_INIT=y
51
+ CONFIG_PMTIMER=y
52
+ CONFIG_TSC_TIMER=y
53
+
54
+ #
55
+ # BIOS interfaces
56
+ #
57
+ CONFIG_DRIVES=y
58
+ CONFIG_CDROM_BOOT=y
59
+ CONFIG_CDROM_EMU=y
60
+ CONFIG_PCIBIOS=y
61
+ CONFIG_APMBIOS=y
62
+ CONFIG_PNPBIOS=y
63
+ CONFIG_OPTIONROMS=y
64
+ CONFIG_PMM=y
65
+ CONFIG_BOOT=y
66
+ CONFIG_KEYBOARD=y
67
+ CONFIG_KBD_CALL_INT15_4F=y
68
+ CONFIG_MOUSE=y
69
+ CONFIG_S3_RESUME=y
70
+ CONFIG_VGAHOOKS=y
71
+ # CONFIG_DISABLE_A20 is not set
72
+ # CONFIG_WRITABLE_UPPERMEMORY is not set
73
+ CONFIG_TCGBIOS=y
74
+
75
+ #
76
+ # BIOS Tables
77
+ #
78
+ CONFIG_PIRTABLE=y
79
+ CONFIG_MPTABLE=y
80
+ # CONFIG_SMBIOS is not set
81
+ CONFIG_ACPI=y
82
+ CONFIG_ACPI_DSDT=y
83
+ CONFIG_FW_ROMFILE_LOAD=y
84
+ CONFIG_ACPI_PARSE=y
85
+
86
+ #
87
+ # VGA ROM
88
+ #
89
+ # CONFIG_NO_VGABIOS is not set
90
+ # CONFIG_VGA_STANDARD_VGA is not set
91
+ # CONFIG_VGA_CIRRUS is not set
92
+ # CONFIG_VGA_ATI is not set
93
+ CONFIG_VGA_BOCHS=y
94
+ # CONFIG_VGA_GEODEGX2 is not set
95
+ # CONFIG_VGA_GEODELX is not set
96
+ # CONFIG_DISPLAY_BOCHS is not set
97
+ # CONFIG_VGA_RAMFB is not set
98
+ CONFIG_VGA_BOCHS_STDVGA=y
99
+ # CONFIG_VGA_BOCHS_VMWARE is not set
100
+ # CONFIG_VGA_BOCHS_QXL is not set
101
+ # CONFIG_VGA_BOCHS_VIRTIO is not set
102
+ CONFIG_BUILD_VGABIOS=y
103
+ CONFIG_VGA_STDVGA_PORTS=y
104
+ CONFIG_VGA_FIXUP_ASM=y
105
+ CONFIG_VGA_ALLOCATE_EXTRA_STACK=y
106
+ CONFIG_VGA_EXTRA_STACK_SIZE=512
107
+ CONFIG_VGA_VBE=y
108
+ CONFIG_VGA_PCI=y
109
+ CONFIG_OVERRIDE_PCI_ID=y
110
+ CONFIG_VGA_VID=0x1234
111
+ CONFIG_VGA_DID=0x1111
112
+
113
+ #
114
+ # Debugging
115
+ #
116
+ CONFIG_DEBUG_LEVEL=0
bios/vgabios-debug.bin ADDED
Binary file (39.4 kB). View file
 
bios/vgabios.bin ADDED
Binary file (36.4 kB). View file
 
debug.html ADDED
@@ -0,0 +1,313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
3
+
4
+ <title>v86 (debug)</title>
5
+ <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,interactive-widget=resizes-content">
6
+
7
+ <script src="build/capstone-x86.min.js"></script>
8
+ <script src="build/libwabt.cjs"></script>
9
+ <script type="module" src="src/browser/main.js"></script>
10
+
11
+ <link rel="stylesheet" href="v86.css">
12
+
13
+ <div>
14
+ <div id="boot_options">
15
+ <h4>Debugger</h4>
16
+ <input type="button" value="ReactOS" id="start_reactos">
17
+ <input type="button" value="ReactOS (boot)" id="start_reactos-boot">
18
+ <br>
19
+
20
+ <input type="button" value="MS-DOS" id="start_msdos">
21
+ <input type="button" value="FreeDOS" id="start_freedos">
22
+ <input type="button" value="FreeDOS with FreeGEM" id="start_freegem">
23
+ <br>
24
+
25
+ <input type="button" value="Windows 1.01" id="start_windows1">
26
+ <input type="button" value="Windows 3.0" id="start_windows30">
27
+ <input type="button" value="Windows 3.1" id="start_windows31">
28
+ <input type="button" value="Windows 95" id="start_windows95">
29
+ <input type="button" value="Windows 95 (boot)" id="start_windows95-boot">
30
+ <br>
31
+ <input type="button" value="Windows 98" id="start_windows98">
32
+ <input type="button" value="Windows 98 (boot)" id="start_windows98-boot">
33
+ <input type="button" value="Windows NT 3.1" id="start_windowsnt3">
34
+ <input type="button" value="Windows NT 4.0" id="start_windowsnt4">
35
+ <input type="button" value="Windows 2000" id="start_windows2000">
36
+ <input type="button" value="Windows 2000 (boot)" id="start_windows2000-boot">
37
+ <br>
38
+
39
+ <input type="button" value="Linux 2.6 (Buildroot)" id="start_linux26">
40
+ <input type="button" value="Linux 3.18 (Buildroot)" id="start_linux3">
41
+ <input type="button" value="Linux 4.16 (Buildroot)" id="start_linux4">
42
+ <input type="button" value="Linux 5.6 (Buildroot)" id="start_buildroot">
43
+ <input type="button" value="Tiny Core" id="start_tinycore">
44
+ <input type="button" value="OpenWRT" id="start_openwrt">
45
+ <br>
46
+ <input type="button" value="Arch Linux" id="start_archlinux">
47
+ <input type="button" value="Arch Linux (boot)" id="start_archlinux-boot">
48
+ <input type="button" value="Damn Small Linux" id="start_dsl">
49
+ <br>
50
+
51
+ <input type="button" value="FreeBSD" id="start_freebsd">
52
+ <input type="button" value="FreeBSD (boot)" id="start_freebsd-boot">
53
+ <input type="button" value="OpenBSD" id="start_openbsd">
54
+ <input type="button" value="NetBSD" id="start_netbsd">
55
+ <br>
56
+
57
+ <input type="button" value="Haiku" id="start_haiku">
58
+ <input type="button" value="Haiku (boot)" id="start_haiku-boot">
59
+ <input type="button" value="Minix" id="start_minix">
60
+ <input type="button" value="SerenityOS" id="start_serenity">
61
+ <input type="button" value="QNX" id="start_qnx">
62
+ <input type="button" value="9front" id="start_9front">
63
+ <br>
64
+
65
+ <input type="button" value="Oberon" id="start_oberon">
66
+ <input type="button" value="KolibriOS" id="start_kolibrios">
67
+ <input type="button" value="Solar OS" id="start_solos">
68
+ <input type="button" value="Bootchess" id="start_bootchess">
69
+ <input type="button" value="HelenOS" id="start_helenos">
70
+ <br>
71
+
72
+ <!--
73
+ <hr>
74
+ Restore state: <input type="file" id="restore_state">
75
+ -->
76
+
77
+ <br>
78
+ <hr>
79
+
80
+ <table>
81
+ <tr>
82
+ <td width="350"><label for="cdrom_image">CD image</label></td>
83
+ <td>
84
+ <input type="file" id="cdrom_image">
85
+ </td>
86
+ </tr>
87
+
88
+ <tr>
89
+ <td><label for="floppy_image">Floppy disk image</label></td>
90
+ <td><input type="file" id="fda_image"> or <a id="fda_toggle_empty_disk">create empty floppy disk</a><br></td>
91
+ </tr>
92
+
93
+ <tr>
94
+ <td><label for="floppy_image">Second floppy disk image</label></td>
95
+ <td><input type="file" id="fdb_image"> or <a id="fdb_toggle_empty_disk">create empty floppy disk</a><br></td>
96
+ </tr>
97
+
98
+ <tr>
99
+ <td><label for="hda_image">Hard disk image</label></td>
100
+ <td><input type="file" id="hda_image"> or <a id="hda_toggle_empty_disk">create empty hard disk</a><br></td>
101
+ </tr>
102
+
103
+ <tr>
104
+ <td>Second hard disk image</td>
105
+ <td><input type="file" id="hdb_image"> or <a id="hdb_toggle_empty_disk">create empty hard disk</a><br></td>
106
+ </tr>
107
+
108
+ <tr>
109
+ <td><label for="multiboot_image">Multiboot kernel image (experimental)</label></td>
110
+ <td><input type="file" id="multiboot_image"><br></td>
111
+ </tr>
112
+
113
+ <tr>
114
+ <td><label for="bzimage">Kernel image (bzimage)</label></td>
115
+ <td><input type="file" id="bzimage"><br></td>
116
+ </tr>
117
+ <tr>
118
+ <td><label for="initrd">initrd</label></td>
119
+ <td><input type="file" id="initrd"><br></td>
120
+ </tr>
121
+
122
+ <tr>
123
+ <td><label for="bios">BIOS</label></td>
124
+ <td><input type="file" id="bios"><br></td>
125
+ </tr>
126
+
127
+ <tr>
128
+ <td><label for="vga_bios">VGA BIOS</label></td>
129
+ <td><input type="file" id="vga_bios"><br></td>
130
+ </tr>
131
+
132
+ <tr>
133
+ <td colspan="2"><small>Disk images are not uploaded to the server</small><hr></td>
134
+ </tr>
135
+
136
+ <tr>
137
+ <td><label for="memory_size">Memory size</label></td>
138
+ <td>
139
+ <input id="memory_size" type="number" value="128" min="16" max="2048" step="16"> MB<br>
140
+ </td>
141
+ </tr>
142
+
143
+ <tr>
144
+ <td><label for="vga_memory_size">Video Memory size</label></td>
145
+ <td>
146
+ <input id="vga_memory_size" type="number" value="8" min="1" max="128" step="1"> MB<br>
147
+ </td>
148
+ </tr>
149
+
150
+ <tr>
151
+ <td><label for="relay_url">Networking proxy (leave blank to disable)</label></td>
152
+ <td>
153
+ <input id="relay_url" type="text" value="wss://relay.widgetry.org/">
154
+ </td>
155
+ </tr>
156
+
157
+ <tr>
158
+ <td colspan="2"><hr></td>
159
+ </tr>
160
+
161
+ <tr>
162
+ <td><label for="disable_audio">Disable audio</label></td>
163
+ <td>
164
+ <input id="disable_audio" type="checkbox"><br>
165
+ </td>
166
+ </tr>
167
+
168
+ <tr>
169
+ <td><label for="acpi">Enable ACPI (experimental)</label></td>
170
+ <td>
171
+ <input id="acpi" type="checkbox"><br>
172
+ </td>
173
+ </tr>
174
+
175
+ <tr>
176
+ <td colspan="2"><hr></td>
177
+ </tr>
178
+
179
+ <tr>
180
+ <td><label for="boot_order">Boot order</label></td>
181
+ <td>
182
+ <select id="boot_order">
183
+ <option value="0">Auto</option>
184
+ <option value="213">CD / Floppy / Hard Disk</option>
185
+ <option value="123">CD / Hard Disk / Floppy</option>
186
+ <option value="231">Floppy / CD / Hard Disk</option>
187
+ <option value="321">Floppy / Hard Disk / CD</option>
188
+ <option value="312">Hard Disk / Floppy / CD</option>
189
+ <option value="132">Hard Disk / CD / Floppy</option>
190
+ </select>
191
+ </td>
192
+ </tr>
193
+ </table>
194
+
195
+ <br>
196
+ <button id="start_emulation">Start Emulation</button>
197
+ <br>
198
+ <br>
199
+ </div>
200
+
201
+ <div id="runtime_options" style="display: none">
202
+ <input type="button" value="Dump Registers" id="dump_regs">
203
+ <input type="button" value="Dump GDT/LDT" id="dump_gdt">
204
+ <input type="button" value="Dump IDT" id="dump_idt">
205
+ <input type="button" value="Dump page tables" id="dump_pt">
206
+ <input type="button" value="Dump log" id="dump_log">
207
+ <br>
208
+
209
+ <input type="button" value="Pause" id="run">
210
+ <input type="button" value="Reset" id="reset">
211
+ <input type="button" value="Exit" id="exit">
212
+ <input type="button" value="Send Ctrl-Alt-Del" id="ctrlaltdel">
213
+ <input type="button" value="Send Alt-Tab" id="alttab">
214
+ <input type="button" value="Get floppy image" id="get_fda_image">
215
+ <input type="button" value="Get second floppy image" id="get_fdb_image">
216
+ <input type="button" value="Get hard disk image" id="get_hda_image">
217
+ <input type="button" value="Get second hard disk image" id="get_hdb_image">
218
+ <input type="button" value="Get CD-ROM image" id="get_cdrom_image">
219
+ <input type="button" value="Insert floppy image" id="change_fda_image">
220
+ <input type="button" value="Insert second floppy image" id="change_fdb_image">
221
+ <input type="button" value="Insert CD image" id="change_cdrom_image">
222
+ <input type="button" value="Save State" id="save_state">
223
+ <input type="button" value="Load State" id="load_state"> <input type="file" style="display: none" id="load_state_input">
224
+ <input type="button" value="Memory Dump" id="memory_dump">
225
+ <input type="button" value="Capture network traffic" id="capture_network_traffic">
226
+ <input type="button" value="Disable mouse" id="toggle_mouse">
227
+ <input type="button" value="Lock mouse" id="lock_mouse">
228
+ <input type="button" value="Go fullscreen" id="fullscreen">
229
+ <input type="button" value="Take screenshot" id="take_screenshot">
230
+ <input type="button" value="Mute" id="mute">
231
+ <input type="button" value="Enable theatre mode" id="toggle_theatre">
232
+ <input type="button" style="display: none" value="Enable zoom to fit" id="toggle_zoom_to_fit">
233
+
234
+ <label>
235
+ Scale:
236
+ <input type="number" min="0.25" step="0.25" value="1.0" id="scale" style="width: 50px">
237
+ </label>
238
+ </div>
239
+
240
+ <pre style="margin: 0" id="log_levels"></pre>
241
+ <pre style="display: none" id="loading"></pre>
242
+ <br>
243
+ </div>
244
+
245
+ <div id="screen_container" style="display: none">
246
+ <div id="screen"></div>
247
+ <canvas id="vga"></canvas>
248
+
249
+ <div style="position: absolute; top: 0; z-index: 10">
250
+ <textarea class="phone_keyboard"></textarea>
251
+ </div>
252
+ </div>
253
+
254
+
255
+ <div id="runtime_infos" style="display: none">
256
+ Running: <span id="running_time">0s</span> <br>
257
+ Speed: <span id="speed">0</span> mIPS<br>
258
+ Avg speed: <span id="avg_speed">0</span> mIPS<br>
259
+ <br>
260
+ <div id="info_storage" style="display: none">
261
+ <b>IDE device<span id="ide_type"></span></b><br>
262
+ Sectors read: <span id="info_storage_sectors_read">0</span><br>
263
+ Bytes read: <span id="info_storage_bytes_read">0</span><br>
264
+ Sectors written: <span id="info_storage_sectors_written">0</span><br>
265
+ Bytes written: <span id="info_storage_bytes_written">0</span><br>
266
+ Status: <span id="info_storage_status"></span><br>
267
+ <br>
268
+ </div>
269
+ <div id="info_filesystem" style="display: none">
270
+ <b>9p Filesystem</b><br>
271
+ Bytes read: <span id="info_filesystem_bytes_read">0</span><br>
272
+ Bytes written: <span id="info_filesystem_bytes_written">0</span><br>
273
+ <div style="white-space: nowrap; overflow-x: hidden">Last file: <span id="info_filesystem_last_file"></span></div>
274
+ Status: <span id="info_filesystem_status"></span><br>
275
+ <br>
276
+ </div>
277
+ <div id="info_network" style="display: none">
278
+ <b>Network</b><br>
279
+ Bytes received: <span id="info_network_bytes_received">0</span><br>
280
+ Bytes transmitted: <span id="info_network_bytes_transmitted">0</span><br>
281
+ <br>
282
+ </div>
283
+ <b>VGA</b><br>
284
+ Mode: <span id="info_vga_mode"></span><br>
285
+ Resolution: <span id="info_res">-</span><br>
286
+ <br>
287
+ Mouse: <span id="info_mouse_enabled">No</span><br>
288
+ </div>
289
+
290
+ <div id="filesystem_panel" style="display: none">
291
+ <label>
292
+ Send files to emulator<br>
293
+ <input type="file" id="filesystem_send_file" multiple>
294
+ </label>
295
+ <br><br>
296
+ <label>
297
+ Get file from emulator<br>
298
+ <input type="text" id="filesystem_get_file" placeholder="Absolute path">
299
+ </label>
300
+ </div>
301
+
302
+ <div id="debug_panel" style="display: none">
303
+ </div>
304
+
305
+ <br style="clear: both"><br>
306
+
307
+ <textarea spellcheck="false" cols="40" rows="12" id="serial" style="display: none">
308
+ </textarea>
309
+
310
+ <div id="terminal"></div>
311
+
312
+ <input type="button" value="Hide UI" id="toggle_ui" style="display: none">
313
+ <div id="theatre_background" style="display: none"></div>
docs/.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ node_modules
docs/archlinux.md ADDED
@@ -0,0 +1,491 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ See [Alpine setup](../tools/docker/alpine/Readme.md) for a more reliable and
2
+ faster way to automatically build Linux images for v86.
3
+
4
+ (This document partly also applies to other Linuxes)
5
+
6
+ Choosing an installer ISO
7
+ -------------------------
8
+
9
+ Download Arch Linux 32 from https://archlinux32.org.
10
+
11
+ Basic installation using QEMU
12
+ -----------------------
13
+
14
+ Installing Arch Linux with these instructions will result in a raw disk image that can be booted by v86.
15
+
16
+ ```sh
17
+ # fetch archlinux32 installer
18
+ wget https://mirror.archlinux32.org/archisos/archlinux32-2021.12.01-i686.iso
19
+
20
+ # Create a 10 gigabyte disk image. If you intend to pacstrap only 'base' then 1.5G should be fine also.
21
+ qemu-img create arch.img 10G
22
+
23
+ # Follow the normal installation process (you can add accel=kvm if your system supports it to speed up the installation)
24
+ qemu-system-x86_64 -m 256 -drive file=arch.img,format=raw -cdrom archlinux32-2021.12.01-i686.iso
25
+ ```
26
+
27
+ For keyboard support, it is necessary to open /etc/mkinitcpio.conf and edit the following line:
28
+
29
+ ```sh
30
+ MODULES="atkbd i8042"
31
+ ```
32
+
33
+ For the changes to take effect, you need to regenerate the initial ramdisk with `mkinitcpio -p linux`
34
+
35
+ The resulting `arch.img` file is a bootable disk image for v86.
36
+
37
+ Scripting image creation for v86
38
+ --------------------------------
39
+
40
+ Installing the ISO by hand takes a long time if you intend to recreate the image many times. There are various reasons why you might want to do this more than once. For example: because the emulator is slow you might want to compile any new software release in QEMU which is much faster and then use the resulting image in v86 instead of making the emulator compile the software. Another reason is that the build progress potentially takes long and if you want to do automated builds in parallel to find out what configurations do and don't work you can just throw more computing power at the problem in order to solve it. This example requires that you have `packer`, `qemu` and `kpartx` installed.
41
+
42
+ ### Creating a packer template
43
+
44
+ [Packer](https://www.packer.io/docs/builders/qemu.html) is a tool that lets you boot an ISO in any of multiple emulators (so QEMU in our case) and send pre-scripted keystrokes to bootstrap an SSH server. Once the SSH connection is established a script can be started for further provisioning.
45
+
46
+ Create a template for automating the base installation:
47
+ ```sh
48
+ mkdir -p packer
49
+ cat > packer/template.json << 'EOF'
50
+ {
51
+ "provisioners": [
52
+ {
53
+ "type": "shell",
54
+ "override": {
55
+ "qemu": {
56
+ "scripts": ["scripts/provision.sh"]
57
+ }
58
+ }
59
+ }
60
+ ],
61
+ "builders": [
62
+ {
63
+ "accelerator": "kvm",
64
+ "type": "qemu",
65
+ "boot_command": [
66
+ "<enter><wait30><enteropenssl passwd help<wait10>",
67
+ "dhcpcd<enter><wait5>",
68
+ "echo root:root | chpasswd<enter><wait5>",
69
+ "systemctl start sshd<enter>"
70
+ ],
71
+ "headless": true,
72
+ "boot_wait": "10s",
73
+ "disk_size": 1500,
74
+ "disk_interface": "ide",
75
+ "iso_url": "https://mirror.archlinux32.org/archisos/archlinux32-2021.12.01-i686.iso",
76
+ "iso_checksum": "90c6f5aecb095d5578f6c9970539da7c5e9324ec",
77
+ "iso_checksum_type": "sha1",
78
+ "ssh_wait_timeout": "120s",
79
+ "ssh_pty": true,
80
+ "ssh_username": "root",
81
+ "ssh_password": "root",
82
+ "ssh_port": 22,
83
+ "format": "raw",
84
+ "vm_name": "archlinux",
85
+ "disk_detect_zeroes": "unmap",
86
+ "memory": 2048,
87
+ "vnc_bind_address": "0.0.0.0"
88
+ }
89
+ ]
90
+ }
91
+ EOF
92
+ ```
93
+
94
+ You can tweak the options a bit to match your situation. For debugging, you can set `headless` to `false`. That will show you the VNC connection instead of running the `boot_command` in the background. For a `base` pacstrap, using a 2 GB disk image should be sufficient. The `raw` disk format is important. v86 does not read qcow2 images, only raw disk images. If your system does not support KVM (the default accelerator), you can change `"accelerator": "none"` to the settings, in macos you may use `"accelerator": "hvf"`. Other accelerator options can be found [here](https://www.packer.io/docs/builders/qemu.html#accelerator).
95
+
96
+ After gaining SSH connectivity to the VM, packer will run the `scripts/provisioning.sh` script in the guest.
97
+
98
+ ### Creating the Arch Linux installation script
99
+
100
+ Create a script for your Arch Linux installation. This runs in the live Arch Linux environment, so you need to partition the disk, do a pacstrap, and install a bootloader.
101
+ ```sh
102
+ mkdir -p packer/scripts
103
+ ### Write your own or copy paste the example below
104
+ vim packer/scripts/provision.sh
105
+ ```
106
+
107
+ An example script to install Arch Linux with the root mounted using the 9p network filesystem:
108
+ ```sh
109
+ #!/bin/bash
110
+ echo "Creating a GPT partition on /dev/sda1"
111
+ echo -e "g\nn\n\n\n\nw" | fdisk /dev/sda
112
+
113
+ # In case you might want to create a DOS partition instead. It doesn't really matter.
114
+ #echo "Creating a DOS partition on /dev/sda1"
115
+ #echo -e "o\nn\np\n1\n\n\nw" | fdisk /dev/sda
116
+
117
+ echo "Formatting /dev/sda1 to ext4"
118
+ mkfs -t ext4 /dev/sda1
119
+
120
+ echo "Mounting new filesystem"
121
+ mount -t ext4 /dev/sda1 /mnt
122
+
123
+ echo "Create pacman package cache dir"
124
+ mkdir -p /mnt/var/cache/pacman/pkg
125
+
126
+ # We don't want the pacman cache to fill up the image. After reboot whatever tarballs pacman has cached are gone.
127
+ echo "Mount the package cache dir in memory so it doesn't fill up the image"
128
+ mount -t tmpfs none /mnt/var/cache/pacman/pkg
129
+
130
+ echo "Updating archlinux-keyring"
131
+ pacman -Sy archlinux-keyring --noconfirm
132
+
133
+ # uncomment to remove signing if unable to resolve signing errors
134
+ sed -i 's/SigLevel.*/SigLevel = Never/g' /etc/pacman.conf
135
+
136
+ # Install the Arch Linux base system, feel free to add packages you need here
137
+ echo "Performing pacstrap"
138
+ pacstrap -i /mnt base linux dhcpcd curl openssh --noconfirm
139
+
140
+ echo "Writing fstab"
141
+ genfstab -p /mnt >> /mnt/etc/fstab
142
+
143
+ # When the Linux boots we want it to automatically log in on tty1 as root
144
+ echo "Ensuring root autologin on tty1"
145
+ mkdir -p /mnt/etc/systemd/system/getty@tty1.service.d
146
+ cat << 'EOF' > /mnt/etc/systemd/system/getty@tty1.service.d/override.conf
147
+ [Service]
148
+ ExecStart=
149
+ ExecStart=-/usr/bin/agetty --autologin root --noclear %I $TERM
150
+ EOF
151
+
152
+ # This is the tricky part. The current root will be mounted on /dev/sda1 but after we reboot
153
+ # it will try to mount root during boot using the 9p network filesystem. This means the emulator
154
+ # will request all files over the network using XMLHttpRequests from the server. This is great
155
+ # because then you only need to provide the client with a saved state (the memory) and the
156
+ # session will start instantly and load needed files on the fly. This is fast and it saves bandwidth.
157
+ echo "Ensuring root is remounted using 9p after reboot"
158
+ mkdir -p /mnt/etc/initcpio/hooks
159
+ cat << 'EOF' > /mnt/etc/initcpio/hooks/9p_root
160
+ run_hook() {
161
+ mount_handler="mount_9p_root"
162
+ }
163
+
164
+ mount_9p_root() {
165
+ msg ":: mounting '$root' on real root (9p)"
166
+ # Note the host9p. We won't mount /dev/sda1 on root anymore,
167
+ # instead we mount the network filesystem and the emulator will
168
+ # retrieve the files on the fly.
169
+ if ! mount -t 9p host9p "$1"; then
170
+ echo "You are now being dropped into an emergency shell."
171
+ launch_interactive_shell
172
+ msg "Trying to continue (this will most likely fail) ..."
173
+ fi
174
+ }
175
+ EOF
176
+
177
+ echo "Adding initcpio build hook for 9p root remount"
178
+ mkdir -p /mnt/etc/initcpio/install
179
+ cat << 'EOF' > /mnt/etc/initcpio/install/9p_root
180
+ #!/bin/bash
181
+ build() {
182
+ add_runscript
183
+ }
184
+ EOF
185
+
186
+ # We need to load some modules into the kernel for it to play nice with the emulator
187
+ # The atkbd and i8042 modules are for keyboard input in the browser. If you do not
188
+ # want to use the network filesystem you only need these. The 9p, 9pnet and 9pnet_virtio
189
+ # modules are needed for being able to mount 9p network filesystems using the emulator.
190
+ echo "Configure mkinitcpio for 9p"
191
+ sed -i 's/MODULES=()/MODULES=(atkbd i8042 libps2 serio serio_raw psmouse virtio_pci virtio_pci_modern_dev 9p 9pnet 9pnet_virtio fscache netfs)/g' /mnt/etc/mkinitcpio.conf
192
+
193
+ # Because we want to mount the root filesystem over the network during boot, we need to
194
+ # hook into initcpio. If you do not want to mount the root filesystem during boot but
195
+ # only want to mount a 9p filesystem later, you can leave this out. Once the system
196
+ # has been booted you should be able to mount 9p filesystems with mount -t 9p host9p /blabla
197
+ # without this hook.
198
+ sed -i 's/fsck"/fsck 9p_root"/g' /mnt/etc/mkinitcpio.conf
199
+
200
+ # enable ssh password auth and root login
201
+ sed -i 's/#PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config
202
+ sed -i 's/#PasswordAuthentication.*/PasswordAuthentication yes/g' /etc/ssh/sshd_config
203
+
204
+ echo "Writing the installation script"
205
+ cat << 'EOF' > /mnt/bootstrap.sh
206
+ #!/usr/bin/bash
207
+ echo "Re-generate initial ramdisk environment"
208
+ mkinitcpio -p linux
209
+
210
+ # uncomment to remove signing if you are unable to resolve signing errors otherwise
211
+ sed -i 's/SigLevel.*/SigLevel = Never/g' /etc/pacman.conf
212
+
213
+ pacman -S --noconfirm syslinux gptfdisk
214
+ syslinux-install_update -i -a -m
215
+
216
+ # disabling ldconfig to speed up boot (to remove Rebuild dynamic linker cache...)
217
+ # you may want to comment this out
218
+ echo "Disabling ldconfig service"
219
+ systemctl mask ldconfig.service
220
+
221
+ sync
222
+ EOF
223
+
224
+ echo "Chrooting and bootstrapping the installation"
225
+ arch-chroot /mnt bash bootstrap.sh
226
+
227
+
228
+ cat << 'EOF' > /mnt/boot/syslinux/syslinux.cfg
229
+ # Config file for Syslinux -
230
+ # /boot/syslinux/syslinux.cfg
231
+ #
232
+ # Comboot modules:
233
+ # * menu.c32 - provides a text menu
234
+ # * vesamenu.c32 - provides a graphical menu
235
+ # * chain.c32 - chainload MBRs, partition boot sectors, Windows bootloaders
236
+ # * hdt.c32 - hardware detection tool
237
+ # * reboot.c32 - reboots the system
238
+ #
239
+ # To Use: Copy the respective files from /usr/lib/syslinux to /boot/syslinux.
240
+ # If /usr and /boot are on the same file system, symlink the files instead
241
+ # of copying them.
242
+ #
243
+ # If you do not use a menu, a 'boot:' prompt will be shown and the system
244
+ # will boot automatically after 5 seconds.
245
+ #
246
+ # Please review the wiki: https://wiki.archlinux.org/index.php/Syslinux
247
+ # The wiki provides further configuration examples
248
+
249
+ DEFAULT arch
250
+ PROMPT 0 # Set to 1 if you always want to display the boot: prompt
251
+ TIMEOUT 100
252
+
253
+ # Menu Configuration
254
+ # Either menu.c32 or vesamenu32.c32 must be copied to /boot/syslinux
255
+ UI menu.c32
256
+ #UI vesamenu.c32
257
+
258
+ # Refer to http://syslinux.zytor.com/wiki/index.php/Doc/menu
259
+ MENU TITLE Arch Linux
260
+ #MENU BACKGROUND splash.png
261
+ MENU COLOR border 30;44 #40ffffff #a0000000 std
262
+ MENU COLOR title 1;36;44 #9033ccff #a0000000 std
263
+ MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
264
+ MENU COLOR unsel 37;44 #50ffffff #a0000000 std
265
+ MENU COLOR help 37;40 #c0ffffff #a0000000 std
266
+ MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
267
+ MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
268
+ MENU COLOR msg07 37;40 #90ffffff #a0000000 std
269
+ MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
270
+
271
+ # boot sections follow
272
+ #
273
+ # TIP: If you want a 1024x768 framebuffer, add "vga=773" to your kernel line.
274
+ #
275
+ #-*
276
+
277
+ LABEL arch
278
+ MENU LABEL Arch Linux 9p
279
+ LINUX ../vmlinuz-linux
280
+ APPEND root=/dev/sda1 rw quiet
281
+ INITRD ../initramfs-linux.img
282
+
283
+ LABEL arch2
284
+ MENU LABEL Arch Linux Disk
285
+ LINUX ../vmlinuz-linux
286
+ APPEND root=/dev/sda1 rw quiet disablehooks=9p_root
287
+ INITRD ../initramfs-linux.img
288
+
289
+ LABEL hdt
290
+ MENU LABEL HDT (Hardware Detection Tool)
291
+ COM32 hdt.c32
292
+
293
+ LABEL reboot
294
+ MENU LABEL Reboot
295
+ COM32 reboot.c32
296
+
297
+ LABEL poweroff
298
+ MENU LABEL Poweroff
299
+ COM32 poweroff.c32
300
+ EOF
301
+ umount -R /mnt
302
+ ```
303
+
304
+ With the packer template and the script you have enough to create an image that can be booted by v86. But because this example script installs an Arch Linux that wants to mount root over the network with 9p, we need to host that filesystem first. If you do not want to use 9p, you can just run `(cd packer && packer build -force template.json)` to build the image.
305
+
306
+ ### Creating the 9p filesystem
307
+
308
+ Now that we have an image that contains a filesystem, we can convert that filesystem into something we can host on the webserver together with the v86 library.
309
+
310
+ To do so, we need to mount the image once and create a json mapping of the filesystem. The following script shows how to map the filesystem in an automated fashion.
311
+
312
+ Create a script to builds the image and then creates v86 compatible artifacts:
313
+ ```sh
314
+ vim build.sh
315
+ ```
316
+
317
+ Example script:
318
+
319
+ ```sh
320
+ #!/bin/sh
321
+
322
+ SRC=packer
323
+ TARGET=output
324
+
325
+ # build the boxfile from the iso
326
+ (cd $SRC && sudo PACKER_LOG=1 PACKER_LOG_PATH="./packer.log" packer build -force template.json)
327
+
328
+ # test if there is a boxfile where we expected it
329
+ if [ ! -f $SRC/output-qemu/archlinux ]; then
330
+ echo "Looks like something went wrong building the image, maybe try again?"
331
+ exit 1
332
+ fi;
333
+
334
+ # clean up any previous loops and mounts
335
+ echo "Making sure mountpoint is empty"
336
+ LOOP_DEV=$(sudo losetup -f)
337
+
338
+ sudo umount diskmount -f || /bin/true
339
+ sudo kpartx -d $LOOP_DEV || /bin/true
340
+ sudo losetup -d $LOOP_DEV || /bin/true
341
+
342
+ # mount the generated raw image, we do that so we can create
343
+ # a json mapping of it and copy it to host on the webserver
344
+ mkdir -p diskmount
345
+ echo "Mounting the created image so we can convert it to a p9 image"
346
+ sudo losetup $LOOP_DEV $SRC/output-qemu/archlinux
347
+ sudo kpartx -a $LOOP_DEV
348
+ sudo mount /dev/mapper/$(basename $LOOP_DEV)p1 diskmount
349
+
350
+ # make images dir
351
+ mkdir -p $TARGET
352
+ mkdir -p $TARGET/images
353
+ mkdir -p $TARGET/images/arch
354
+
355
+ # map the filesystem to json with fs2json
356
+ sudo ./tools/fs2json.py --out $TARGET/images/fs.json diskmount
357
+ sudo ./tools/copy-to-sha256.py diskmount $TARGET/images/arch
358
+
359
+ # copy the filesystem and chown to nonroot user
360
+ echo "Copying the filesystem to $TARGET/arch"
361
+ mkdir $TARGET/arch -p
362
+ sudo rsync -q -av diskmount/ $TARGET/arch
363
+ sudo chown -R $(whoami):$(whoami) $TARGET/arch
364
+
365
+ # clean up mount
366
+ echo "Cleaning up mounts"
367
+ sudo umount diskmount -f
368
+ sudo kpartx -d $LOOP_DEV
369
+ sudo losetup -d $LOOP_DEV
370
+
371
+ # Move the image to the images dir
372
+ sudo mv $SRC/output-qemu/archlinux $TARGET/images/arch.img
373
+ ```
374
+
375
+ Given that the packer template and provision.sh is rooted at `packer` (adjust the value of `$SRC` otherwise), run the `build.sh` at root of your `v86` repo:
376
+
377
+ ```
378
+ chmod +x build.sh
379
+ ./build.sh
380
+ ```
381
+
382
+ Generated artifacts are now available for serving from `output`.
383
+
384
+ ### Using the created artifacts in v86
385
+
386
+ Now that we have everything we need to host a server that serves an Arch Linux environment over the network.
387
+
388
+ Create a checkout of v86 and run `make build/libv86.js`.
389
+ We can then edit `examples/arch.html`, we have two options:
390
+
391
+ 1. Boot Arch Linux from the 9p filesystem (generated .bin artifacts at `/output/images/arch`):
392
+
393
+ ```sh
394
+ filesystem: {
395
+ baseurl: "../output/images/arch/",
396
+ basefs: "../output/images/fs.json",
397
+ },
398
+
399
+ bzimage_initrd_from_filesystem: true,
400
+
401
+ cmdline: [
402
+ "rw",
403
+ "root=host9p rootfstype=9p rootflags=trans=virtio,cache=loose",
404
+ ].join(" "),
405
+
406
+ acpi: false,
407
+ autostart: true,
408
+ ```
409
+ 2. Boot the Arch Linux from the qemu raw disk image:
410
+
411
+ ```sh
412
+ hda: {
413
+ url: "../output/images/arch.img",
414
+ # set to true if you want to load it asynchrously during runtime (for this option we need to run a webserver that supports the Range header)
415
+ # NOTE: async: false is slow but proved to be more realiable
416
+ async: false,
417
+
418
+ # This needs to be the size of the raw disk.
419
+ size: 1.5 * 1024 * 1024 * 1024,
420
+ # See the `disk_size` item in the packer template.
421
+ },
422
+
423
+ acpi: false,
424
+ autostart: true,
425
+ ```
426
+
427
+ Next, we need a webserver that supports the Range header. For example [this extension of the SimpleHTTPServer](https://github.com/smgoller/rangehttpserver). At your `v86` root, run:
428
+
429
+ ```sh
430
+ wget https://raw.githubusercontent.com/smgoller/rangehttpserver/master/RangeHTTPServer.py
431
+ python2 RangeHTTPServer.py
432
+ ```
433
+
434
+ Now that the webserver is running, point your browser to `http://localhost:8000/examples/arch.html`. Wait for the Linux to boot. When the system is up, click 'Save state to file'. Your browser will download a `v86state.bin` file. Copy that file to `/your/v86/dir/images`. You can then edit `examples/arch.html` again and add a 'state' key to the `V86` array.
435
+
436
+ ```sh
437
+ initial_state: {
438
+ "url": "http://localhost:8000/images/v86state.bin",
439
+ },
440
+ ```
441
+
442
+ If you refresh `http://localhost:8000/examples/arch.html` you will see that the state is restored instantly and all required files are loaded over the network on the fly.
443
+
444
+ ### Networking
445
+
446
+ The emulator can emulate a network card. For more information [look at the networking documentation](https://github.com/copy/v86/blob/master/docs/networking.md). To set up networking in the VM, add the following item to the `V86` array in the `examples/arch.html` file:
447
+ ```sh
448
+ network_relay_url: "ws://localhost:8080/",
449
+ ```
450
+
451
+ This will make the emulator try to connect to a [WebSockets proxy](https://github.com/benjamincburns/websockproxy). Running the proxy is very easy if you use the Docker container.
452
+
453
+ ```sh
454
+ sudo docker run --privileged -p 8080:80 --name relay bennottelling/websockproxy
455
+ ```
456
+ **NOTE:** original `benjamincburns/jor1k-relay:latest` has throttling built-in by default which will degrade the networking. `bennottelling/websockproxy` has this throttling removed via [websockproxy/issues/4#issuecomment-317255890](https://github.com/benjamincburns/websockproxy/issues/4#issuecomment-317255890).
457
+
458
+ You can check if the relay is running correctly by going to `http://localhost:8080/` in your browser. There you should see a message that reads `Can "Upgrade" only to "Websocket".`.
459
+
460
+ Now you should be able to get network connectivity in the virtual machine. If you are restoring from a saved state, you might need to first run:
461
+ ```sh
462
+ ip link set enp0s5 down
463
+ rmmod ne2k-pci
464
+ ```
465
+
466
+ To bring the network up, run:
467
+ ```sh
468
+ modprobe ne2k-pci
469
+ dhcpcd -w4 enp0s5
470
+ ```
471
+
472
+ It might take a while for a carrier to become available on the interface. If the `dhcpcd` command fails shortly after booting, wait a bit and try again a bit later. If you are using the 9p network filesystem you can use the developer tools networking tab (in chrome) to get a sense of what is going on by looking at the files that are being downloaded.
473
+
474
+ When the network is up you should be able to curl a website. To check, run `curl icanhazip.com`. There you should see the public IP of the machine running the proxy.
475
+
476
+ You can't do inbound traffic into the VM with the websockproxy Docker container because it uses a basic NAT. To SSH into the VM running in the browser, you can create a reverse SSH tunnel to expose the SSH port of the sshd in the VM to the outside world. You may need to start `sshd` first, it may also be reasonable to change root password:
477
+
478
+ ```sh
479
+ passwd root
480
+ systemctl start sshd
481
+ ```
482
+
483
+ then create a reverse SSH tunnel:
484
+
485
+ ```sh
486
+ # This will create a port 1122 on the example.com server
487
+ # which forwards to the SSH in the VM
488
+ ssh root@example.com -R 1122:localhost:22
489
+ ```
490
+
491
+ Now on the `example.com` server you should be able to SSH into your browser tab by running `ssh root@localhost -p 1122`.
docs/cpu-idling.md ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Some operating systems don't support `hlt` instruction, because of this, the CPU spin loops instead of idling.
2
+ Here are some solutions for different OSes:
3
+
4
+ ## MS-DOS (using DOSIdle)
5
+ 1. Download `DOSID251.zip` from https://www.vogons.org/viewtopic.php?p=438763#p438763
6
+ 2. Unzip DOSIDLE.EXE from archive in any location (recommended to root of C:).
7
+ 3. Run `edit C:\autoexec.bat`
8
+ 4. Add to file: `C:\path\to\dosidle.exe`
9
+ 5. Save changes (*press Alt + F and x*) and restart the VM.
10
+
11
+ **Note:** To hide output when starting DOSIdle, change `C:\path\to\dosidle.exe` to `C:\path\to\dosidle.exe > nul` on step №4.
12
+
13
+ ## FreeDOS ([source](https://narkive.com/UGrcO8wU.2))
14
+ 1. Run `edit C:\fdconfig.sys` (or `edit C:\config.sys`)
15
+ 2. Add to file: `IDLEHALT=1`
16
+ 3. Save changes (*press Alt + F and x*) and restart FreeDOS.
17
+
18
+ ## Windows 9x (using AmnHLT)
19
+ 1. Download `amnhltm.zip` from http://toogam.com/software/archive/drivers/cpu/cpuidle/amnhltm.zip ([mirror](https://web.archive.org/web/20060212132151/http://www.user.cityline.ru/~maxamn/amnhltm.zip))
20
+ 2. Unzip the archive in any location.
21
+ 3. **Note**: If you have installed VBE9x, restart Windows, press F8 on boot, select *Command prompt only*, run `cd C:\path\to\amnhlt\`, and follow to the next step.
22
+ 4. Run `AMNHLT.BAT`
23
+ 5. Restart Windows, and AmnHLT will start automatically on next boot (you can safely delete archive and unpacked folder).
24
+
25
+ ## Windows 98+ and Unix-like
26
+ These systems are already supports `hlt`, no further action is required.
docs/filesystem.md ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ A 9p filesystem is supported by v86, using a virtio transport. There are several
2
+ ways it can be set up.
3
+
4
+ ### Guest mount
5
+
6
+ In all cases, the filesystem is mounted in the guest system using the `9p`
7
+ filesystem type and the `host9p` device tag. Typically you want to be specific
8
+ with the version and transport options:
9
+
10
+ ```sh
11
+ mount -t 9p -o trans=virtio,version=9p2000.L host9p /mnt/9p/
12
+ ```
13
+
14
+ Here are kernel arguments you can use to boot directly off the 9p filesystem:
15
+
16
+ ```
17
+ rw root=host9p rootfstype=9p rootflags=trans=virtio,version=9p2000.L
18
+ ```
19
+
20
+ The `aname` option can be used to pick the directory from 9p to mount. The `rw`
21
+ argument makes this a read-write root filesystem.
22
+
23
+
24
+ ### JSON/HTTP Filesystem
25
+
26
+ This is the standard way to setup the 9p filesystem. It loads files over
27
+ HTTP on-demand into an in-memory filesystem in JS. This allows files to be
28
+ exchanged with the guest OS. See `create_file` and `read_file` in
29
+ [`starter.js`](https://github.com/copy/v86/blob/master/src/browser/starter.js).
30
+
31
+ This mode is enabled by passing the following options to `V86`:
32
+
33
+ ```javascript
34
+ filesystem: {
35
+ basefs: "../9p/fs.json",
36
+ baseurl: "../9p/base/",
37
+ }
38
+ ```
39
+
40
+ Here, `basefs` is a json file created using
41
+ [fs2json.py](tools/fs2json.py) and the `baseurl` directory is created using
42
+ [copy-to-sha256.py](tools/copy-to-sha256.py).
43
+
44
+ If `basefs` and `baseurl` are omitted, an empty 9p filesystem is created. Unless
45
+ you configure one of the alternative modes.
46
+
47
+
48
+ ### Function Handler
49
+
50
+ You can handle 9p messages directly in JavaScript yourself by providing a
51
+ function as `handle9p` under `filesystem`:
52
+
53
+ ```javascript
54
+ filesystem: {
55
+ handle9p: async (reqBuf, reply) => {
56
+ // reqBuf is a Uint8Array of the entire request frame.
57
+ // you can parse these bytes using a library or reading the 9p spec.
58
+ // once you formulate a response, you send the reply frame as a
59
+ // Uint8Array by passing it to reply: reply(respBuf)
60
+ }
61
+ }
62
+ ```
63
+
64
+ This allows you to implement a 9p server or custom proxy in JS. However, this
65
+ filesystem will not be cached (unless cached in the guest OS), functions like
66
+ `create_file` and `read_file` will not be available, and you will be responsible
67
+ for keeping its state in sync with any machine save states.
68
+
69
+
70
+ ### WebSocket Proxy
71
+
72
+ You can also back the 9p virtio filesystem with a 9p server over WebSocket by
73
+ providing a WS proxy URL:
74
+
75
+ ```javascript
76
+ filesystem: {
77
+ proxy_url: "ws://localhost:8080/"
78
+ }
79
+ ```
80
+
81
+ Simlar to using `handle9p`, this filesystem will not be available in JS and
82
+ will need to be re-mounted after restoring state.
83
+
84
+ The WS proxy just needs to hand off messages with a connection to a normal 9p
85
+ server. Each binary WebSocket message is the full buffer of a request or a
86
+ reply.
87
+
88
+ To implement, request message bytes can just be sent directly to the 9p
89
+ connection, but the 9p reply stream needs to be buffered into a single binary
90
+ WebSocket message. The proxy must at least parse the first 4 bytes to get the
91
+ message size and use it to buffer a full message before sending over WebSocket.
92
+
93
+ The [wanix](https://github.com/tractordev/wanix) CLI has a `serve` command that
94
+ not only serves a directory over HTTP, but also over 9P via WebSocket. You can
95
+ see how it [implements a proxy][1] in Go.
96
+
97
+ [1]: https://github.com/tractordev/wanix/blob/main/cmd/wanix/serve.go#L117-L177
docs/how-it-works.md ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Here's an overview of v86's workings. For details, check the
2
+ [source](https://github.com/copy/v86/tree/master/src).
3
+
4
+ The major limitations of WebAssembly are (for the purpose of making emulators with jit):
5
+
6
+ - structured control flow (no arbitrary jumps)
7
+ - no control over registers (you can't keep hardware registers in wasm locals across functions)
8
+ - no mmap (paging needs to be fully emulated)
9
+ - no patching
10
+ - module generation is fairly slow, but at least it's asynchronous, so other things can keep running
11
+ - there is some memory overhead per module, so you can't generate more than a few thousand
12
+
13
+ v86 has an interpreted mode, which collects entry points (targets of function
14
+ calls and indirect jumps). It also measures the hotness per page, so that
15
+ compilation is focused on code that is often executed. Once a page is
16
+ considered hot, code is generated for the entire page and up to `MAX_PAGES`
17
+ that are directly reachable from it.
18
+
19
+ v86 generates a single function with a big switch statement (brtable), to
20
+ ensure that all functions and targets of indirect jumps are reachable from
21
+ other modules. The remaining control flow is handled using the "stackifier"
22
+ algorithm (well-explained in
23
+ [this blog post](https://medium.com/leaningtech/solving-the-structured-control-flow-problem-once-and-for-all-5123117b1ee2)).
24
+ At the moment, there is no linking of wasm modules. The current module is
25
+ exited, and the main loop detects if a new module can be entered.
26
+
27
+ In practice, I found that browsers don't handle this structure (deep brtables,
28
+ with locals being used across the entire function) very well, and `MAX_PAGES`
29
+ has to be set to fairly low, otherwise memory usage blows up. It's likely that
30
+ improvements are possible (generating fewer entry points, splitting code across
31
+ multiple functions).
32
+
33
+ Code-generation happens in two passes. The first pass finds all basic block
34
+ boundaries, the second generates code for each basic block. Instruction
35
+ decoding is generated by a [set of
36
+ scripts](https://github.com/copy/v86/tree/master/gen) from a [table of
37
+ instructions](https://github.com/copy/v86/blob/master/gen/x86_table.js). It's
38
+ also used to [generate
39
+ tests](https://github.com/copy/v86/blob/master/tests/nasm/create_tests.js).
40
+
41
+ To handle paging, v86 generates code similar to this (see `gen_safe_read`):
42
+
43
+ ```
44
+ entry <- tlb[addr >> 12 << 2]
45
+ if entry & MASK == TLB_VALID && (addr & 0xFFF) <= 0xFFC - bytes: goto fast
46
+ entry <- safe_read_jit_slow(addr, instruction_pointer)
47
+ if page_fault: goto exit-with-pagefault
48
+ fast: mem[(entry & ~0xFFF) ^ addr]
49
+ ```
50
+
51
+ There is a 4 MB cache that acts like a tlb. It contains the physical address,
52
+ read-only bit, whether the page contains code (in order to invalidate it on
53
+ write) and whether the page points to mmio. Any of those cases are handled in
54
+ the slow path (`safe_read_jit_slow`), as well as walking the page tables and
55
+ triggering page faults. The fast path is taken in the vast majority of times.
56
+
57
+ The remaining code generation is mostly a straight-forward, 1-to-1 translation
58
+ of x86 to wasm. The only analysis done is to optimise generation of condional
59
+ jumps immediately after arithmetic instructions, e.g.:
60
+
61
+ ```
62
+ cmp eax, 52
63
+ setb eax
64
+ ```
65
+
66
+ becomes:
67
+
68
+ ```
69
+ ... // code for cmp
70
+ eax <- eax < 52
71
+ ```
72
+
73
+ A lazy flag mechanism is used to speed arithmetic (applies to both jit and
74
+ interpreted mode, see
75
+ [`arith.rs`](https://github.com/copy/v86/blob/master/src/rust/cpu/arith.rs) and
76
+ [`misc_instr.rs`](https://github.com/copy/v86/blob/master/src/rust/cpu/misc_instr.rs)).
77
+ There's a wip that tries to elide most lazy-flags updates:
78
+ https://github.com/copy/v86/pull/466
79
+
80
+ FPU instructions are emulated using softfloat (very slow, but unfortunately
81
+ some code relies on 80 bit floats).
docs/linux-9p-image.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ In order to create a Linux image that can mount the 9p file system, add the following lines to the kernel configuration:
2
+
3
+ ```
4
+ CONFIG_NET_9P=y
5
+ CONFIG_NET_9P_VIRTIO=y
6
+ CONFIG_NET_9P_DEBUG=y
7
+ CONFIG_VIRTIO=y
8
+ CONFIG_VIRTIO_PCI=y
9
+ CONFIG_9P_FS=y
10
+ CONFIG_9P_FSCACHE=y
11
+ CONFIG_9P_FS_POSIX_ACL=y
12
+ ```
13
+
14
+ A Dockerfile for this build is here: https://github.com/ysangkok/build-v86-9p-linux
15
+
16
+ Using initcpio
17
+ --------------
18
+
19
+ This allows you to remount the root file system using 9p. No changes are necessary if you only want to mount a 9p filesystem after booting.
20
+
21
+ Add the following files:
22
+
23
+ `/etc/initcpio/hooks/9p_root`
24
+
25
+ ```bash
26
+ #!/usr/bin/bash
27
+
28
+ run_hook() {
29
+ mount_handler="mount_9p_root"
30
+ }
31
+
32
+ mount_9p_root() {
33
+ msg ":: mounting '$root' on real root (9p)"
34
+ if ! mount -t 9p host9p "$1"; then
35
+ echo "You are now being dropped into an emergency shell."
36
+ launch_interactive_shell
37
+ msg "Trying to continue (this will most likely fail) ..."
38
+ fi
39
+ }
40
+ ```
41
+
42
+ <hr>
43
+
44
+ `/etc/initcpio/install/9p_root`
45
+
46
+ ```bash
47
+ #!/bin/bash
48
+ build() {
49
+ add_runscript
50
+ }
51
+ ```
52
+
53
+ Change the following options in `/etc/mkinitcpio.conf`:
54
+
55
+ ```bash
56
+ MODULES="virtio_pci 9p 9pnet 9pnet_virtio"
57
+ HOOKS="base udev autodetect modconf block filesystems keyboard fsck 9p_root" # appended 9p_root
58
+ ```
docs/networking.md ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # v86 networking
2
+
3
+ User guide to networking in v86.
4
+
5
+ ## Introduction
6
+
7
+ On the most basic level, networking in v86 is comprised of two components:
8
+
9
+ * an emulation of the guest's [Network Interface Controller](https://en.wikipedia.org/wiki/Network_interface_controller) (NIC), and
10
+ * a network backend which passes ethernet frames between the NIC and a virtual and/or physical [ethernet network](https://en.wikipedia.org/wiki/Ethernet).
11
+
12
+ There are two **NIC emulations** supported by v86 to chose from, either **`ne2k`** (NE2000/RTL8390-compatible NIC) or **`virtio`** ([VirtIO](http://wiki.osdev.org/Virtio)-compatible device). The right choice simply depends on the driver support in the guest OS, older OSes like FreeDOS only support NE2000, more modern ones usually support VirtIO. In case both are supported by the guest OS it's recommended to try VirtIO first and only fall back to NE2000 if that fails. In some cases it will also be necessary to manually load a driver or similar to activate the NIC and/or networking in the guest OS, yet modern systems usually auto-detect an available NIC during installation and when booting.
13
+
14
+ There are also several **network backends** to chose from which emulate the network that the virtual NIC is connected to, they differ in their requirements and in the degree of network access and services provided to guests. Some provide only limited network access, others full access to a physical network which may include a gateway to the Internet. Backends may require a specific type of proxy server to operate.
15
+
16
+ ### Backend URL schemes
17
+
18
+ The active network backend is configured through a user-specified **backend URL**. Each backend has at least one distinct URL scheme as specified below, where `PROXY` is the DNS hostname or IP address of a compatible proxy server, `PORT` its optional TCP port number (and its default), and `QUERY` is some HTTP query field fragment:
19
+
20
+ | Backend | Backend URL scheme(s) | Example(s) |
21
+ | :------ | :-------------------- | :--------- |
22
+ | **[inbrowser](#the-inbrowser-backend)** | `inbrowser` | `inbrowser` |
23
+ | **[wsproxy](#the-wsproxy-backend)** | `"ws://" PROXY [":" PORT=80] ["/" ...]`<br>`"wss://" PROXY [":" PORT=443] ["/" ...]` | `wss://relay.widgetry.org/` |
24
+ | **[wisp](#the-wisp-backend)** | `"wisp://" PROXY [":" PORT=80] ["/" ...]`<br>`"wisps://" PROXY [":" PORT=443] ["/" ...]` | `wisp://localhost:12345` |
25
+ | **[fetch](#the-fetch-backend)** | `"fetch" [ "://" PROXY [":" PORT] ["/" QUERY] ]` | `fetch`<br>`fetch://localhost:1234/?url=` |
26
+
27
+ Note that `wss://` and `wisps://` are the TLS-secured transports of `ws://` and `wisp://`, respectively.
28
+
29
+ > [!TIP]
30
+ > Since public proxy servers provide only limited bandwidth it is recommended to install and use a local, private proxy server for best results. All proxy servers allow to be executed on the local machine, in a VM running on the local machine, in a local network or even publicly on the Internet (which is generally not recommended, of course). Many proxy servers are distributed as Docker containers which is the recommended way of installing them, otherwise install into a VM.
31
+
32
+ ## Network setup
33
+
34
+ ### Web interface setup
35
+
36
+ Network setup in the v86 web interface at **https://copy.sh/v86/** is straightforward, simply copy the backend URL into the text box named **`Networking proxy`** or select one of the presets to configure the network backend. The guest's NIC emulation (NE2000 or VirtIO) is automatically configured when selecting the guest image in the web interface.
37
+
38
+ ### Embedded v86 setup
39
+
40
+ JavaScript applications that do not use the v86 web interface (but instead embed V86 into their architecture) setup their network by using the common `config` object that they pass to the V86 constructor. Network settings are members of the object **`config.net_device`**, all settings are optional except for `relay_url`.
41
+
42
+ #### General `net_device` settings
43
+
44
+ Common options in `config.net_device`:
45
+
46
+ | net_device | type | description |
47
+ | :------------ | :--- | :--- |
48
+ | **type** | str | The type of emulated NIC provided to the guest OS, either `ne2k` or `virtio`. Default: `ne2k`. |
49
+ | **relay_url** | str | The network backend URL, see [Backend URL schemes](#backend-url-schemes) for details. Note that the CORS proxy server of the `fetch` backend is defined in field `cors_proxy` below. This option is required. |
50
+ | **id** | int | Network id, all v86 network instances with the same id share the same network namespace. Default: `0`.<br>*(TODO: class `NetworkAdapter` should also get options.net_device as an argument, at least options.net_device.id).* |
51
+
52
+ #### Special `net_device` settings
53
+
54
+ Backends `fetch` and `wisp` support a couple of special settings in `config.net_device` to control virtual network components emulated by the backend:
55
+
56
+ | net_device | type | description |
57
+ | :------------- | :--- | :--- |
58
+ | **router_mac** | str | MAC address of virtual network peers (ARP, PING, DHCP, DNS, NTP, UDP echo and TCP peers) in common MAC address notation. Default `52:54:0:1:2:3`. |
59
+ | **router_ip** | str | IP address of virtual network peers (ARP, PING, DHCP, DNS and TCP peers) in dotted IP notation. Default `192.168.86.1`. |
60
+ | **vm_ip** | str | IP address to be assigned to the guest by DHCP in dotted IP notation. Default `192.168.86.100`. |
61
+ | **masquerade** | bool | If `True`, announce `router_ip` as the router's and DNS server's IP addresses in generated DHCP replies, and also generate ARP replies to IPs outside the router's subnet `255.255.255.0`. Default: `True`. |
62
+ | **dns_method** | str | DNS method to use, either `static` or `doh`. `static`: use built-in DNS server, `doh`: use [DNS-over-HTTPS](https://en.wikipedia.org/wiki/DNS_over_HTTPS) (DoH). Defaults to `static` for `fetch` and to `doh` for `wisp` backend. |
63
+ | **doh_server** | str | Host name or IP address (and optional port number) of the DoH server if `dns_method` is `doh`. The value is expanded to the URL `https://DOH_SERVER/dns-query`. Default: `cloudflare-dns.com`. |
64
+ | **cors_proxy** | str | CORS proxy server URL, do not use a proxy if undefined. Default: undefined (`fetch` backend only). |
65
+
66
+ #### Example `net_device` settings
67
+
68
+ * **Example 1:** Provide an emulated NE2000 NIC to the guest OS and use the `wsproxy` backend with a secure wsproxy server at public host `relay.widgetry.org` listening at default TLS port 443:
69
+ ```javascript
70
+ let example_1 = new V86({
71
+ net_device: {
72
+ relay_url: "wss://relay.widgetry.org/"
73
+ },
74
+ // ...
75
+ });
76
+ ```
77
+
78
+ * **Example 2:** Provide a VirtIO NIC to the guest OS and use the `fetch` backend with a CORS proxy server at the local machine listening at port number 23456:
79
+ ```javascript
80
+ let example_2 = new V86({
81
+ net_device: {
82
+ type: "virtio",
83
+ relay_url: "fetch",
84
+ cors_proxy: "https://localhost:23456/?url="
85
+ },
86
+ // ...
87
+ });
88
+ ```
89
+
90
+ ## Network backends
91
+
92
+ One way to compare the different network backends is how they operate on different layers of the TCP/IP Model (see [Wikipedia](https://en.wikipedia.org/wiki/OSI_model#Comparison_with_TCP/IP_model) for a comparison to the OSI model), approximately:
93
+
94
+ Network Peer Backend v86 Guest
95
+
96
+ [ Application ] <---- fetch ----> +-----+ [ Application ]
97
+ [ Transport ] <---- wisp -----> | v86 | [ Transport ]
98
+ [ Network ] | | [ Network ]
99
+ [ Access ] <--- wsproxy ---> +-----+ <---> [ Access ]
100
+ and inbrowser
101
+
102
+ Fig. 1: Network backends in v86
103
+
104
+ v86 guests strictly expect to exchange raw ethernet frames with their (emulated) network card, hence the higher the layer that a v86 network backend operates on the more virtualized the network becomes and the more work has to be done by the backend to fill in for the missing layers.
105
+
106
+ In order to facilitate this for backend implementations, v86 provides helper functions to encode/decode ethernet frames, ARP and IPv4 packets, UDP datagrams, TCP streams and HTTP requests/responses. v86 can also provide minimal but sufficient ARP, ICMP-echo, DHCP, DNS (including DoH) and NTP services to guests.
107
+
108
+ The v86 architecture is open for additional network backend implementations, for a basic example see [examples/two_instances.html](../examples/two_instances.html).
109
+
110
+ ### The `inbrowser` backend
111
+
112
+ This backend provides raw ethernet services for multiple v86 guests running within the same browser process (meaning within the same web page and/or in separate browser tabs). It works standalone without a proxy server, but it also does not provide any access to external networks.
113
+
114
+ The `inbrowser` backend is implemented using the browser-internal [BroadcastChannel](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) API, due to its simplicity it is the most efficient backend, however all VMs have to share the same browser resources.
115
+
116
+ ### The `wsproxy` backend
117
+
118
+ A backend based on a proxy server that provides raw ethernet services to guests using the [WebSocket](https://en.wikipedia.org/wiki/WebSocket) protocol for transport. It depends on the specific proxy server what kind of network configuration it presents to guests, but usually a separate IP subnet with DHCP and DNS services and optional access to the server's physical network and possibly Internet are provided.
119
+
120
+ Since this backend (including its proxy server) only forwards unmodified ethernet frames it is inherently efficient while providing full physical network emulation to guests.
121
+
122
+ **Proxy server**
123
+
124
+ * **[websockproxy](https://github.com/benjamincburns/websockproxy)** -- one TAP device for all clients, integrates dnsmasq for DHCP/DNS, no TLS, original server by benjamincburns
125
+ * Docker container [`benjamincburns/jor1k-relay`](https://hub.docker.com/r/benjamincburns/jor1k-relay) is throttled, see [this comment](https://github.com/benjamincburns/websockproxy/issues/4#issuecomment-317255890)
126
+ * Docker container [`bellenottelling/websockproxy`](https://hub.docker.com/r/bellenottelling/websockproxy) is unthrottled
127
+ * [See here](https://github.com/copy/v86/discussions/1175#discussioncomment-11199254) for step-by-step instructions on how to unthrottle websockproxy manually.
128
+ * **[go-websockproxy](https://github.com/gdm85/go-websockproxy)** -- one TAP device for all clients, written in Go, without integraded DHCP but with integrated TLS support
129
+ * **[node-relay](https://github.com/krishenriksen/node-relay)** -- like websockproxy but written for NodeJS (dnsmasq/no TLS), see [New websocket ethernet switch built using Node.js #777](https://github.com/copy/v86/discussions/777)
130
+ * **[wsnic](https://github.com/chschnell/wsnic)** -- uses a single bridge and one TAP device per client, integrates dnsmasq for DHCP/DNS and stunnel for TLS
131
+
132
+ [See here](https://github.com/copy/v86/discussions/1199#discussioncomment-12026845) for a benchmark comparing the download performance of these proxy servers.
133
+
134
+ ### The `wisp` backend
135
+
136
+ The `wisp` backend implements the client side of the [WISP protocol](https://github.com/MercuryWorkshop/wisp-protocol). WISP is a client/server protocol designed to exchange messages containing UDP and TCP payloads between a WebSocket client and a WISP-compatible proxy server. Note that WISP transports only the packet payloads, not the raw UDP or TCP packets.
137
+
138
+ This backend monitors outbound traffic from guests and wraps/unwraps TCP payload data in WISP messages. A TCP state machine is included to terminate the guest's TCP stream. In addition to the TCP stream, virtual replies to ARP, DHCP, DNS, NTP, ICMP-Ping and UDP-Echo requests from guests are generated (to a certain degree). See PR [#1097](https://github.com/copy/v86/pull/1097) for additional information about this backend.
139
+
140
+ v86 guests are isolated from each other when using the `wisp` backend.
141
+
142
+ **WISP-compatible proxy server**
143
+
144
+ * **[wisp-js](https://www.npmjs.com/package/@mercuryworkshop/wisp-js)**
145
+ * **[epoxy-tls](https://github.com/MercuryWorkshop/epoxy-tls)**
146
+
147
+ > [!NOTE]
148
+ > The WISP protocol only supports UDP and TCP client sockets in the v86 guest, any server sockets listening in the guest are not supported.
149
+
150
+ > [!NOTE]
151
+ > This WISP implementation does not support UDP, only TCP. Once UDP is added, regular DNS over UDP will become the default (instead of DoH), and the builtin NTP and UDP-Echo servers will be removed.
152
+
153
+ ### The `fetch` backend
154
+
155
+ The `fetch` backend uses the browser's [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) API to allow guests to send HTTP requests to external HTTP servers and to receive related HTTP responses. This is however complicated by the fact that browsers add [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) to HTTP requests initiated by `fetch()`, and that they check the CORS headers of related HTTP responses to block access to external web resources not authorized to `fetch()` in the given context.
156
+
157
+ This backend is efficient and very useful in cases where CORS is not in the way, otherwise (and in general) a CORS proxy server must be used to provide access to HTTP servers on the open Internet.
158
+
159
+ Like the [`wisp`](#the-wisp-backend) backend, the `fetch` backend handles DHCP and ARP requests from guests internally, and additionally monitors the guest's outbound traffic for HTTP requests which it translates into calls to `fetch()`. NTP, ICMP pings and UDP echo packets are handled to a certain degree. Note that `fetch()` performs the DNS lookup using the browser's internal DNS client. See PR [#1061](https://github.com/copy/v86/pull/1061) for additional technical details.
160
+
161
+ Starting with PR [#1233](https://github.com/copy/v86/pull/1233), the TCP guest listener can be accessed from JS API, see the [examples/tcp_terminal.html](../examples/tcp_terminal.html) example.
162
+
163
+ v86 guests are isolated from each other when using the `fetch` backend.
164
+
165
+ v86 guests have HTTP access to the host's `localhost` using the URL `http://<port>.external` (e.g. `1234.external` -> `localhost:1234`).
166
+
167
+ **CORS proxy server**
168
+
169
+ * **[cors-anywhere](https://github.com/Rob--W/cors-anywhere)** -- NodeJS
170
+ * **[uncors](https://github.com/chschnell/uncors)** -- A simple PHP-based CORS proxy server for Apache2.
171
+
172
+ > [!TIP]
173
+ > You can pass the following flags to **chromium** to allow browsing without restrictions when using the fetch backend:
174
+ >
175
+ > --disable-web-security --user-data-dir=/tmp/test
176
+ >
177
+ > **NOTE:** This turns off the same-origin policy and should only be used temporarily!
178
+
179
+ ## Related topics
180
+
181
+ ### v86 run-time state images
182
+
183
+ v86 supports saving and restoring the guest's and emulator's run-time state in **state image** files.
184
+
185
+ When restoring a state image, v86 randomises the restored guest's MAC address to make sure that multiple VMs restored from the same state image use different MAC addresses. However, the restored guest OS is unaware that its NIC's MAC address has changed which prevents it from sending and receiving packets correctly. There are several workarounds:
186
+
187
+ - Unload the network driver before saving the state. On Linux, unloading can be
188
+ done using `rmmod ne2k-pci` or `echo 0000:00:05.0 >
189
+ /sys/bus/pci/drivers/ne2k-pci/unbind` and loading (after the state has been
190
+ loaded) using `modprobe ne2k-pci` or `echo 0000:00:05.0 >
191
+ /sys/bus/pci/drivers/ne2k-pci/bind`
192
+ - Pass `preserve_mac_from_state_image: true` to the V86 constructor. This
193
+ causes MAC addresses to be shared between all VMs with the same state image.
194
+ - Pass `mac_address_translation: true` to the V86 constructor. This causes v86
195
+ to present the old MAC address to the guest OS, but translate it to a
196
+ randomised MAC address in outgoing packets (and vice-versa for incoming
197
+ packets). This mechanism currently only supports the ethernet, ipv4, dhcp and
198
+ arp protcols. See `translate_mac_address` in
199
+ [`src/ne2k.js`](https://github.com/copy/v86/blob/master/src/ne2k.js). This is
200
+ currently used in Windows, ReactOS and SerenityOS profiles.
201
+ - Some OSes don't cache the MAC address when the driver loads and therefore
202
+ don't need any of the above workarounds. This seems to be the case for Haiku,
203
+ OpenBSD and FreeBSD.
204
+
205
+ Note that the same applies to IP addresses, so a DHCP client should only be run
206
+ after the state has been loaded.
207
+
208
+ ### NodeJS
209
+
210
+ Network backends `wsproxy` and `wisp` depend on a browser-compatible `WebSocket` constructor being present which is the case since NodeJS v22, backends `inbrowser` and `fetch` should work straightaway.
211
+
212
+ ## Links
213
+
214
+ * [`examples/two_instances.html`](../examples/two_instances.html), example code that shows how to connect two VMs in a web page with a virtual ethernet crossover cable.
215
+ * [`examples/broadcast-network.html`](../examples/broadcast-network.html), example code that shows the raw packet API.
216
+ * [`examples/tcp_terminal.html`](../examples/tcp_terminal.html), example code that shows how to communicate with a guest TCP port on the `fetch` backend.
217
+ * [DC through windows OS for experimental lab #1195](https://github.com/copy/v86/discussions/1195), demonstrates how to setup a Domain Controller for two Windows VMs (XP and Server 2003) using a virtual crossover cable.
218
+ * [Working on a new cross-platform network relay that is a full virtualized network #1064](https://github.com/copy/v86/discussions/1064) (used in [env86 #1085](https://github.com/copy/v86/discussions/1085))
docs/profiling.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ v86 has a built-in profiler, which instruments generated code to count certain
2
+ events and types of instructions. It can be used by building with `make
3
+ debug-with-profiler` and opening debug.html.
4
+
5
+ For debugging networking, packet logging is available in the UI in both debug
6
+ and release builds. The resulting `traffic.hex` file can be loaded in Wireshark
7
+ using file -> import from hex -> tick direction indication, timestamp %s.%f.
docs/sse-shifts.txt ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0F F1 PSLLW mm mm/m64 mmx Shift Packed Data Left Logical
2
+ 66 0F F1 PSLLW xmm xmm/m128 sse2 Shift Packed Data Left Logical
3
+ 0F F2 PSLLD mm mm/m64 mmx Shift Packed Data Left Logical
4
+ 66 0F F2 PSLLD xmm xmm/m128 sse2 Shift Packed Data Left Logical
5
+ 0F F3 PSLLQ mm mm/m64 mmx Shift Packed Data Left Logical
6
+ 66 0F F3 PSLLQ xmm xmm/m128 sse2 Shift Packed Data Left Logical
7
+
8
+ 0F E1 PSRAW mm mm/m64 mmx Shift Packed Data Right Arithmetic
9
+ 66 0F E1 PSRAW xmm xmm/m128 sse2 Shift Packed Data Right Arithmetic
10
+ 0F E2 PSRAD mm mm/m64 mmx Shift Packed Data Right Arithmetic
11
+ 66 0F E2 PSRAD xmm xmm/m128 sse2 Shift Packed Data Right Arithmetic
12
+
13
+ 0F D1 PSRLW mm mm/m64 mmx Shift Packed Data Right Logical
14
+ 66 0F D1 PSRLW xmm xmm/m128 sse2 Shift Packed Data Right Logical
15
+ 0F D2 PSRLD mm mm/m64 mmx Shift Packed Data Right Logical
16
+ 66 0F D2 PSRLD xmm xmm/m128 sse2 Shift Packed Data Right Logical
17
+ 0F D3 PSRLQ mm mm/m64 mmx Shift Packed Data Right Logical
18
+ 66 0F D3 PSRLQ xmm xmm/m128 sse2 Shift Packed Data Right Logical
19
+
20
+ 0F 71 PSRLW mm imm8 mmx Shift Packed Data Right Logical
21
+ 66 0F 71 PSRLW xmm imm8 sse2 Shift Packed Data Right Logical
22
+ 0F 71 PSRAW mm imm8 mmx Shift Packed Data Right Arithmetic
23
+ 66 0F 71 PSRAW xmm imm8 sse2 Shift Packed Data Right Arithmetic
24
+ 0F 71 PSLLW mm imm8 mmx Shift Packed Data Left Logical
25
+ 66 0F 71 PSLLW xmm imm8 sse2 Shift Packed Data Left Logical
26
+
27
+ 0F 72 PSRLD mm imm8 mmx Shift Double Quadword Right Logical
28
+ 66 0F 72 PSRLD xmm imm8 sse2 Shift Double Quadword Right Logical
29
+ 0F 72 PSRAD mm imm8 mmx Shift Packed Data Right Arithmetic
30
+ 66 0F 72 PSRAD xmm imm8 sse2 Shift Packed Data Right Arithmetic
31
+ 0F 72 PSLLD mm imm8 mmx Shift Packed Data Left Logical
32
+ 66 0F 72 PSLLD xmm imm8 sse2 Shift Packed Data Left Logical
33
+
34
+ 0F 73 PSRLQ mm imm8 mmx Shift Packed Data Right Logical
35
+ 66 0F 73 PSRLQ xmm imm8 sse2 Shift Packed Data Right Logical
36
+ 66 0F 73 PSRLDQ xmm imm8 sse2 Shift Double Quadword Right Logical
37
+ 0F 73 PSLLQ mm imm8 mmx Shift Packed Data Left Logical
38
+ 66 0F 73 PSLLQ xmm imm8 sse2 Shift Packed Data Left Logical
39
+ 66 0F 73 PSLLDQ xmm imm8 sse2 Shift Double Quadword Left Logical
docs/windows-9x.md ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Installing using QEMU
2
+
3
+ Recommended versions:
4
+ - Windows 95 OSR2(.5)
5
+ - Windows 98 Second Edition (SE)
6
+
7
+ -------------
8
+
9
+ 1. Create a disk image (up to 2 GB):
10
+ ```sh
11
+ qemu-img create -f raw hdd.img <size in megabytes>M
12
+ ```
13
+ 2. Run QEMU with the following settings:
14
+ ```sh
15
+ qemu-system-i386 -m 128 -M pc,acpi=off -hda hdd.img
16
+ ```
17
+ - add `-cdrom /path/to/installCD.iso`, if you use a CD version.
18
+ - add `-fda /path/to/boot_floppy.img -boot a`, if you use a floppy version or your install CD is non-bootable.
19
+ - (optionally) add `-device sb16` to enable sound
20
+ - (optionally) add `-nic user,model=ne2k_pci` or `-device ne2k_pci,netdev=<...>` to enable networking
21
+
22
+ 3. For Windows 98: select "Start Windows 98 Setup from CD-ROM". For Windows 95: select "Load NEC IDE CDROM driver" and run `fdisk` to create partition, restart emulator, run `format c:` and `D:\WIN95\SETUP`.
23
+
24
+ 4. To change floppy disk, press *Ctrl+Alt+2* to switch to the QEMU Monitor, run `change floppy0 /path/to/new_floppy_image` and press *Ctrl+Alt+1* to switch to VGA.
25
+ 5. Follow the installation guide on the screen.
26
+ 6. (optionally) If "Windows protection" errors appears on startup, apply [FIX95CPU](http://lonecrusader.x10host.com/fix95cpu.html) or [patcher9x](https://github.com/JHRobotics/patcher9x#installation).
27
+
28
+ > [!TIP]
29
+ > For transfer files from host to guest, use [genisoimage](https://wiki.debian.org/genisoimage) ([UltraISO](https://www.ultraiso.com/) and [PowerISO](https://www.poweriso.com/) for Windows and Mac) for creating CD-ISO image or [dosfstools](https://github.com/dosfstools/dosfstools) ([WinImage](https://www.winimage.com/download.htm) for Windows) for creating floppy disk images, then mount the created image to QEMU.
30
+
31
+ ## Floppy disk support
32
+
33
+ Currently, the floppy drive in v86 works only with MS-DOS compatibility mode.
34
+
35
+ To check this: open the Start menu, click on "Control Panel" and "System", select "Performance" tab.
36
+ If it says *"Drive A is using MS-DOS compatibility mode file system"*, the floppy drive should work properly in v86. If not, try this solution:
37
+
38
+ 1. Click on "Device Manager" in "System Properties".
39
+ 2. Open "Floppy disk controllers", select "Standard Floppy Disk Controller" and press "Remove" at the bottom.
40
+ 3. Restart Windows.
41
+
42
+ ## Enabling True Color (32 bpp)
43
+
44
+ The default VGA display driver only supports 640x480x8 video mode, to fix this, install **Universal VBE9x Video Display Driver**.
45
+
46
+ > [!WARNING]
47
+ > After installing, DOS Mode (and other programs and games that require it) may not work properly.
48
+ > This is a problem in VBE9x, not v86, see [#110](https://github.com/copy/v86/issues/110).
49
+ > Also, this driver doesn't support DirectX, DirectDraw and OpenGL.
50
+
51
+ 1. Download driver from https://bearwindows.zcm.com.au/vbe9x.htm and unpack into Windows.
52
+ 2. Right-click on the Desktop, click on "Properties".
53
+ 3. Click "Advanced" > "Adapter" > "Change".
54
+ 4. Press "Next", select "Display a of all the drivers in a specific location..." and press again "Next".
55
+ 5. Press "Have Disk...", click "Browse" and go to folder with unpacked driver. Inside the folder with driver, should be folders like `032mb`, `064mb`, `128mb`. Choose a version based on needed video memory size (for example, `032mb`), then select `vbemp.inf` inside.
56
+ 6. Select "VBE Miniport" adapter, press "OK" and "Next".
57
+ 7. After installing, restart Windows.
58
+
59
+ ## CPU idling on Windows 95
60
+ See about [installing AmnHLT](cpu-idling.md#windows-9x-using-amnhlt).
61
+
62
+ ## Enabling networking on Windows 95 (requires install CD)
63
+
64
+ 1. Open the Start menu, click on "Control Panel" and "Add New Hardware".
65
+ 2. Press "Next", select "No" and select next options:
66
+
67
+ ```
68
+ Hardware type: Network adapters
69
+ Manufacturers: Novell
70
+ Models: NE2000 Compatible
71
+ ```
72
+
73
+ 3. Press "Next" and restart Windows.
74
+ 4. After restarting, right-click on "My computer", select "Propeties".
75
+ 5. Open "Device Manager" tab, select "NE2000 Compatible" (in "Network adapters") and press "Properties"
76
+ 6. Open "Resources", change values by selecting the properties and click on "Change Setting":
77
+
78
+ ```
79
+ Interrupt Request: 10
80
+ Input/Output Range: 0300 - 031F
81
+ ```
82
+
83
+ 7. In "Control Panel", open "Network", click on "Add", choose "Protocol" and select the following options:
84
+
85
+ ```
86
+ Manufacturers: Microsoft
87
+ Network Protocols: TCP/IP
88
+ ```
89
+
90
+ 8. (optionally) Set "Primary Network Logon" to `Windows Logon`.
91
+
92
+ ## Enabling sound manually
93
+
94
+ > [!NOTE]
95
+ > If you don't have an install CD, use the Sound Blaster 16 driver from https://www.claunia.com/qemu/drivers/index.html.
96
+
97
+ 1. Open "Start" menu, click on "Control Panel" and "Add New Hardware".
98
+ 2. Press "Next", select "No" and select the following options:
99
+
100
+ ```
101
+ Hardware type: Sound, video and game cotrollers
102
+ Manufacturers: Creative Labs
103
+ Models: Creative Labs Sound Blaster 16 or AWE-32
104
+ ```
105
+
106
+ 3. Restart Windows.
docs/windows-nt.md ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ - [Windows NT 3.1](#windows-nt-31) / [3.51](#windows-nt-351) / [4.0](#windows-nt-40)
3
+ - [Windows 2000/XP](#windows-2000xp)
4
+ - [Windows Vista and newer](#windows-vista-and-newer)
5
+
6
+ ------------------------
7
+ ## Windows NT 3.1
8
+
9
+ ### Installing using QEMU
10
+
11
+ 1. Install MS-DOS and [Oak CD-ROM Driver](https://www.dosdays.co.uk/topics/Software/optical_downloads.php).
12
+ 2. Create 4 blank floppy disk images:
13
+
14
+ - run `qemu-img create -f raw floppy.img 1440K`
15
+ - mount (`-fda floppy.img`) and run `format A:` in a VM
16
+
17
+ 3. Run QEMU with the following settings for installation:
18
+
19
+ ```sh
20
+ qemu-system-i386 -m 64 -hda hdd.img -cpu pentium -M pc,acpi=off -cdrom InstallCD.iso
21
+ ```
22
+
23
+ 4. Run `xcopy /v <CD-ROM letter>:\I386\ C:\install\` in a VM to copy all files, disable the CD-ROM driver.
24
+ 5. Run QEMU with the following settings:
25
+
26
+ ```sh
27
+ qemu-system-i386 -m 64 -hda hdd.img -cpu pentium -M pc,acpi=off
28
+ ```
29
+
30
+ 6. Run `C:\install\winnt /F /C` in a VM.
31
+ 7. Follow the setup instructions. To change floppy disk, press *Ctrl+Alt+2* to switch to the QEMU Monitor, run `change floppy0 /path/to/new_floppy_image` and press *Ctrl+Alt+1* to switch to VGA.
32
+
33
+
34
+ ## Windows NT 3.51
35
+
36
+ ### Installing
37
+
38
+ > [!NOTE]
39
+ > In newer versions of QEMU, the Windows Setup may not work, you can use an older version of QEMU, PCem, 86Box or PCBox instead.
40
+
41
+ 1. If you install via MS-DOS, install [the Oak CD-ROM Driver](https://www.dosdays.co.uk/topics/Software/optical_downloads.php) and run `<CD-ROM letter>:\I386\WINNT /B`.
42
+ 2. Follow the setup instructions.
43
+ 3. After installing, download NT 3.51 SuperPack ([here](https://bearwindows.zcm.com.au/winnt351.htm#4) or [here](https://alter.org.ua/en/soft/nt_spack/nt3/)), unpack the archive into a Windows and copy files from `FAT32` (`SYS\FAT32`) and `RENEW` (`SYS\RENEW`) folders in `C:\WINNT35\system32\drivers` with replacing.
44
+
45
+ ### Enabling networking
46
+
47
+ 1. Open "Control Panel" > "Network", install Windows NT Networking (installation CD required).
48
+ 2. In "Network Adapter Card Detection", press Continue three times, set `Network Adapter Card: Novell NE2000 Compatible Adapter`.
49
+ 3. Set the following settings and click Continue:
50
+
51
+ ```
52
+ IRQ Level: 10
53
+ I/O Port Address: 0x300
54
+ ```
55
+
56
+ 4. In "Bus Location", press OK. Check the boxes "TCP/IP Transport" and "Enable Automatic DHCP Configuration" in the next window.
57
+ 5. In "TCP/IP Configuration", check the box "Enable Automatic DHCP Configuration".
58
+ 6. Restart the VM.
59
+
60
+
61
+ ## Windows NT 4.0
62
+
63
+ Recommended version: Windows NT 4.0 SP1
64
+
65
+ ### Installing using QEMU
66
+
67
+ 1. Run QEMU with the following settings for installation:
68
+
69
+ ```sh
70
+ qemu-system-i386 -m 64 -hda hdd.img -cdrom InstallCD.iso -cpu pentium -M pc,acpi=off
71
+ ```
72
+
73
+ 2. On setup startup, press F5 and select "Standard PC".
74
+ 3. Follow the setup instructions.
75
+
76
+ ### Running in v86
77
+
78
+ Due to a problem with CPUID, you need to add `cpuid_level: 2` and `acpi: false` to the V86 constructor (not supported in the UI):
79
+
80
+ ```js
81
+ var emulator = new V86({
82
+ ...
83
+ cpuid_level: 2,
84
+ acpi: false
85
+ });
86
+ ```
87
+
88
+
89
+ ## Windows 2000/XP
90
+
91
+ ### Installing using QEMU
92
+
93
+ 1. Run QEMU with the following settings for installation:
94
+
95
+ ```sh
96
+ qemu-system-i386 -m 512 -hda hdd.img -cdrom InstallCD.iso
97
+ ```
98
+
99
+ Optional:
100
+ - add `-device sb16` to enable sound
101
+ - add `-nic user,model=ne2k_pci` or `-device ne2k_pci,netdev=<...>` to enable networking
102
+
103
+ 2. Follow the setup instructions.
104
+ 3. This step fixes the error `Uncaught RangeError: Maximum call stack size exceeded` in Chromium during Windows 2000/XP startup in v86.
105
+
106
+ After installation, change the computer type to "Standard PC" as described [here](http://web.archive.org/web/20220528021535/https://www.scm-pc-card.de/file/manual/FAQ/acpi_uninstallation_windows_xp_english.pdf):
107
+ 1. Open Start menu, right-click on "My Computer", select "Manage"
108
+ 2. Open Device Manager, open Computer, right-click on "ACPI Uniprocessor PC"
109
+ 3. Select "Update Driver..." > "No, not this time"
110
+ 4. Select "Install from a list or specific location (Advanced)" > Next > "Don't search. I will choose the driver to install."
111
+ 5. Choose "Standard PC", press Next > Finish.
112
+ 6. Restart the VM, follow multiple "Found New Hardware Wizard" dialogs with default options.
113
+
114
+ ### Enabling True Color (for Windows 2000)
115
+
116
+ > [!NOTE]
117
+ > This driver doesn't support DirectX, DirectDraw and OpenGL.
118
+
119
+ 1. Download driver from https://bearwindows.zcm.com.au/vbemp.htm and unpack into Windows.
120
+ 2. Open Start menu, right-click on "My Computer", select "Manage"
121
+ 3. Open Device Manager, open Computer and right-click on "Video Controller".
122
+ 4. Press "Properties", select "Driver" tab and press "Update Driver".
123
+ 5. Select "Display a list of the known drivers for this device...", choose "Display adapters".
124
+ 5. Press "Have Disk...", click "Browse" and go to folder with unpacked driver. Go to `VBE20\W2K\PNP`, then select `vbemppnp.inf` inside.
125
+ 6. Select "VBE Miniport" adapter, press "Yes" and "Next".
126
+ 7. After installing, restart the VM.
127
+
128
+ ### Enabling sound
129
+
130
+ *Source: [#1049](https://github.com/copy/v86/issues/1049)*
131
+
132
+ 1. Right-click on "My computer" > "System Properties", select "Hardware" tab, press "Hardware Wizard"
133
+ 2. Press "Next" > "Add/Troubleshoot a device" > "Add a new device"
134
+ 3. Select "No, I want to select the hardware from a list" > "Sound, video and game controllers"
135
+ 4. Select the following options and press "Next":
136
+
137
+ ```
138
+ Hardware type: Sound, video and game cotrollers
139
+ Manufacturers: Creative Technology Ltd.
140
+ Models: Sound Blaster 16 or AWE32 or compatible (WDM)
141
+ ```
142
+
143
+
144
+ ## Windows Vista and newer
145
+
146
+ ### Installing using QEMU
147
+
148
+ 1. Run QEMU with the following settings for installation:
149
+
150
+ ```sh
151
+ qemu-system-i386 -m 1024 -hda hdd.img -cdrom InstallCD.iso
152
+ ```
153
+
154
+ Optionally add `-accel kvm` (for Linux host), `-accel whpx` (for Windows host) or `-accel hvf` (for MacOS host) to use hypervisor acceleration.
155
+
156
+ 2. Follow the setup instructions.
157
+
158
+ ### Running in v86
159
+
160
+ Enable ACPI and set the memory size to 512 MB or more.
161
+
162
+ ### Enabling networking (ne2k)
163
+
164
+ *Source: https://phaq.phunsites.net/2007/05/21/vista-on-xen-using-ne2000-in-favor-to-rtl8139/*
165
+
166
+ 1. Download https://phaq.phunsites.net/files/2007/05/drivercd.iso_.zip, unpack the archive, mount the ISO to the VM (`-cdrom path/to/drivercd.iso` or `change ide1-cd0 path/to/drivercd.iso` in QEMU Monitor), unpack the archive from CDROM into Windows.
167
+ 2. Open Start Menu > "Control Panel" > "System" > "Device Manager"
168
+ 3. Right-click on "Ethernet Controller" > "Update Driver Software", press "Browse my computer for driver software".
169
+ 4. Click "Browse" and go to folder with unpacked driver, select `WIN2000` folder, press "Install this driver software anyway".
eslint.config.mjs ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export default [
2
+ {
3
+ "languageOptions": {
4
+ "globals": {
5
+ "process": "readonly",
6
+ "window": "writable",
7
+ "navigator": "writable",
8
+ "location": "writable",
9
+ "document": "readonly",
10
+ "console": "readonly",
11
+ "crypto": "readonly",
12
+ "alert": "readonly",
13
+ "performance": "readonly",
14
+ "URL": "readonly",
15
+ "WebAssembly": "readonly",
16
+
17
+ "setTimeout": "readonly",
18
+ "setInterval": "readonly",
19
+ "clearTimeout": "readonly",
20
+ "clearInterval": "readonly",
21
+ "requestAnimationFrame": "readonly",
22
+ "cancelAnimationFrame": "readonly",
23
+
24
+ "Buffer": "readonly",
25
+ "FileReader": "readonly",
26
+ "TextEncoder": "readonly",
27
+ "TextDecoder": "readonly",
28
+ "fetch": "readonly",
29
+ "Headers": "readonly",
30
+ "Response": "readonly",
31
+ "WebSocket": "readonly",
32
+ "Blob": "readonly",
33
+ "File": "readonly",
34
+ "XMLHttpRequest": "readonly",
35
+ "URLSearchParams": "readonly",
36
+ "ImageData": "readonly",
37
+ "Image": "readonly",
38
+ "OffscreenCanvas": "readonly",
39
+ "BroadcastChannel": "readonly",
40
+
41
+ "AudioContext": "readonly",
42
+ "AudioWorkletProcessor": "readonly",
43
+ "webkitAudioContext": "readonly",
44
+ "AudioWorkletNode": "readonly",
45
+ "Worker": "readonly",
46
+ "postMessage": "readonly",
47
+ "importScripts": "readonly",
48
+
49
+ "DEBUG": "writable"
50
+ }
51
+ },
52
+ rules: {
53
+ "eol-last": "error",
54
+ //"no-extra-parens": "error",
55
+ "no-trailing-spaces": "error",
56
+ "no-extra-semi": "error",
57
+ "no-tabs": "error",
58
+ "quotes": ["error", "double", { "avoidEscape": true, "allowTemplateLiterals": true }],
59
+ "keyword-spacing": ["error", { "overrides": {
60
+ "if": { "after": false },
61
+ "for": { "after": false },
62
+ "while": { "after": false },
63
+ "switch": { "after": false },
64
+ "catch": { "after": false },
65
+ } }],
66
+ "semi": "error",
67
+ "no-useless-return": "error",
68
+ "eqeqeq": "error",
69
+ "no-multiple-empty-lines": ["error", { "max": 2, "maxBOF": 0, "maxEOF": 0 }],
70
+ //"no-var": "error",
71
+ "radix": "error",
72
+ "comma-style": ["error", "last"],
73
+ //"comma-dangle": ["error", "always-multiline"],
74
+ "no-sequences": "error",
75
+ //"one-var": ["error", "never"],
76
+ "constructor-super": "error",
77
+ "for-direction": "error",
78
+ "getter-return": "error",
79
+ "no-async-promise-executor": "error",
80
+ //"no-case-declarations": "error",
81
+ "no-class-assign": "error",
82
+ "no-compare-neg-zero": "error",
83
+ "no-cond-assign": "error",
84
+ "no-const-assign": "error",
85
+ "no-constant-binary-expression": "error",
86
+ //"no-constant-condition": "error",
87
+ //"no-control-regex": "error",
88
+ //"no-debugger": "error",
89
+ "no-delete-var": "error",
90
+ "no-dupe-args": "error",
91
+ "no-dupe-class-members": "error",
92
+ //"no-dupe-else-if": "error",
93
+ "no-dupe-keys": "error",
94
+ "no-duplicate-case": "error",
95
+ //"no-empty": "error",
96
+ "no-empty-character-class": "error",
97
+ "no-empty-pattern": "error",
98
+ "no-empty-static-block": "error",
99
+ "no-ex-assign": "error",
100
+ "no-extra-boolean-cast": "error",
101
+ "no-fallthrough": "error",
102
+ "no-func-assign": "error",
103
+ "no-global-assign": "error",
104
+ "no-import-assign": "error",
105
+ "no-invalid-regexp": "error",
106
+ "no-irregular-whitespace": "error",
107
+ "no-loss-of-precision": "error",
108
+ "no-misleading-character-class": "error",
109
+ "no-new-native-nonconstructor": "error",
110
+ "no-nonoctal-decimal-escape": "error",
111
+ "no-obj-calls": "error",
112
+ "no-octal": "error",
113
+ "no-prototype-builtins": "error",
114
+ //"no-redeclare": "error",
115
+ "no-regex-spaces": "error",
116
+ "no-self-assign": "error",
117
+ "no-setter-return": "error",
118
+ "no-shadow-restricted-names": "error",
119
+ "no-sparse-arrays": "error",
120
+ "no-this-before-super": "error",
121
+ "no-undef": "error",
122
+ "no-unexpected-multiline": "error",
123
+ //"no-unreachable": "error",
124
+ "no-unsafe-finally": "error",
125
+ "no-unsafe-negation": "error",
126
+ "no-unsafe-optional-chaining": "error",
127
+ "no-unused-labels": "error",
128
+ "no-unused-private-class-members": "error",
129
+ //"no-unused-vars": "error",
130
+ "no-useless-backreference": "error",
131
+ "no-useless-catch": "error",
132
+ //"no-useless-escape": "error",
133
+ "no-with": "error",
134
+ "require-yield": "error",
135
+ "use-isnan": "error",
136
+ "valid-typeof": "error",
137
+ "strict": "error"
138
+ }
139
+ }
140
+ ];
examples/alpine.html ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Alpine</title>
3
+ <script src="../build/libv86.js"></script>
4
+ <script>
5
+ "use strict";
6
+ window.onload = function()
7
+ {
8
+ var emulator = new V86({
9
+ wasm_path: "../build/v86.wasm",
10
+ memory_size: 512 * 1024 * 1024,
11
+ vga_memory_size: 8 * 1024 * 1024,
12
+ screen_container: document.getElementById("screen_container"),
13
+ bios: { url: "../bios/seabios.bin" },
14
+ vga_bios: { url: "../bios/vgabios.bin" },
15
+ filesystem: {
16
+ baseurl: "../images/alpine-rootfs-flat",
17
+ basefs: "../images/alpine-fs.json",
18
+ },
19
+ autostart: true,
20
+ bzimage_initrd_from_filesystem: true,
21
+ cmdline: "rw root=host9p rootfstype=9p rootflags=trans=virtio,cache=loose modules=virtio_pci tsc=reliable",
22
+ //initial_state: { url: "../images/alpine-state.bin" },
23
+ });
24
+ };
25
+ </script>
26
+ <div id="screen_container">
27
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
28
+ <canvas style="display: none"></canvas>
29
+ </div>
examples/arch.html ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Archlinux</title>
3
+
4
+ <script src="../build/libv86.js"></script>
5
+ <script>
6
+ "use strict";
7
+
8
+ window.onload = function()
9
+ {
10
+ var emulator = new V86({
11
+ wasm_path: "../build/v86.wasm",
12
+ memory_size: 512 * 1024 * 1024,
13
+ vga_memory_size: 8 * 1024 * 1024,
14
+ screen_container: document.getElementById("screen_container"),
15
+ bios: {
16
+ url: "../bios/seabios.bin",
17
+ },
18
+ vga_bios: {
19
+ url: "../bios/vgabios.bin",
20
+ },
21
+ filesystem: {
22
+ baseurl: "../images/arch/",
23
+ basefs: "../images/fs.json",
24
+ },
25
+ autostart: true,
26
+ bzimage_initrd_from_filesystem: true,
27
+ cmdline: [
28
+ "rw",
29
+ "root=host9p rootfstype=9p rootflags=trans=virtio,cache=loose",
30
+ "init=/usr/bin/init-openrc",
31
+ ].join(" "),
32
+ });
33
+
34
+ document.getElementById("save_file").onclick = async function()
35
+ {
36
+ const new_state = await emulator.save_state();
37
+
38
+ var a = document.createElement("a");
39
+ a.download = "v86state.bin";
40
+ a.href = window.URL.createObjectURL(new Blob([new_state]));
41
+ a.dataset.downloadurl = "application/octet-stream:" + a.download + ":" + a.href;
42
+ a.click();
43
+
44
+ this.blur();
45
+ };
46
+
47
+ document.getElementById("restore_file").onchange = function()
48
+ {
49
+ if(this.files.length)
50
+ {
51
+ var filereader = new FileReader();
52
+ emulator.stop();
53
+
54
+ filereader.onload = async function(e)
55
+ {
56
+ await emulator.restore_state(e.target.result);
57
+ emulator.run();
58
+ };
59
+
60
+ filereader.readAsArrayBuffer(this.files[0]);
61
+
62
+ this.value = "";
63
+ }
64
+
65
+ this.blur();
66
+ };
67
+ };
68
+ </script>
69
+
70
+ <input id="save_file" type="button" value="Save state to file">
71
+ Restore from file: <input id="restore_file" type="file">
72
+ <hr>
73
+
74
+ <!-- A minimal structure for the ScreenAdapter defined in browser/screen.js -->
75
+ <div id="screen_container">
76
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
77
+ <canvas style="display: none"></canvas>
78
+ </div>
examples/async_load.html ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Asynchronous loading of disk images</title>
3
+
4
+ <script src="../build/libv86.js"></script>
5
+ <script>
6
+ "use strict";
7
+
8
+ window.onload = function()
9
+ {
10
+ // Async loading of the iso image
11
+ // Note how the emulation starts without downloading the 50MB image
12
+
13
+ // Support of the "Range: bytes=..." header is required on the server, CORS
14
+ // is required if the server is on a different host
15
+
16
+ var emulator = new V86({
17
+ wasm_path: "../build/v86.wasm",
18
+ memory_size: 64 * 1024 * 1024,
19
+ vga_memory_size: 2 * 1024 * 1024,
20
+ screen_container: document.getElementById("screen_container"),
21
+ bios: {
22
+ url: "../bios/seabios.bin",
23
+ },
24
+ vga_bios: {
25
+ url: "../bios/vgabios.bin",
26
+ },
27
+ cdrom: {
28
+ url: "../images/dsl-4.11.rc2.iso",
29
+ async: true,
30
+
31
+ // size can be determined automatically, but costs an extra request
32
+ // and might not work reliably
33
+ size: 52824064,
34
+ },
35
+ autostart: true,
36
+ });
37
+ }
38
+ </script>
39
+
40
+ <div id="screen_container">
41
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
42
+ <canvas style="display: none"></canvas>
43
+ </div>
examples/basic.html ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Basic Emulator</title><!-- not BASIC! -->
3
+
4
+ <script src="../build/libv86.js"></script>
5
+ <script>
6
+ "use strict";
7
+
8
+ window.onload = function()
9
+ {
10
+ var emulator = window.emulator = new V86({
11
+ wasm_path: "../build/v86.wasm",
12
+ memory_size: 32 * 1024 * 1024,
13
+ vga_memory_size: 2 * 1024 * 1024,
14
+ screen_container: document.getElementById("screen_container"),
15
+ bios: {
16
+ url: "../bios/seabios.bin",
17
+ },
18
+ vga_bios: {
19
+ url: "../bios/vgabios.bin",
20
+ },
21
+ cdrom: {
22
+ url: "../images/linux.iso",
23
+ },
24
+ autostart: true,
25
+ });
26
+ }
27
+ </script>
28
+
29
+ <!-- A minimal structure for the ScreenAdapter defined in browser/screen.js -->
30
+ <div id="screen_container">
31
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
32
+ <canvas style="display: none"></canvas>
33
+ </div>
examples/broadcast-network.html ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Networking via Broadcast Channel API</title>
3
+
4
+ <script src="../build/libv86.js"></script>
5
+ <script>
6
+ "use strict";
7
+
8
+ window.onload = function()
9
+ {
10
+ var emulator = window.emulator = new V86({
11
+ wasm_path: "../build/v86.wasm",
12
+ memory_size: 64 * 1024 * 1024,
13
+ vga_memory_size: 2 * 1024 * 1024,
14
+ screen_container: document.getElementById("screen_container"),
15
+ bios: {
16
+ url: "../bios/seabios.bin",
17
+ },
18
+ vga_bios: {
19
+ url: "../bios/vgabios.bin",
20
+ },
21
+ bzimage: {
22
+ url: "../images/buildroot-bzimage68.bin",
23
+ },
24
+ autostart: true,
25
+ });
26
+
27
+ var broadcast = new BroadcastChannel("v86-network");
28
+
29
+ broadcast.addEventListener("message", function(e) {
30
+ emulator.bus.send("net0-receive", e.data);
31
+ });
32
+ emulator.add_listener("net0-send", function(packet) {
33
+ broadcast.postMessage(packet);
34
+ });
35
+ }
36
+ </script>
37
+
38
+ <div id="screen_container">
39
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
40
+ <canvas style="display: none"></canvas>
41
+ </div>
42
+
43
+ <pre>
44
+ # This example allows network across multiple browser tabs by using BroadcastChannels.
45
+
46
+ # Configure a static IP
47
+ ifconfig eth0 up arp 10.5.0.x
48
+
49
+ # Ping by IP
50
+ ping 10.5.0.x
51
+
52
+ # Run a DNS server and send a query (10.5.0.x for server, 10.5.0.y for record)
53
+ echo "anotherhost 10.5.0.y" | dnsd -c - -v - server
54
+ nslookup -type=a anotherhost 10.5.0.x - client
55
+
56
+ # Telnet calculator
57
+ socat TCP-L:23,fork exec:bc
58
+
59
+ # Simple HTTP server
60
+ socat TCP-L:80,crlf,fork system:'echo HTTP/1.1 200 OK;echo;lua /root/test.lua'
61
+ </pre>
examples/destroy.html ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Destroyable Emulator</title>
3
+
4
+ <script src="../build/libv86.js"></script>
5
+ <script>
6
+ "use strict";
7
+
8
+ window.onload = function()
9
+ {
10
+ var emulator = new V86({
11
+ wasm_path: "../build/v86.wasm",
12
+ memory_size: 32 * 1024 * 1024,
13
+ vga_memory_size: 2 * 1024 * 1024,
14
+ screen_container: document.getElementById("screen_container"),
15
+ bios: {
16
+ url: "../bios/seabios.bin",
17
+ },
18
+ vga_bios: {
19
+ url: "../bios/vgabios.bin",
20
+ },
21
+ cdrom: {
22
+ url: "../images/linux.iso",
23
+ },
24
+ autostart: true,
25
+ });
26
+
27
+ setTimeout(() => { emulator.destroy(); }, 1000);
28
+ }
29
+ </script>
30
+
31
+ <div id="screen_container">
32
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
33
+ <canvas style="display: none"></canvas>
34
+ </div>
examples/lang.html ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Basic Emulator</title><!-- not BASIC! -->
3
+
4
+ <script src="../build/libv86.js"></script>
5
+ <script>
6
+ "use strict";
7
+
8
+ window.onload = function()
9
+ {
10
+ var start = Date.now();
11
+
12
+ setInterval(function()
13
+ {
14
+ document.getElementById("time").textContent = Math.round((Date.now() - start) / 1000);
15
+ }, 999);
16
+
17
+ var emulator = new V86({
18
+ wasm_path: "../build/v86.wasm",
19
+ memory_size: 512 * 1024 * 1024,
20
+ vga_memory_size: 8 * 1024 * 1024,
21
+ screen_container: document.getElementById("screen_container"),
22
+ bios: {
23
+ url: "../bios/seabios.bin",
24
+ },
25
+ vga_bios: {
26
+ url: "../bios/vgabios.bin",
27
+ },
28
+ initial_state: {
29
+ url: "../images/arch_state-v2.bin.zst",
30
+ },
31
+ filesystem: {
32
+ baseurl: "../images/arch/",
33
+ },
34
+ autostart: true,
35
+ });
36
+
37
+ document.getElementById("status").textContent += ".";
38
+
39
+ emulator.add_listener("emulator-ready", async function()
40
+ {
41
+ document.getElementById("status").textContent += ".";
42
+
43
+ var code = "console.log(3 * 7);\n";
44
+ var buffer = new Uint8Array(code.length);
45
+
46
+ buffer.set(code.split("").map(function(chr) { return chr.charCodeAt(0); }));
47
+
48
+ await emulator.create_file("/root/code.js", buffer);
49
+ emulator.serial0_send("node /root/code.js > /root/out.txt 2> /root/out.txt\n");
50
+ });
51
+
52
+ var serial_out = "";
53
+ emulator.add_listener("serial0-output-byte", async function(byte)
54
+ {
55
+ var chr = String.fromCharCode(byte);
56
+ serial_out += chr;
57
+
58
+ if(serial_out.endsWith("root@nyu"))
59
+ {
60
+ const data = await emulator.read_file("/root/out.txt");
61
+ document.getElementById("output").textContent += String.fromCharCode.apply(this, data);
62
+ }
63
+ });
64
+ }
65
+ </script>
66
+
67
+ <pre><span id=time></span> <span id=status></span></pre>
68
+
69
+ <!-- A minimal structure for the ScreenAdapter defined in browser/screen.js -->
70
+ <div id="screen_container">
71
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
72
+ <canvas style="display: none"></canvas>
73
+ </div>
74
+
75
+ <hr>
76
+
77
+ <pre id=output></pre>
examples/lua.html ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Lua interpreter</title>
3
+
4
+ <script src="../build/libv86.js"></script>
5
+ <script>
6
+ "use strict";
7
+
8
+ window.onload = function()
9
+ {
10
+ var emulator = new V86({
11
+ wasm_path: "../build/v86.wasm",
12
+ memory_size: 32 * 1024 * 1024,
13
+ vga_memory_size: 2 * 1024 * 1024,
14
+
15
+ // Uncomment to see what's going on
16
+ //screen_container: document.getElementById("screen_container"),
17
+
18
+ bios: {
19
+ url: "../bios/seabios.bin",
20
+ },
21
+ vga_bios: {
22
+ url: "../bios/vgabios.bin",
23
+ },
24
+ bzimage: {
25
+ url: "../images/buildroot-bzimage68.bin",
26
+ },
27
+ autostart: true,
28
+ disable_keyboard: true,
29
+ disable_mouse: true,
30
+ });
31
+
32
+ var data = "";
33
+ var do_output = false;
34
+
35
+ emulator.add_listener("serial0-output-byte", function(byte)
36
+ {
37
+ var char = String.fromCharCode(byte);
38
+ if(char !== "\r")
39
+ {
40
+ data += char;
41
+ }
42
+
43
+ if(do_output)
44
+ {
45
+ document.getElementById("result").textContent += char;
46
+ }
47
+
48
+ if(data.endsWith("~% "))
49
+ {
50
+ console.log("Now ready");
51
+ document.getElementById("status").textContent = "Ready.\n";
52
+ document.getElementById("run").disabled = false;
53
+ do_output = false;
54
+ }
55
+ });
56
+
57
+ document.getElementById("source").onkeydown = function(e)
58
+ {
59
+ if(e.which == 13 && e.ctrlKey)
60
+ {
61
+ document.getElementById("run").onclick();
62
+ }
63
+ };
64
+
65
+ document.getElementById("run").onclick = function()
66
+ {
67
+ var code = document.getElementById("source").value;
68
+
69
+ emulator.serial0_send("lua -e " + bashEscape(code) + "\n");
70
+
71
+ document.getElementById("result").textContent = "";
72
+ document.getElementById("status").textContent = "Running ...\n";
73
+ this.disabled = true;
74
+
75
+ do_output = true;
76
+ };
77
+ };
78
+
79
+ // https://gist.github.com/creationix/2502704
80
+ // Implement bash string escaping.
81
+ function bashEscape(arg)
82
+ {
83
+ arg = arg.replace(/\t+/g, "");
84
+ return "'" + arg.replace(/'+/g, function (val) {
85
+ return "'" + val.replace(/'/g, "\\'") + "'";
86
+ }) + "'";
87
+ }
88
+ </script>
89
+
90
+ <textarea id=source rows=20 cols=80>
91
+ k = 1
92
+ x = 0
93
+
94
+ while k &lt; 1000 do
95
+ x = x + 1 / (k * k)
96
+ k = k + 2
97
+ end
98
+
99
+ print(math.sqrt(x*8))
100
+
101
+ function factorial(n)
102
+ if n == 0 then
103
+ return 1
104
+ else
105
+ return n * factorial(n - 1)
106
+ end
107
+ end
108
+
109
+ print("factorial(10):", factorial(10))
110
+ </textarea>
111
+ <button disabled id=run>run (ctrl-enter)</button>
112
+ <br>
113
+ <hr>
114
+ <pre id=status>Wait for boot ...</pre>
115
+ <pre id=result></pre>
116
+
117
+ <hr>
118
+
119
+ <div id="screen_container">
120
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
121
+ <canvas style="display: none"></canvas>
122
+ </div>
examples/nodejs.js ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env node
2
+
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import url from "node:url";
6
+ import { V86 } from "../build/libv86.mjs";
7
+
8
+ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
9
+
10
+ process.stdin.setRawMode(true);
11
+ process.stdin.resume();
12
+ process.stdin.setEncoding("utf8");
13
+
14
+ console.log("Now booting, please stand by ...");
15
+
16
+ var emulator = new V86({
17
+ bios: { url: __dirname + "/../bios/seabios.bin" },
18
+ vga_bios: { url: __dirname + "/../bios/vgabios.bin" },
19
+ cdrom: { url: __dirname + "/../images/linux4.iso" },
20
+ autostart: true,
21
+ net_device: {
22
+ type: "virtio",
23
+ relay_url: "fetch",
24
+ },
25
+ });
26
+
27
+ emulator.add_listener("serial0-output-byte", function(byte)
28
+ {
29
+ var chr = String.fromCharCode(byte);
30
+ if(chr <= "~")
31
+ {
32
+ process.stdout.write(chr);
33
+ }
34
+ });
35
+
36
+ process.stdin.on("data", function(c)
37
+ {
38
+ if(c === "\u0003")
39
+ {
40
+ // ctrl c
41
+ emulator.destroy();
42
+ process.stdin.pause();
43
+ }
44
+ else
45
+ {
46
+ emulator.serial0_send(c);
47
+ }
48
+ });
examples/nodejs_state.js ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import url from "node:url";
5
+ import { V86 } from "../build/libv86.mjs";
6
+
7
+ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
8
+
9
+ console.log("Use F2 to save the state and F3 to restore.");
10
+
11
+ process.stdin.setRawMode(true);
12
+ process.stdin.resume();
13
+ process.stdin.setEncoding("utf8");
14
+
15
+ console.log("Now booting, please stand by ...");
16
+
17
+ var emulator = new V86({
18
+ bios: { url: __dirname + "/../bios/seabios.bin" },
19
+ cdrom: { url: __dirname + "/../images/linux4.iso" },
20
+ autostart: true,
21
+ });
22
+
23
+ emulator.add_listener("serial0-output-byte", function(byte)
24
+ {
25
+ var chr = String.fromCharCode(byte);
26
+ if(chr <= "~")
27
+ {
28
+ process.stdout.write(chr);
29
+ }
30
+ });
31
+
32
+ var state;
33
+
34
+ process.stdin.on("data", async function(c)
35
+ {
36
+ if(c === "\u0003")
37
+ {
38
+ // ctrl c
39
+ emulator.destroy();
40
+ process.stdin.pause();
41
+ }
42
+ else if(c === "\x1b\x4f\x51")
43
+ {
44
+ // f2
45
+ state = await emulator.save_state();
46
+ console.log("--- Saved ---");
47
+ }
48
+ else if(c === "\x1b\x4f\x52")
49
+ {
50
+ // f3
51
+ if(state)
52
+ {
53
+ console.log("--- Restored ---");
54
+ await emulator.restore_state(state);
55
+ }
56
+ }
57
+ else
58
+ {
59
+ emulator.serial0_send(c);
60
+ }
61
+ });
examples/save_restore.html ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <title>Save and restore</title>
3
+
4
+ <script src="../build/libv86.js"></script>
5
+ <script>
6
+ "use strict";
7
+
8
+ window.onload = function()
9
+ {
10
+ var emulator = new V86({
11
+ wasm_path: "../build/v86.wasm",
12
+ memory_size: 32 * 1024 * 1024,
13
+ vga_memory_size: 2 * 1024 * 1024,
14
+ screen_container: document.getElementById("screen_container"),
15
+ bios: {
16
+ url: "../bios/seabios.bin",
17
+ },
18
+ vga_bios: {
19
+ url: "../bios/vgabios.bin",
20
+ },
21
+ cdrom: {
22
+ url: "../images/linux.iso",
23
+ },
24
+ autostart: true,
25
+ });
26
+
27
+ var state;
28
+
29
+ document.getElementById("save_restore").onclick = async function()
30
+ {
31
+ var button = this;
32
+
33
+ if(state)
34
+ {
35
+ button.value = "Save state";
36
+ await emulator.restore_state(state);
37
+ state = undefined;
38
+ }
39
+ else
40
+ {
41
+ const new_state = await emulator.save_state();
42
+ console.log("Saved state of " + new_state.byteLength + " bytes");
43
+ button.value = "Restore state";
44
+ state = new_state;
45
+ }
46
+
47
+ button.blur();
48
+ };
49
+
50
+ document.getElementById("save_file").onclick = async function()
51
+ {
52
+ const new_state = await emulator.save_state();
53
+ var a = document.createElement("a");
54
+ a.download = "v86state.bin";
55
+ a.href = window.URL.createObjectURL(new Blob([new_state]));
56
+ a.dataset.downloadurl = "application/octet-stream:" + a.download + ":" + a.href;
57
+ a.click();
58
+
59
+ this.blur();
60
+ };
61
+
62
+ document.getElementById("restore_file").onchange = function()
63
+ {
64
+ if(this.files.length)
65
+ {
66
+ var filereader = new FileReader();
67
+ emulator.stop();
68
+
69
+ filereader.onload = async function(e)
70
+ {
71
+ await emulator.restore_state(e.target.result);
72
+ emulator.run();
73
+ };
74
+
75
+ filereader.readAsArrayBuffer(this.files[0]);
76
+
77
+ this.value = "";
78
+ }
79
+
80
+ this.blur();
81
+ };
82
+ };
83
+ </script>
84
+
85
+ <input id="save_restore" type="button" value="Save state">
86
+ <input id="save_file" type="button" value="Save state to file">
87
+ Restore from file: <input id="restore_file" type="file">
88
+ <hr>
89
+
90
+ <!-- A minimal structure for the ScreenAdapter defined in browser/screen.js -->
91
+ <div id="screen_container">
92
+ <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
93
+ <canvas style="display: none"></canvas>
94
+ </div>