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,244 @@
1
+ import { AnyAction } from "@reduxjs/toolkit";
2
+ import { useDispatch, useSelector, useStore } from "react-redux";
3
+ import { LockBadge } from "../components/lock";
4
+ import { State, Store } from "../store";
5
+ import { Frame, uiSlice } from "../store/ui";
6
+ import { DisketteIcon } from "./diskette-icon";
7
+ import { useEffect, useRef, useState } from "preact/hooks";
8
+
9
+ export function ImageRenderingButton(props: {
10
+ class?: string,
11
+ }) {
12
+ return <SidebarButton
13
+ class={props.class}
14
+ frame="image-rendering"
15
+ action={uiSlice.actions.frameImageRendering()}
16
+ >
17
+ <svg xmlns="http://www.w3.org/2000/svg"
18
+ fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
19
+ class="w-full h-full">
20
+ <path stroke-linecap="round"
21
+ stroke-linejoin="round" d="M2.25 15.75l5.159-5.159a2.25 2.25 0
22
+ 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0
23
+ 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5
24
+ 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5
25
+ 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75
26
+ 0 .375.375 0 01.75 0z" />
27
+ </svg>
28
+ </SidebarButton>;
29
+ }
30
+
31
+ export function QuickSaveButton(props: {
32
+ class?: string,
33
+ }) {
34
+ const disabled = useSelector((state: State) => state.auth.account) === null;
35
+ const action = disabled ?
36
+ uiSlice.actions.modalLogin() :
37
+ uiSlice.actions.frameQuickSave();
38
+ return <SidebarButton
39
+ class={props.class + (disabled ? " opacity-50" : "")}
40
+ frame="quick-save"
41
+ action={action}
42
+ >
43
+ <DisketteIcon />
44
+ {disabled && <LockBadge />}
45
+ </SidebarButton>;
46
+ }
47
+
48
+ export function FatDrivesButton(props: {
49
+ class?: string,
50
+ }) {
51
+ return <SidebarButton
52
+ class={props.class}
53
+ frame="fat-drives"
54
+ action={uiSlice.actions.frameFatDrives()}
55
+ >
56
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
57
+ stroke-width="1.5" stroke="currentColor" class="w-full h-full">
58
+ <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5
59
+ 0a3 3 0 01-3-3m3 3a3 3 0 100 6h13.5a3 3 0 100-6m-16.5-3a3 3 0 013-3h13.5a3 3
60
+ 0 013 3m-19.5 0a4.5 4.5 0 01.9-2.7L5.737 5.1a3.375 3.375 0 012.7-1.35h7.126c1.062
61
+ 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 01.9 2.7m0 0a3 3 0 01-3 3m0
62
+ 3h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008zm-3
63
+ 6h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008z" />
64
+ </svg>
65
+ </SidebarButton>;
66
+ }
67
+
68
+ export function DosboxConfButton(props: { class?: string }) {
69
+ return <SidebarButton
70
+ class={props.class}
71
+ frame="editor-conf"
72
+ action={uiSlice.actions.frameConf()}
73
+ >
74
+ <svg xmlns="http://www.w3.org/2000/svg"
75
+ fill="none" viewBox="0 0 24 24"
76
+ stroke-width="1.5"
77
+ stroke="currentColor"
78
+ class="w-full h-full">
79
+ <path stroke-linecap="round"
80
+ stroke-linejoin="round"
81
+ d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125
82
+ 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5
83
+ 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504
84
+ 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
85
+ </svg>
86
+ </SidebarButton>;
87
+ }
88
+
89
+ export function FsButton(props: {
90
+ class?: string,
91
+ }) {
92
+ return <SidebarButton
93
+ class={props.class}
94
+ frame="editor-fs"
95
+ action={uiSlice.actions.frameFs()}
96
+ >
97
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none"
98
+ viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-full h-full">
99
+ <path stroke-linecap="round" stroke-linejoin="round" d="M21.75 17.25v-.228a4.5 4.5
100
+ 0 00-.12-1.03l-2.268-9.64a3.375 3.375 0 00-3.285-2.602H7.923a3.375
101
+ 3.375 0 00-3.285 2.602l-2.268 9.64a4.5 4.5 0 00-.12 1.03v.228m19.5 0a3 3
102
+ 0 01-3 3H5.25a3 3 0 01-3-3m19.5 0a3 3 0 00-3-3H5.25a3 3 0 00-3 3m16.5
103
+ 0h.008v.008h-.008v-.008zm-3 0h.008v.008h-.008v-.008z" />
104
+ </svg>
105
+ </SidebarButton>;
106
+ }
107
+
108
+ export function CyclesButton() {
109
+ const cycles = Math.round(useSelector((state: State) => state.dos.stats.cyclesPerMs) / 1000);
110
+ return <SidebarButton
111
+ class="cycles"
112
+ frame="stats"
113
+ action={uiSlice.actions.frameStats()}>
114
+ { cycles <= 0 && <><span>~</span><sup>KC</sup></> }
115
+ { cycles > 0 && cycles <= 1000 && <><span>{cycles}</span><sup>KC</sup></> }
116
+ { cycles > 0 && cycles > 1000 && <><span>{Math.round(cycles / 1000)}</span><sup><strong>K</strong>KC</sup></> }
117
+ </SidebarButton>;
118
+ }
119
+
120
+ export function HddLed(props: {}) {
121
+ const store: Store = useStore();
122
+ const ref = useRef<HTMLDivElement>(null);
123
+ const [state] = useState<{
124
+ recv: number, enabled: boolean, delayLedTo: number,
125
+ }>({ recv: 0, enabled: false, delayLedTo: 0 });
126
+
127
+ useEffect(() => {
128
+ if (ref.current) {
129
+ const el = ref.current;
130
+ el.classList.add("bg-base-300");
131
+
132
+ const id = setInterval(() => {
133
+ if (state.delayLedTo <= Date.now()) {
134
+ const newRecv = store.getState().dos.stats.driveRecv;
135
+ const newEnabled = state.recv !== newRecv;
136
+ if (newEnabled !== state.enabled) {
137
+ el.classList.remove("bg-base-300", "bg-green-300", "animate-led");
138
+ if (newEnabled) {
139
+ el.classList.add("bg-green-300", "animate-led");
140
+ } else {
141
+ el.classList.add("bg-base-300");
142
+ }
143
+ state.enabled = newEnabled;
144
+ }
145
+
146
+ if (newEnabled) {
147
+ state.delayLedTo = Date.now() + 300 + Math.random() * 1500;
148
+ } else {
149
+ state.delayLedTo = 0;
150
+ }
151
+
152
+ state.recv = newRecv;
153
+ }
154
+ }, 150);
155
+
156
+ return () => {
157
+ el.classList.remove("bg-base-300", "bg-green-300", "animate-led");
158
+ clearInterval(id);
159
+ };
160
+ }
161
+ }, [ref, state]);
162
+ const [on, setOn] = useState<boolean>(false);
163
+ const [off, setOff] = useState<{ recv: number, timeoutId: number | null }>({
164
+ recv: 0,
165
+ timeoutId: null,
166
+ });
167
+ const statsRecv = useSelector((state: State) => state.dos.stats.driveRecv);
168
+ if (off.recv !== statsRecv) {
169
+ if (!on) {
170
+ setOn(true);
171
+ }
172
+
173
+ if (off.timeoutId) {
174
+ clearTimeout(off.timeoutId);
175
+ }
176
+
177
+ const id = setTimeout(() => {
178
+ setOn(false);
179
+ setOff({
180
+ recv: statsRecv,
181
+ timeoutId: null,
182
+ });
183
+ }, 1000);
184
+
185
+ setOff({
186
+ recv: statsRecv,
187
+ timeoutId: id,
188
+ });
189
+ }
190
+ return <div ref={ref} class="self-end mr-2 -mt-3 w-2 h-1"></div>;
191
+ }
192
+
193
+ export function SettingsButton(props: {
194
+ class?: string,
195
+ }) {
196
+ return <SidebarButton
197
+ class={props.class}
198
+ action={uiSlice.actions.frameSettings()}
199
+ frame="settings">
200
+
201
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none"
202
+ viewBox="0 0 24 24" stroke-width="1.5"
203
+ stroke="currentColor" class="w-full h-full">
204
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55
205
+ 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257
206
+ 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26
207
+ 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010
208
+ .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298
209
+ 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0
210
+ 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55
211
+ 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0
212
+ 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0
213
+ 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932
214
+ 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0
215
+ 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072
216
+ 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
217
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
218
+ </svg>
219
+
220
+ </SidebarButton >;
221
+ }
222
+
223
+ export function SidebarButton(props: {
224
+ class?: string,
225
+ frame: Frame,
226
+ action: AnyAction,
227
+ children: any
228
+ }) {
229
+ const hightlight = useSelector((state: State) => state.ui.frame) === props.frame;
230
+ const dispatch = useDispatch();
231
+
232
+ function onClick() {
233
+ if (hightlight) {
234
+ dispatch(uiSlice.actions.frameNone());
235
+ } else {
236
+ dispatch(props.action);
237
+ }
238
+ }
239
+
240
+ return <div class={"sidebar-button " + (hightlight ? "sidebar-highlight " : "") +
241
+ props.class} onClick={onClick}>
242
+ {props.children}
243
+ </div>;
244
+ }
@@ -0,0 +1,47 @@
1
+ .jsdos-rso {
2
+ .sidebar {
3
+ @apply absolute left-0 top-0 h-full flex flex-col items-center py-2 z-10;
4
+ background: linear-gradient(90deg, hsl(var(--b3)) 0%, hsl(var(--b2)) 100%);
5
+ width: var(--sidebar-width);
6
+
7
+ .contentbar {
8
+ @apply flex-grow;
9
+ }
10
+
11
+ .sidebar-badge {
12
+ @apply absolute right-0 bottom-0 w-3 h-3 rounded-full animate-pulse;
13
+ background-color: hsl(var(--p));
14
+ }
15
+
16
+ .cycles {
17
+ @apply text-xs overflow-hidden text-right w-full pr-2 mt-1 -mb-2 whitespace-nowrap opacity-50;
18
+ color: hsl(var(--bc));
19
+
20
+ &.higlight,
21
+ &:hover {
22
+ color: hsl(var(--af));
23
+ }
24
+ }
25
+
26
+ .network-button {
27
+ &.inactive {
28
+ @apply opacity-50;
29
+ }
30
+ }
31
+ }
32
+
33
+ .sidebar-button {
34
+ @apply cursor-pointer h-8 w-8 my-2 relative;
35
+ color: hsl(var(--bc));
36
+ }
37
+
38
+ .sidebar-highlight,
39
+ .sidebar-button:hover {
40
+ color: hsl(var(--af));
41
+ }
42
+
43
+ .animate-led {
44
+ animation: pulse 300ms cubic-bezier(0.4, 0, 0.6, 1) infinite;
45
+ }
46
+
47
+ }
@@ -0,0 +1,30 @@
1
+ import { useSelector } from "react-redux";
2
+ import { State } from "../store";
3
+ import { AccountButton } from "./account-button";
4
+ import { FullscreenButton } from "./fullscreen-button";
5
+ import { NetworkButton } from "./network-button";
6
+ import { CloudSaveButton } from "./cloud-save-button";
7
+ import { DosboxConfButton, SettingsButton, CyclesButton, FsButton,
8
+ FatDrivesButton, QuickSaveButton, ImageRenderingButton, HddLed } from "./sidebar-button";
9
+
10
+ export function SideBar(props: {}) {
11
+ const window = useSelector((state: State) => state.ui.window);
12
+ const editor = useSelector((state: State) => state.ui.editor);
13
+ const backend = useSelector((state: State) => state.dos.backend);
14
+
15
+ return <div class="sidebar">
16
+ {window === "run" && backend === "dosbox" && <CloudSaveButton />}
17
+ {window === "run" && backend === "dosboxX" && <QuickSaveButton />}
18
+ {window === "run" && <ImageRenderingButton />}
19
+ {window === "run" && <NetworkButton />}
20
+ {editor && window === "prerun" && <DosboxConfButton />}
21
+ {editor && window === "prerun" && backend === "dosboxX" && <FatDrivesButton />}
22
+ {editor && window === "run" && <FsButton />}
23
+ <div class="contentbar"></div>
24
+ {window === "run" && <FullscreenButton />}
25
+ {window === "run" && <CyclesButton />}
26
+ {window === "run" && <HddLed />}
27
+ {(window === "prerun" || window === "run") && <SettingsButton />}
28
+ {window !== "run" && <AccountButton />}
29
+ </div>;
30
+ };