js-dos 7.4.9 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/.github/workflows/build.yml +51 -0
  2. package/.gitmodules +4 -0
  3. package/README.deployment.md +11 -0
  4. package/README.md +29 -89
  5. package/index.html +106 -0
  6. package/package.json +46 -71
  7. package/postcss.config.cjs +8 -0
  8. package/src/app.css +14 -0
  9. package/src/base.css +10 -0
  10. package/src/components/checkbox.tsx +41 -0
  11. package/src/components/close-button.tsx +17 -0
  12. package/src/components/components.css +28 -0
  13. package/src/components/dos-option-checkbox.tsx +94 -0
  14. package/src/components/dos-option-select.tsx +108 -0
  15. package/src/components/dos-option-slider.tsx +35 -0
  16. package/src/components/error.tsx +16 -0
  17. package/src/components/loading.tsx +26 -0
  18. package/src/components/lock.tsx +10 -0
  19. package/src/components/select.tsx +33 -0
  20. package/src/components/slider.tsx +69 -0
  21. package/src/download-file.ts +18 -0
  22. package/src/frame/account-frame.tsx +156 -0
  23. package/src/frame/editor/defaults.ts +419 -0
  24. package/src/frame/editor/editor-conf-frame.tsx +226 -0
  25. package/src/frame/editor/editor-frame.css +55 -0
  26. package/src/frame/editor/editor-fs-frame.tsx +314 -0
  27. package/src/frame/fat-drives-frame.tsx +135 -0
  28. package/src/frame/frame.css +119 -0
  29. package/src/frame/frame.tsx +34 -0
  30. package/src/frame/image-rendering-frame.tsx +8 -0
  31. package/src/frame/network-frame.tsx +157 -0
  32. package/src/frame/quick-save-frame.tsx +96 -0
  33. package/src/frame/settings-frame.tsx +14 -0
  34. package/src/frame/stats-frame.tsx +87 -0
  35. package/src/host/bundle-storage.ts +91 -0
  36. package/src/host/fullscreen.ts +35 -0
  37. package/src/host/lcache.ts +203 -0
  38. package/src/host/lstorage.ts +156 -0
  39. package/src/i18n.ts +179 -0
  40. package/src/index.css +7 -0
  41. package/src/load.ts +132 -0
  42. package/src/login/login.css +9 -0
  43. package/src/login/login.tsx +77 -0
  44. package/src/main.tsx +197 -0
  45. package/src/public/types.ts +41 -0
  46. package/src/sidebar/account-button.tsx +33 -0
  47. package/src/sidebar/cloud-save-button.tsx +89 -0
  48. package/src/sidebar/diskette-icon.tsx +14 -0
  49. package/src/sidebar/fullscreen-button.tsx +44 -0
  50. package/src/sidebar/network-button.tsx +39 -0
  51. package/src/sidebar/sidebar-button.tsx +244 -0
  52. package/src/sidebar/sidebar.css +47 -0
  53. package/src/sidebar/sidebar.tsx +30 -0
  54. package/src/sockdrive/LICENSE +674 -0
  55. package/src/sockdrive/README.md +45 -0
  56. package/src/sockdrive/include/sockdrive.h +23 -0
  57. package/src/sockdrive/js/.eslintrc.json +43 -0
  58. package/src/sockdrive/js/package.json +29 -0
  59. package/src/sockdrive/js/src/fatfs/chains.js +318 -0
  60. package/src/sockdrive/js/src/fatfs/dir.js +385 -0
  61. package/src/sockdrive/js/src/fatfs/helpers.js +210 -0
  62. package/src/sockdrive/js/src/fatfs/index.js +606 -0
  63. package/src/sockdrive/js/src/fatfs/structs.js +255 -0
  64. package/src/sockdrive/js/src/fatfs/vol.js +166 -0
  65. package/src/sockdrive/js/src/sockdrive/cache.ts +133 -0
  66. package/src/sockdrive/js/src/sockdrive/drive.ts +457 -0
  67. package/src/sockdrive/js/src/sockdrive/lru.ts +221 -0
  68. package/src/sockdrive/js/src/sockdrive/types.ts +14 -0
  69. package/src/sockdrive/js/src/sockdrive-fat.d.ts +64 -0
  70. package/src/sockdrive/js/src/sockdrive-fat.ts +226 -0
  71. package/src/sockdrive/js/src/sockdrive-native.ts +100 -0
  72. package/src/sockdrive/js/src/test/test.ts +288 -0
  73. package/src/sockdrive/js/tsconfig.json +11 -0
  74. package/src/sockdrive/js/webpack.config.js +68 -0
  75. package/src/sockdrive/js/yarn.lock +1808 -0
  76. package/src/store/auth.ts +115 -0
  77. package/src/store/dos.ts +305 -0
  78. package/src/store/editor.ts +61 -0
  79. package/src/store/init.ts +48 -0
  80. package/src/store/storage.ts +32 -0
  81. package/src/store/ui.ts +186 -0
  82. package/src/store.tsx +108 -0
  83. package/src/ui.tsx +104 -0
  84. package/src/v8/changes.ts +56 -0
  85. package/src/v8/config.ts +18 -0
  86. package/src/v8/subscriptions.ts +62 -0
  87. package/src/vite-env.d.ts +2 -0
  88. package/src/window/dos/controls/keyboard.ts +32 -0
  89. package/src/window/dos/controls/keys.ts +331 -0
  90. package/src/window/dos/controls/mouse/mount.ts +99 -0
  91. package/src/window/dos/controls/mouse/mouse-locked.ts +51 -0
  92. package/src/window/dos/controls/mouse/mouse-not-locked.ts +84 -0
  93. package/src/window/dos/controls/mouse/mouse-swipe.ts +57 -0
  94. package/src/window/dos/controls/mouse/pointer.ts +85 -0
  95. package/src/window/dos/controls/mouse.ts +21 -0
  96. package/src/window/dos/dos-dhry2.tsx +191 -0
  97. package/src/window/dos/dos-runtime.tsx +214 -0
  98. package/src/window/dos/dos-window.tsx +84 -0
  99. package/src/window/dos/render/canvas.ts +65 -0
  100. package/src/window/dos/render/resize.ts +31 -0
  101. package/src/window/dos/render/webgl.ts +173 -0
  102. package/src/window/dos/sound/audio-node.ts +148 -0
  103. package/src/window/error-window.tsx +9 -0
  104. package/src/window/loading-window.tsx +54 -0
  105. package/src/window/prerun-window.tsx +123 -0
  106. package/src/window/select-window.tsx +118 -0
  107. package/src/window/window.css +78 -0
  108. package/src/window/window.tsx +49 -0
  109. package/src/ws/ws-sockdrive.ts +101 -0
  110. package/src/ws/ws-transport-layer.ts +455 -0
  111. package/tailwind.config.cjs +48 -0
  112. package/tsconfig.json +32 -0
  113. package/tsconfig.node.json +9 -0
  114. package/vite.config.ts +22 -0
  115. package/LICENSE +0 -339
  116. package/dist/emulators-ui-loader.png +0 -0
  117. package/dist/js-dos.css +0 -1690
  118. package/dist/js-dos.js +0 -17
  119. package/dist/js-dos.js.map +0 -1
  120. package/dist/types/src/backend/v7/latency.d.ts +0 -8
  121. package/dist/types/src/backend/v7/personal.d.ts +0 -2
  122. package/dist/types/src/backend/v7/v7-config.d.ts +0 -16
  123. package/dist/types/src/components/action-bar.d.ts +0 -2
  124. package/dist/types/src/components/action-hide.d.ts +0 -4
  125. package/dist/types/src/components/action-save-or-exit.d.ts +0 -4
  126. package/dist/types/src/components/client.d.ts +0 -6
  127. package/dist/types/src/components/controls.d.ts +0 -8
  128. package/dist/types/src/components/cpu-control.d.ts +0 -2
  129. package/dist/types/src/components/horizontal-slider.d.ts +0 -13
  130. package/dist/types/src/components/region.d.ts +0 -6
  131. package/dist/types/src/components/scale-control.d.ts +0 -3
  132. package/dist/types/src/components/sensitivity-control.d.ts +0 -3
  133. package/dist/types/src/components/sidebar/latency-info.d.ts +0 -7
  134. package/dist/types/src/components/sidebar/main.d.ts +0 -2
  135. package/dist/types/src/components/sidebar/networking.d.ts +0 -2
  136. package/dist/types/src/components/sidebar/token/token-add-time.d.ts +0 -2
  137. package/dist/types/src/components/sidebar/token/token-select.d.ts +0 -2
  138. package/dist/types/src/components/sidebar/token/token.d.ts +0 -17
  139. package/dist/types/src/components/sidebar.d.ts +0 -2
  140. package/dist/types/src/components/sync-control.d.ts +0 -2
  141. package/dist/types/src/components/tip.d.ts +0 -2
  142. package/dist/types/src/components/vertical-slider.d.ts +0 -12
  143. package/dist/types/src/components/volume-control.d.ts +0 -3
  144. package/dist/types/src/dom.d.ts +0 -8
  145. package/dist/types/src/hardware-transport-layer.d.ts +0 -18
  146. package/dist/types/src/icons.d.ts +0 -95
  147. package/dist/types/src/player-app.d.ts +0 -50
  148. package/dist/types/src/player.d.ts +0 -29
  149. package/dist/types/src/request.d.ts +0 -1
  150. package/dist/types/src/xhr.d.ts +0 -6
  151. package/dist/types/v7-services/src/personal.d.ts +0 -3
  152. package/dist/wdosbox.js +0 -55
  153. package/dist/wdosbox.js.symbols +0 -3174
  154. package/dist/wdosbox.wasm +0 -0
  155. package/examples/digger/index.html +0 -71
@@ -0,0 +1,115 @@
1
+ import { createSlice } from "@reduxjs/toolkit";
2
+ import { getCache } from "../host/lcache";
3
+ import { lStorage } from "../host/lstorage";
4
+ import { DosAction, getNonSerializableStore } from "../store";
5
+ import { dosSlice } from "./dos";
6
+
7
+ const cachedAccount = "cached.account";
8
+
9
+ export interface Token {
10
+ access_token: string,
11
+ refresh_token: string,
12
+ scope: string,
13
+ expires_in: number,
14
+ validUntilMs: number;
15
+ };
16
+
17
+ export interface Account {
18
+ email: string,
19
+ name: null | string,
20
+ picture: null | string,
21
+ token: Token,
22
+ premium: boolean,
23
+ };
24
+
25
+ const initAccount = (() => {
26
+ const params = new URLSearchParams(location.search);
27
+ const refreshToken = params.get("jsdos_token");
28
+ if (refreshToken !== null) {
29
+ setRefreshToken(refreshToken);
30
+ history.replaceState(null, "", location.href.substring(0, location.href.indexOf("?")));
31
+ return null;
32
+ } else {
33
+ const json = lStorage.getItem(cachedAccount);
34
+ const account = json !== null ? JSON.parse(json) : null;
35
+ return account !== null && account.token.validUntilMs - Date.now() > 1 * 60 * 60 * 1000 ?
36
+ account : null;
37
+ }
38
+ })();
39
+
40
+ const initialState: {
41
+ account: Account | null,
42
+ ready: boolean,
43
+ } = {
44
+ account: initAccount,
45
+ ready: initAccount !== null,
46
+ };
47
+
48
+ export type AuthState = typeof initialState;
49
+
50
+ export const authSlice = createSlice({
51
+ name: "auth",
52
+ initialState,
53
+ reducers: {
54
+ login: (state, action: { payload: Account }) => {
55
+ setRefreshToken(action.payload.token.refresh_token);
56
+ state.account = action.payload;
57
+ state.account.premium = state.account.premium ||
58
+ state.account.email === "dz.caiiiycuk@gmail.com" ||
59
+ state.account.email === "caiiiycuk@gmail.com";
60
+ lStorage.setItem(cachedAccount, JSON.stringify(action.payload));
61
+ (action as unknown as DosAction).asyncStore((store) => {
62
+ if (action.payload.email === "dz.caiiiycuk@gmail.com" ||
63
+ action.payload.email === "caiiiycuk@gmail.com") {
64
+ store.dispatch(dosSlice.actions.setSockdriveWrite(false));
65
+ }
66
+ getCache(action.payload.email)
67
+ .then((cache) => getNonSerializableStore(store).cache = cache)
68
+ .catch(console.error)
69
+ .finally(() => {
70
+ store.dispatch(authSlice.actions.ready());
71
+ });
72
+ });
73
+ },
74
+ logout: (state, action) => {
75
+ clearRefreshToken();
76
+ lStorage.removeItem(cachedAccount);
77
+ (action as unknown as DosAction).asyncStore((store) => {
78
+ getCache("guest")
79
+ .then((cache) => getNonSerializableStore(store).cache = cache)
80
+ .catch(console.error);
81
+ });
82
+ state.account = null;
83
+ },
84
+ ready: (state) => {
85
+ state.ready = true;
86
+ },
87
+ },
88
+ });
89
+
90
+ export function postAuthMessage(action: "auth/login" | "auth/authenicate") {
91
+ const message = {
92
+ action,
93
+ refresh_token: action === "auth/authenicate" ? getRefreshToken() : undefined,
94
+ url: action === "auth/login" ? location.href : undefined,
95
+ };
96
+ document.querySelector<HTMLIFrameElement>("#authentificator")!
97
+ .contentWindow?.postMessage(message, "*");
98
+ }
99
+
100
+ function getRefreshToken(): string | null {
101
+ return lStorage.getItem("cached.rt");
102
+ }
103
+
104
+ function setRefreshToken(refreshToken: string | null) {
105
+ if (refreshToken === null) {
106
+ clearRefreshToken();
107
+ return;
108
+ }
109
+
110
+ return lStorage.setItem("cached.rt", refreshToken);
111
+ }
112
+
113
+ function clearRefreshToken() {
114
+ lStorage.removeItem("cached.rt");
115
+ }
@@ -0,0 +1,305 @@
1
+ import { createSlice } from "@reduxjs/toolkit";
2
+ import { DosAction, getNonSerializableStore, makeStore, postJsDosEvent } from "../store";
3
+ import { Emulators } from "emulators";
4
+ import { lStorage } from "../host/lstorage";
5
+
6
+ const alphabet = "qwertyuiopasdfghjklzxcvbnm1234567890";
7
+ declare const emulators: Emulators;
8
+ export interface BundleConfig {
9
+ name?: string,
10
+ version?: string,
11
+ backend?: string,
12
+ render?: string,
13
+ };
14
+
15
+ export const BackendValues = <const>["dosbox", "dosboxX"];
16
+ export type Backend = typeof BackendValues[number];
17
+
18
+ export const RenderBackendValues = <const>["webgl", "canvas"];
19
+ export type RenderBackend = typeof RenderBackendValues[number];
20
+
21
+ export const RenderAspectValues = <const>["AsIs", "1/1", "5/4", "4/3", "16/10", "16/9", "Fit"];
22
+ export type RenderAspect = typeof RenderAspectValues[number];
23
+ export const FitConstant = 65535;
24
+
25
+ export const ImageRenderingValues = <const>["pixelated", "smooth"];
26
+ export type ImageRendering = typeof ImageRenderingValues[number];
27
+
28
+ export interface EmulatorStats {
29
+ cyclesPerMs: number,
30
+ nonSkippableSleepPreSec: number,
31
+ sleepPerSec: number,
32
+ sleepTimePerSec: number,
33
+ framePerSec: number,
34
+ soundPerSec: number,
35
+ msgSentPerSec: number,
36
+ msgRecvPerSec: number,
37
+ netSent: number,
38
+ netRecv: number,
39
+ driveSent: number,
40
+ driveRecv: number,
41
+ driveRecvTime: number,
42
+ driveCacheHit: number,
43
+ driveCacheMiss: number,
44
+ driveCacheUsed: number,
45
+ };
46
+
47
+ const initialState: {
48
+ step:
49
+ "emu-init" | "emu-error" | "emu-ready" |
50
+ "bnd-load" | "bnd-error" | "bnd-config" | "bnd-ready" |
51
+ "bnd-play",
52
+ emuVersion: string,
53
+ worker: boolean,
54
+ backend: Backend,
55
+ backendLocked: boolean,
56
+ backendHardware: boolean,
57
+ renderBackend: RenderBackend,
58
+ renderAspect: RenderAspect,
59
+ volume: number,
60
+ mouseSensitivity: number,
61
+ mouseCapture: boolean,
62
+ paused: boolean,
63
+ error: null | undefined | string,
64
+ bundle: string | null,
65
+ config: BundleConfig,
66
+ stats: EmulatorStats,
67
+ ci: boolean,
68
+ ciStartedAt: number,
69
+ network: {
70
+ server: "netherlands" | "newyork" | "singapore",
71
+ room: string,
72
+ ipx: "connecting" | "connected" | "disconnected" | "error",
73
+ },
74
+ imageRendering: ImageRendering,
75
+ sockdriveWrite: boolean,
76
+ } = {
77
+ step: "emu-init",
78
+ emuVersion: "-",
79
+ error: null,
80
+ bundle: null,
81
+ config: {},
82
+ worker: lStorage.getItem("worker") !== "false",
83
+ backend: (lStorage.getItem("backend") ?? "dosbox") as Backend,
84
+ backendLocked: false,
85
+ backendHardware: (lStorage.getItem("backendHardware") !== "false"),
86
+ renderBackend: (lStorage.getItem("renderBackend") ?? "webgl") as RenderBackend,
87
+ renderAspect: (lStorage.getItem("renderAspect") ?? "AsIs") as RenderAspect,
88
+ volume: (Number.parseFloat(lStorage.getItem("volume") ?? "1.0")),
89
+ mouseSensitivity: (Number.parseFloat(lStorage.getItem("mouse_sensitivity") ?? "1.0")),
90
+ mouseCapture: false,
91
+ paused: false,
92
+ stats: {
93
+ cyclesPerMs: 0,
94
+ nonSkippableSleepPreSec: 0,
95
+ sleepPerSec: 0,
96
+ sleepTimePerSec: 0,
97
+ framePerSec: 0,
98
+ soundPerSec: 0,
99
+ msgSentPerSec: 0,
100
+ msgRecvPerSec: 0,
101
+ netRecv: 0,
102
+ netSent: 0,
103
+ driveSent: 0,
104
+ driveRecv: 0,
105
+ driveRecvTime: 0,
106
+ driveCacheHit: 0,
107
+ driveCacheMiss: 0,
108
+ driveCacheUsed: 0,
109
+ },
110
+ network: {
111
+ server: (lStorage.getItem("net.server") ?? "netherlands") as any,
112
+ room: randomRoom(),
113
+ ipx: "disconnected",
114
+ },
115
+ ci: false,
116
+ ciStartedAt: 0,
117
+ imageRendering: (lStorage.getItem("imageRendering") ?? "pixelated") as any,
118
+ sockdriveWrite: true,
119
+ };
120
+
121
+ export type DosState = typeof initialState;
122
+
123
+ export const dosSlice = createSlice({
124
+ name: "dos",
125
+ initialState,
126
+ reducers: {
127
+ emuReady: (s, a: { payload: string }) => {
128
+ s.step = "emu-ready";
129
+ s.emuVersion = a.payload;
130
+ },
131
+ emuError: (s, a: { payload: string }) => {
132
+ s.step = "emu-error";
133
+ s.error = a.payload ?? "Unexpeceted error";
134
+ },
135
+ bndLoad: (s, a: { payload: string }) => {
136
+ s.step = "bnd-load";
137
+ s.bundle = a.payload;
138
+ },
139
+ bndError: (s, a: { payload: string }) => {
140
+ s.step = "bnd-error";
141
+ s.error = a.payload ?? "Unexpeceted error";
142
+ },
143
+ bndConfig: (s) => {
144
+ s.step = "bnd-config";
145
+ },
146
+ bndReady: (s, a: { payload: BundleConfig }) => {
147
+ s.step = "bnd-ready";
148
+ s.config = a.payload;
149
+ },
150
+ bndPlay: (s, a) => {
151
+ s.step = "bnd-play";
152
+ (a as unknown as DosAction).asyncStore((store) => {
153
+ postJsDosEvent(getNonSerializableStore(store), "bnd-play");
154
+ });
155
+ },
156
+ dosWorker: (s, a: { payload: boolean }) => {
157
+ s.worker = a.payload;
158
+ lStorage.setItem("worker", s.worker ? "true" : "false");
159
+ },
160
+ dosBackend: (s, a: { payload: Backend }) => {
161
+ s.backend = a.payload as Backend;
162
+ },
163
+ dosBackendLocked: (s, a: { payload: boolean }) => {
164
+ s.backendLocked = a.payload;
165
+ },
166
+ dosBackendHardware: (s, a: { payload: boolean }) => {
167
+ s.backendHardware = a.payload;
168
+ lStorage.setItem("backendHardware", s.backendHardware ? "true" : "false");
169
+ },
170
+ renderBackend: (s, a: { payload: RenderBackend }) => {
171
+ s.renderBackend = a.payload;
172
+ lStorage.setItem("renderBackend", s.renderBackend);
173
+ },
174
+ renderAspect: (s, a: { payload: RenderAspect }) => {
175
+ s.renderAspect = a.payload;
176
+ lStorage.setItem("renderAspect", s.renderAspect);
177
+ },
178
+ imageRendering: (s, a: { payload: ImageRendering }) => {
179
+ s.imageRendering = a.payload;
180
+ lStorage.setItem("imageRendering", s.imageRendering);
181
+ },
182
+ volume: (s, a: { payload: number }) => {
183
+ s.volume = a.payload;
184
+ lStorage.setItem("volume", s.volume + "");
185
+ },
186
+ mouseSensitivity: (s, a: { payload: number }) => {
187
+ s.mouseSensitivity = a.payload;
188
+ lStorage.setItem("mouse_sensitivity", s.mouseSensitivity + "");
189
+ },
190
+ mouseCapture: (s, a: { payload: boolean }) => {
191
+ s.mouseCapture = a.payload;
192
+ },
193
+ paused: (s, a: { payload: boolean }) => {
194
+ s.paused = a.payload;
195
+ },
196
+ stats: (s, a: { payload: EmulatorStats }) => {
197
+ s.stats = a.payload;
198
+ },
199
+ ci: (s, a: { payload: boolean }) => {
200
+ s.ci = a.payload;
201
+ if (a.payload) {
202
+ s.ciStartedAt = Date.now();
203
+ }
204
+ },
205
+ connectIpx: (s, a: { payload: { room: string, address: string } }) => {
206
+ if (s.network.ipx === "connected") {
207
+ throw new Error("Already connected");
208
+ }
209
+
210
+ if (!s.ci) {
211
+ throw new Error("DOS is not started");
212
+ }
213
+
214
+ const { room, address } = a.payload;
215
+ s.network.ipx = "connecting";
216
+ (a as unknown as DosAction).asyncStore((store) => {
217
+ const nonSerializableStore = getNonSerializableStore(store);
218
+ if (!nonSerializableStore.ci) {
219
+ throw new Error("DOS is not started");
220
+ }
221
+
222
+ const canonicalAddress = address.endsWith("/") ?
223
+ address.substring(0, address.length - 1) :
224
+ address;
225
+
226
+ nonSerializableStore.ci.networkConnect(0 /* NetworkType.NETWORK_DOSBOX_IPX */,
227
+ canonicalAddress + ":1900/ipx/" + room.replaceAll("@", "_"))
228
+ .then(() => {
229
+ store.dispatch(dosSlice.actions.statusIpx("connected"));
230
+ })
231
+ .catch((e) => {
232
+ store.dispatch(dosSlice.actions.statusIpx("error"));
233
+ console.error(e);
234
+ });
235
+ });
236
+ },
237
+ statusIpx: (s, a: { payload: "error" | "connected" | "connecting" }) => {
238
+ s.network.ipx = a.payload;
239
+ },
240
+ disconnectIpx: (s, a) => {
241
+ s.network.ipx = "disconnected";
242
+ (a as unknown as DosAction).asyncStore((store) => {
243
+ getNonSerializableStore(store).ci?.networkDisconnect(0 /* IPX */);
244
+ });
245
+ },
246
+ setRoom: (s, a: { payload: string }) => {
247
+ s.network.room = a.payload;
248
+ },
249
+ setServer: (s, a: { payload: typeof initialState.network.server }) => {
250
+ s.network.server = a.payload;
251
+ lStorage.setItem("net.server", a.payload);
252
+ },
253
+ setSockdriveWrite: (s, a: { payload: boolean }) => {
254
+ s.sockdriveWrite = a.payload;
255
+ },
256
+ },
257
+ });
258
+
259
+ let emulatorsReady = false;
260
+ export function initEmulators(store: ReturnType<typeof makeStore>, pathPrefix: string) {
261
+ store.dispatch(async (dispatch) => {
262
+ try {
263
+ if (!emulatorsReady) {
264
+ await initEmulatorsJs(pathPrefix);
265
+ emulatorsReady = true;
266
+ }
267
+ dispatch(dosSlice.actions.emuReady(emulators.version));
268
+ } catch (e) {
269
+ console.error("Unable to init emulators.js", e);
270
+ dispatch(dosSlice.actions.emuError((e as any).message));
271
+ }
272
+ });
273
+ }
274
+
275
+ function initEmulatorsJs(pathPrefix: string) {
276
+ const el = document.querySelector("#emulators.js");
277
+ if (el !== null) {
278
+ return Promise.resolve();
279
+ }
280
+
281
+ return new Promise<void>((resolve, reject) => {
282
+ const script = document.createElement("script");
283
+ script.async = true;
284
+ script.type = "text/javascript";
285
+ script.src = pathPrefix + "emulators.js";
286
+ script.onload = () => {
287
+ emulators.pathPrefix = pathPrefix;
288
+ resolve();
289
+ };
290
+ script.onerror = (err) => {
291
+ reject(new Error("Unable to add emulators.js. Probably you should set the " +
292
+ "'pathPrefix' option to point to the js-dos folder."));
293
+ };
294
+
295
+ document.head.appendChild(script);
296
+ });
297
+ };
298
+
299
+ function randomSymbol() {
300
+ return alphabet[Math.round(Math.random() * (alphabet.length - 1))];
301
+ }
302
+
303
+ function randomRoom() {
304
+ return randomSymbol() + randomSymbol() + randomSymbol();
305
+ }
@@ -0,0 +1,61 @@
1
+ import { createSlice } from "@reduxjs/toolkit";
2
+ import { DosConfig } from "emulators";
3
+ import { Node } from "react-checkbox-tree";
4
+ import { dosboxconf } from "../frame/editor/defaults";
5
+
6
+ const initialState: {
7
+ // step: "empty" | "extract" | "ready" | "error",
8
+ configChanged: boolean,
9
+ bundleConfig: DosConfig | null,
10
+ errorMessage: string | null,
11
+ fs: Node[],
12
+ } = {
13
+ // step: "empty",
14
+ configChanged: false,
15
+ bundleConfig: null,
16
+ errorMessage: null,
17
+ fs: [],
18
+ };
19
+
20
+ export type EditorState = typeof initialState;
21
+
22
+ export const editorSlice = createSlice({
23
+ name: "editor",
24
+ initialState,
25
+ reducers: {
26
+ init: (s, a: { payload: DosConfig | null }) => {
27
+ if (a.payload === null) {
28
+ s.configChanged = true;
29
+ s.bundleConfig = {
30
+ dosboxConf: dosboxconf[0].contents,
31
+ jsdosConf: {
32
+ version: "js-dos-v8",
33
+ },
34
+ };
35
+ } else {
36
+ s.configChanged = false;
37
+ s.bundleConfig = a.payload;
38
+ }
39
+ },
40
+ dosboxConf: (s, a: { payload: string }) => {
41
+ s.configChanged = true;
42
+ s.bundleConfig!.dosboxConf = a.payload;
43
+ },
44
+ // empty: (s) => {
45
+ // s.step = "empty";
46
+ // },
47
+ // extract: (s) => {
48
+ // s.step = "extract";
49
+ // },
50
+ // ready: (s) => {
51
+ // s.step = "ready";
52
+ // },
53
+ // config: (s, a: { payload: DosConfig | null }) => {
54
+ // s.bundleConfig = a.payload;
55
+ // },
56
+ // error: (s, a: { payload: string }) => {
57
+ // s.step = "error";
58
+ // s.errorMessage = a.payload;
59
+ // },
60
+ },
61
+ });
@@ -0,0 +1,48 @@
1
+ import { createSlice } from "@reduxjs/toolkit";
2
+ import { lStorage } from "../host/lstorage";
3
+
4
+ export const sockdriveBackendNames = ["localhost", "js-dos"];
5
+ export type SockdriveBackendName = typeof sockdriveBackendNames[number];
6
+ export const sockdriveBackend: {
7
+ [key: SockdriveBackendName]: {
8
+ sockdriveEndpoint: string,
9
+ sockdriveWssEndpoint: string,
10
+ }
11
+ } = {
12
+ "js-dos": {
13
+ sockdriveEndpoint: "https://backend.make-vm.com:8001",
14
+ sockdriveWssEndpoint: "wss://backend.make-vm.com:8001",
15
+ },
16
+ "localhost": {
17
+ sockdriveEndpoint: "http://localhost:8001",
18
+ sockdriveWssEndpoint: "ws://localhost:8001",
19
+ },
20
+ };
21
+
22
+ export interface InitState {
23
+ uid: string,
24
+ sockdriveBackendName: SockdriveBackendName,
25
+ };
26
+
27
+ let storeUid = -1;
28
+ export function createInitSlice() {
29
+ storeUid += 1;
30
+ return {
31
+ storeUid,
32
+ slice: createSlice({
33
+ name: "init",
34
+ initialState: {
35
+ uid: storeUid,
36
+ sockdriveBackendName: lStorage.getItem("sockdrive.backend.name") ?? "js-dos",
37
+ },
38
+ reducers: {
39
+ setSockdriveBackendName: (state, a: { payload: SockdriveBackendName }) => {
40
+ state.sockdriveBackendName = a.payload;
41
+ lStorage.setItem("sockdrive.backend.name", a.payload);
42
+ },
43
+ },
44
+ }),
45
+ };
46
+ }
47
+
48
+ export const initSlice = createInitSlice().slice;
@@ -0,0 +1,32 @@
1
+ import { createSlice } from "@reduxjs/toolkit";
2
+
3
+ const initialState: {
4
+ recived: number,
5
+ total: number,
6
+ ready: boolean,
7
+ } = {
8
+ recived: 0,
9
+ total: 0,
10
+ ready: false,
11
+ };
12
+
13
+ export type StorageState = typeof initialState;
14
+
15
+ export const storageSlice = createSlice({
16
+ name: "storage",
17
+ initialState,
18
+ reducers: {
19
+ reset: (s) => {
20
+ s.recived = -1;
21
+ s.total = 0;
22
+ s.ready = false;
23
+ },
24
+ progress: (s, a: { payload: [number, number ] }) => {
25
+ s.recived = a.payload[0];
26
+ s.total = a.payload[1];
27
+ },
28
+ ready: (s) => {
29
+ s.ready = true;
30
+ },
31
+ },
32
+ });