diff --git a/src/app/App.tsx b/src/app/App.tsx
index 02777c1..b708978 100644
--- a/src/app/App.tsx
+++ b/src/app/App.tsx
@@ -1,20 +1,24 @@
-import { useEffect, useState } from 'react';
+import { lazy, Suspense, useEffect, useState } from 'react';
import { Cpu, Settings, Wifi, Network, HardDrive, Activity, Search, Wrench, User, LogOut, Bell, FileText, AppWindow, Folder, Edit, Eye, Database, Upload, Download, Code2, LayoutList, Image, ChevronLeft, Loader2, Terminal, Link, Printer, Maximize2, Minimize2 } from 'lucide-react';
import { Toaster, toast } from 'sonner';
-import StatusPage from './components/StatusPage';
-import DevicesPage from './components/DevicesPage';
-import GeneralPage from './components/GeneralPage';
-import NetworkPage from './components/NetworkPage';
-import IECPage from './components/IECPage';
-import ToolsPage from './components/ToolsPage';
-import SearchOverlay from './components/SearchOverlay';
-import MediaManager from './components/MediaManager';
-import RealityOverridePage from './components/RealityOverridePage';
+import StatusPage from './components/StatusPage';
+import DevicesPage from './components/DevicesPage';
+import GeneralPage from './components/GeneralPage';
+import NetworkPage from './components/NetworkPage';
+import IECPage from './components/IECPage';
+import ToolsPage from './components/ToolsPage';
+import SearchOverlay from './components/SearchOverlay';
import RealityOverrideAdminPage from './components/RealityOverrideAdminPage';
+import MediaManager from './components/MediaManager';
import logoSvg from '../imports/logo.svg';
import { useSettings } from './settings';
import { WsProvider } from './ws';
+// Three.js lives only in RealityOverridePage — keep lazy so it doesn't load on startup.
+// CodeMirror/syntax-highlighter/ReactMarkdown live in MediaViewerEditor — lazy-loaded
+// inside MediaManager when the user first opens a file to view or edit.
+const RealityOverridePage = lazy(() => import('./components/RealityOverridePage'));
+
type Page = 'status' | 'devices' | 'iec' | 'network' | 'general' | 'tools' | 'apps' | AppId;
type AppId =
@@ -41,6 +45,14 @@ type AppId =
| 'reality-override'
| 'reality-override-admin';
+function PageLoader() {
+ return (
+
+
+
+ );
+}
+
export default function App() {
const [currentPage, setCurrentPage] = useState('status');
const { config, setConfig, saveStatus, pendingCount, flushNow, reload } = useSettings();
@@ -90,17 +102,16 @@ export default function App() {
};
const pages = {
- status: ,
+ status: ,
devices: setDevicesOpenId(null)} />,
- iec: ,
- network: ,
- general: ,
- tools: ,
+ iec: ,
+ network: ,
+ general: ,
+ tools: ,
apps: (
Apps
- {/* Manangement Group */}
Management
@@ -110,7 +121,6 @@ export default function App() {
} label="Short Codes" onClick={() => setCurrentPage('serial-console')} />
- {/* Disk Group */}
Disk
@@ -123,7 +133,6 @@ export default function App() {
} label="Write Disk Image" onClick={() => setCurrentPage('write-disk-image')} />
- {/* Cartridge Group */}
Cartridge
@@ -132,7 +141,6 @@ export default function App() {
} label="Easy Flash Cart Builder" onClick={() => setCurrentPage('easy-flash-cart-builder')} />
- {/* Development Group */}
Development
@@ -143,7 +151,6 @@ export default function App() {
} label="Petscii Editor" onClick={() => setCurrentPage('petscii-editor')} />
- {/* Display Group */}
Display
@@ -156,7 +163,6 @@ export default function App() {
),
- // Individual app pages
'file-manager':
setCurrentPage('apps')}
config={config}
@@ -170,26 +176,26 @@ export default function App() {
config={config}
setConfig={setConfig}
/>,
- 'serial-console': setCurrentPage('apps')} />,
- 'directory-editor': setCurrentPage('apps')} />,
- 'sector-editor': setCurrentPage('apps')} />,
- 'bam-editor': setCurrentPage('apps')} />,
- 'disk-visualizer': setCurrentPage('apps')} />,
- 'ramrom-explorer': setCurrentPage('apps')} />,
- 'dump-disk-image': setCurrentPage('apps')} />,
- 'write-disk-image': setCurrentPage('apps')} />,
- 'prg-to-crt': setCurrentPage('apps')} />,
- 'magic-desk-cart-builder': setCurrentPage('apps')} />,
+ 'serial-console': setCurrentPage('apps')} />,
+ 'directory-editor': setCurrentPage('apps')} />,
+ 'sector-editor': setCurrentPage('apps')} />,
+ 'bam-editor': setCurrentPage('apps')} />,
+ 'disk-visualizer': setCurrentPage('apps')} />,
+ 'ramrom-explorer': setCurrentPage('apps')} />,
+ 'dump-disk-image': setCurrentPage('apps')} />,
+ 'write-disk-image': setCurrentPage('apps')} />,
+ 'prg-to-crt': setCurrentPage('apps')} />,
+ 'magic-desk-cart-builder': setCurrentPage('apps')} />,
'easy-flash-cart-builder': setCurrentPage('apps')} />,
- 'basic-editor': setCurrentPage('apps')} />,
- 'assembler': setCurrentPage('apps')} />,
- 'sprite-editor': setCurrentPage('apps')} />,
- 'charset-editor': setCurrentPage('apps')} />,
- 'petscii-editor': setCurrentPage('apps')} />,
- 'idle-animation': setCurrentPage('apps')} />,
- 'loading-animation': setCurrentPage('apps')} />,
- 'reality-override': setCurrentPage('apps')} />,
- 'reality-override-admin': setCurrentPage('apps')} />
+ 'basic-editor': setCurrentPage('apps')} />,
+ 'assembler': setCurrentPage('apps')} />,
+ 'sprite-editor': setCurrentPage('apps')} />,
+ 'charset-editor': setCurrentPage('apps')} />,
+ 'petscii-editor': setCurrentPage('apps')} />,
+ 'idle-animation': setCurrentPage('apps')} />,
+ 'loading-animation': setCurrentPage('apps')} />,
+ 'reality-override': setCurrentPage('apps')} />,
+ 'reality-override-admin': setCurrentPage('apps')} />,
};
// AppCard component for app grid
@@ -263,10 +269,7 @@ function AppPage({ title, onBack }: { title: string; onBack: () => void }) {
{showProfileMenu && (
);
}
-
diff --git a/src/app/components/MediaManager.tsx b/src/app/components/MediaManager.tsx
index 15ae647..5eba12d 100644
--- a/src/app/components/MediaManager.tsx
+++ b/src/app/components/MediaManager.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { lazy, Suspense, useCallback, useEffect, useRef, useState } from 'react';
import {
AlignLeft,
ArrowLeft,
@@ -26,7 +26,6 @@ import {
Move,
Pencil,
RefreshCw,
- Save,
Search,
SlidersHorizontal,
Terminal,
@@ -35,15 +34,9 @@ import {
X,
} from 'lucide-react';
import { MediaEntry, TEXT_EXTS, DOC_EXTS, CODE_EXTS, MD_EXTS, JSON_EXTS, XML_EXTS, IMAGE_EXTS, CONFIG_EXTS } from './MediaEntry';
-import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
-import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
-import ReactMarkdown from 'react-markdown';
-import remarkGfm from 'remark-gfm';
-import CodeMirror, { EditorView } from '@uiw/react-codemirror';
-import { oneDark } from '@codemirror/theme-one-dark';
-import HexEditor from './HexEditor';
-import CodeEditor from './CodeEditor';
-import ConfigEditor from './ConfigEditor';
+import type { ViewMode } from './MediaViewerEditor';
+const MediaViewerEditor = lazy(() => import('./MediaViewerEditor'));
+
import {
copyPath,
createFolder,
@@ -71,9 +64,8 @@ import {
// ─── Types ───────────────────────────────────────────────────────────────────
-type SortKey = 'name' | 'size' | 'date';
-type Clipboard = { op: 'copy' | 'move'; paths: string[] };
-type ViewMode = 'text' | 'markdown' | 'json' | 'xml' | 'hex' | 'image' | 'config' | 'code' | 'doc';
+type SortKey = 'name' | 'size' | 'date';
+type Clipboard = { op: 'copy' | 'move'; paths: string[] };
// Extension sets are imported from MediaEntry.
@@ -111,17 +103,7 @@ const VIEWER_LABEL: Record = {
code: 'Code', text: 'Text', markdown: 'Markdown', json: 'JSON', xml: 'HTML/XML', hex: 'Hex', image: 'Image', config: 'Config', doc: 'Document',
};
-const EXT_TO_LANG: Record = {
- asm: 'nasm', s: 'nasm', bas: 'basic',
- js: 'javascript', ts: 'typescript', jsx: 'jsx', tsx: 'tsx',
- css: 'css', scss: 'scss',
- py: 'python', c: 'c', cpp: 'cpp', h: 'cpp', hpp: 'cpp',
- lua: 'lua', sh: 'bash', bash: 'bash',
- php: 'php', rb: 'ruby', rs: 'rust', go: 'go',
- java: 'java', cs: 'csharp', kt: 'kotlin', sql: 'sql', pl: 'perl',
-};
-
-// ─── Viewer components ───────────────────────────────────────────────────────
+// ─── Viewer helpers ───────────────────────────────────────────────────────────
function ViewerModeIcon({ mode, className }: { mode: ViewMode; className?: string }) {
const cls = className ?? 'w-4 h-4';
@@ -138,112 +120,6 @@ function ViewerModeIcon({ mode, className }: { mode: ViewMode; className?: strin
}
}
-function MarkdownViewer({ text }: { text: string }) {
- return (
-
-
{children}
,
- h2: ({ children }) => {children}
,
- h3: ({ children }) => {children}
,
- p: ({ children }) => {children}
,
- a: ({ href, children }) => {children},
- code: ({ className, children, ...props }) => {
- const match = /language-(\w+)/.exec(className ?? '');
- const inline = !match && !String(children).includes('\n');
- return inline
- ? {children}
- : (
-
-
- {String(children).replace(/\n$/, '')}
-
-
- );
- },
- pre: ({ children }) => <>{children}>,
- blockquote: ({ children }) => {children}
,
- ul: ({ children }) => ,
- ol: ({ children }) => {children}
,
- li: ({ children }) => {children},
- hr: () =>
,
- table: ({ children }) => ,
- th: ({ children }) => {children} | ,
- td: ({ children }) => {children} | ,
- strong: ({ children }) => {children},
- img: ({ src, alt }) =>
,
- }}
- >
- {text}
-
-
- );
-}
-
-const CM_THEME = EditorView.theme({
- '&': { height: '100%', background: '#0a0a0a' },
- '.cm-scroller': { overflow: 'auto', fontFamily: 'ui-monospace,monospace', fontSize: '12px', lineHeight: '1.5' },
- '.cm-content': { padding: '12px 0' },
- '.cm-focused': { outline: 'none' },
-});
-
-function MarkdownEditor({ text, onSave }: { text: string; onSave?: (s: string) => Promise }) {
- const [editMode, setEditMode] = useState(false);
- const [editInitText, setEditInitText] = useState('');
- const [saving, setSaving] = useState(false);
- const editorViewRef = useRef(null);
-
- const save = async () => {
- if (!editorViewRef.current || !onSave) return;
- setSaving(true);
- try { await onSave(editorViewRef.current.state.doc.toString()); }
- finally { setSaving(false); }
- };
-
- return (
-
-
- {onSave && (
-
{ if (!editMode) setEditInitText(text); setEditMode(v => !v); }}
- className={editMode
- ? 'px-2 py-1 rounded bg-amber-600 text-white inline-flex items-center gap-1'
- : 'px-2 py-1 rounded bg-neutral-700 text-neutral-300 hover:bg-neutral-600 inline-flex items-center gap-1'}
- >
- {editMode ? <> View> : <> Edit>}
-
- )}
- {editMode && onSave && (
-
void save()} disabled={saving}
- className="px-2 py-1 rounded bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50 inline-flex items-center gap-1">
- {saving ? 'Saving…' : 'Save'}
-
- )}
- {editMode &&
Ctrl+Z/Y undo · Ctrl+F search}
-
- {editMode ? (
-
- { editorViewRef.current = v; }}
- />
-
- ) : (
-
- )}
-
- );
-}
-
// EntryIcon is imported from MediaEntry.
// ─── ActionsModal ─────────────────────────────────────────────────────────────
@@ -1229,71 +1105,27 @@ export default function MediaManager({ initialPath = '/', rootPath, title, confi
} : undefined}
/>
- {/* ── File viewer overlay ── */}
- {viewEntry && (
-
- {/* Title + mode switcher */}
-
-
-
-
-
{viewEntry.name}
-
- {viewMode && availableViewers(viewEntry).map(mode => (
- void switchViewMode(mode)}
- title={VIEWER_LABEL[mode]}
- className={`px-2 py-1 rounded text-xs inline-flex items-center gap-1 transition-colors ${
- viewMode === mode
- ? 'bg-blue-600 text-white'
- : 'text-neutral-400 hover:bg-neutral-700 hover:text-white'
- }`}
- >
-
- {VIEWER_LABEL[mode]}
-
- ))}
-
-
void downloadEntry(viewEntry)} className="p-1.5 rounded hover:bg-neutral-700 text-neutral-300 hover:text-white" title="Download">
-
-
+ {/* ── File viewer overlay (lazy-loaded) ── */}
+ {viewEntry && viewMode && (
+
+
-
-
- {viewLoading && (
-
- Loading…
-
- )}
- {!viewLoading && viewMode === 'image' && viewImgUrl && (
-
-

-
- )}
- {!viewLoading && viewMode === 'hex' && viewHexData && (
-
saveViewFile(d)} />
- )}
- {!viewLoading && viewMode === 'markdown' && viewText !== null && (
- saveViewFile(s)} />
- )}
- {!viewLoading && (viewMode === 'text' || viewMode === 'json' || viewMode === 'xml') && viewText !== null && (
- saveViewFile(s)} />
- )}
- {!viewLoading && viewMode === 'config' && viewText !== null && (
- saveViewFile(s)} />
- )}
- {!viewLoading && viewMode === 'code' && viewText !== null && (
- saveViewFile(s)}
- />
- )}
-
-
+ }>
+ void switchViewMode(m)}
+ onSave={saveViewFile}
+ onDownload={() => void downloadEntry(viewEntry)}
+ />
+
)}
{/* ── Mount dialog ── */}
diff --git a/src/app/components/MediaViewerEditor.tsx b/src/app/components/MediaViewerEditor.tsx
new file mode 100644
index 0000000..5fb293f
--- /dev/null
+++ b/src/app/components/MediaViewerEditor.tsx
@@ -0,0 +1,251 @@
+import { useRef, useState } from 'react';
+import {
+ AlignLeft,
+ Book,
+ BookOpen,
+ Braces,
+ Code2,
+ Download,
+ Eye,
+ Hash,
+ Image as ImageIcon,
+ Loader2,
+ Pencil,
+ Save,
+ SlidersHorizontal,
+ Terminal,
+ X,
+} from 'lucide-react';
+import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
+import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
+import ReactMarkdown from 'react-markdown';
+import remarkGfm from 'remark-gfm';
+import CodeMirror, { EditorView } from '@uiw/react-codemirror';
+import { oneDark } from '@codemirror/theme-one-dark';
+import HexEditor from './HexEditor';
+import CodeEditor from './CodeEditor';
+import ConfigEditor from './ConfigEditor';
+import type { EntryInfo } from '../webdav';
+
+export type ViewMode = 'text' | 'markdown' | 'json' | 'xml' | 'hex' | 'image' | 'config' | 'code' | 'doc';
+
+const VIEWER_LABEL: Record = {
+ code: 'Code', text: 'Text', markdown: 'Markdown', json: 'JSON', xml: 'HTML/XML',
+ hex: 'Hex', image: 'Image', config: 'Config', doc: 'Document',
+};
+
+const EXT_TO_LANG: Record = {
+ asm: 'nasm', s: 'nasm', bas: 'basic',
+ js: 'javascript', ts: 'typescript', jsx: 'jsx', tsx: 'tsx',
+ css: 'css', scss: 'scss',
+ py: 'python', c: 'c', cpp: 'cpp', h: 'cpp', hpp: 'cpp',
+ lua: 'lua', sh: 'bash', bash: 'bash',
+ php: 'php', rb: 'ruby', rs: 'rust', go: 'go',
+ java: 'java', cs: 'csharp', kt: 'kotlin', sql: 'sql', pl: 'perl',
+};
+
+function ViewerModeIcon({ mode, className }: { mode: ViewMode; className?: string }) {
+ const cls = className ?? 'w-4 h-4';
+ switch (mode) {
+ case 'text': return ;
+ case 'markdown': return ;
+ case 'json': return ;
+ case 'code': return ;
+ case 'xml': return ;
+ case 'hex': return ;
+ case 'image': return ;
+ case 'config': return ;
+ case 'doc': return ;
+ }
+}
+
+function MarkdownViewer({ text }: { text: string }) {
+ return (
+
+
{children}
,
+ h2: ({ children }) => {children}
,
+ h3: ({ children }) => {children}
,
+ p: ({ children }) => {children}
,
+ a: ({ href, children }) => {children},
+ code: ({ className, children, ...props }) => {
+ const match = /language-(\w+)/.exec(className ?? '');
+ const inline = !match && !String(children).includes('\n');
+ return inline
+ ? {children}
+ : (
+
+
+ {String(children).replace(/\n$/, '')}
+
+
+ );
+ },
+ pre: ({ children }) => <>{children}>,
+ blockquote: ({ children }) => {children}
,
+ ul: ({ children }) => ,
+ ol: ({ children }) => {children}
,
+ li: ({ children }) => {children},
+ hr: () =>
,
+ table: ({ children }) => ,
+ th: ({ children }) => {children} | ,
+ td: ({ children }) => {children} | ,
+ strong: ({ children }) => {children},
+ img: ({ src, alt }) =>
,
+ }}
+ >
+ {text}
+
+
+ );
+}
+
+const CM_THEME = EditorView.theme({
+ '&': { height: '100%', background: '#0a0a0a' },
+ '.cm-scroller': { overflow: 'auto', fontFamily: 'ui-monospace,monospace', fontSize: '12px', lineHeight: '1.5' },
+ '.cm-content': { padding: '12px 0' },
+ '.cm-focused': { outline: 'none' },
+});
+
+function MarkdownEditor({ text, onSave }: { text: string; onSave?: (s: string) => Promise }) {
+ const [editMode, setEditMode] = useState(false);
+ const [editInitText, setEditInitText] = useState('');
+ const [saving, setSaving] = useState(false);
+ const editorViewRef = useRef(null);
+
+ const save = async () => {
+ if (!editorViewRef.current || !onSave) return;
+ setSaving(true);
+ try { await onSave(editorViewRef.current.state.doc.toString()); }
+ finally { setSaving(false); }
+ };
+
+ return (
+
+
+ {onSave && (
+
{ if (!editMode) setEditInitText(text); setEditMode(v => !v); }}
+ className={editMode
+ ? 'px-2 py-1 rounded bg-amber-600 text-white inline-flex items-center gap-1'
+ : 'px-2 py-1 rounded bg-neutral-700 text-neutral-300 hover:bg-neutral-600 inline-flex items-center gap-1'}
+ >
+ {editMode ? <> View> : <> Edit>}
+
+ )}
+ {editMode && onSave && (
+
void save()} disabled={saving}
+ className="px-2 py-1 rounded bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50 inline-flex items-center gap-1">
+ {saving ? 'Saving…' : 'Save'}
+
+ )}
+ {editMode &&
Ctrl+Z/Y undo · Ctrl+F search}
+
+ {editMode ? (
+
+ { editorViewRef.current = v; }}
+ />
+
+ ) : (
+
+ )}
+
+ );
+}
+
+export interface MediaViewerEditorProps {
+ entry: EntryInfo;
+ mode: ViewMode;
+ availableModes: ViewMode[];
+ text: string | null;
+ imgUrl: string | null;
+ hexData: Uint8Array | null;
+ loading: boolean;
+ onClose: () => void;
+ onSwitchMode: (mode: ViewMode) => void;
+ onSave: (content: string | Uint8Array) => Promise;
+ onDownload: () => void;
+}
+
+export default function MediaViewerEditor({
+ entry, mode, availableModes, text, imgUrl, hexData, loading,
+ onClose, onSwitchMode, onSave, onDownload,
+}: MediaViewerEditorProps) {
+ return (
+
+ {/* Title + mode switcher */}
+
+
+
+
+
{entry.name}
+
+ {availableModes.map(m => (
+ onSwitchMode(m)}
+ title={VIEWER_LABEL[m]}
+ className={`px-2 py-1 rounded text-xs inline-flex items-center gap-1 transition-colors ${
+ mode === m
+ ? 'bg-blue-600 text-white'
+ : 'text-neutral-400 hover:bg-neutral-700 hover:text-white'
+ }`}
+ >
+
+ {VIEWER_LABEL[m]}
+
+ ))}
+
+
+
+
+
+
+
+ {loading && (
+
+ Loading…
+
+ )}
+ {!loading && mode === 'image' && imgUrl && (
+
+

+
+ )}
+ {!loading && mode === 'hex' && hexData && (
+
void onSave(d)} />
+ )}
+ {!loading && mode === 'markdown' && text !== null && (
+ onSave(s)} />
+ )}
+ {!loading && (mode === 'text' || mode === 'json' || mode === 'xml') && text !== null && (
+ onSave(s)} />
+ )}
+ {!loading && mode === 'config' && text !== null && (
+ onSave(s)} />
+ )}
+ {!loading && mode === 'code' && text !== null && (
+ onSave(s)}
+ />
+ )}
+
+
+ );
+}
diff --git a/src/imports/config.json b/src/imports/config.json
index b9892fb..83f2905 100644
--- a/src/imports/config.json
+++ b/src/imports/config.json
@@ -1,10 +1,10 @@
{
"general": {
- "appearance": "light|dark|auto",
- "language": "en|es|de",
- "timezone": "America/Los_Angeles",
- "country": "US",
"devicename": "Meatloaf",
+ "appearance": "light",
+ "language": "en",
+ "timezone": "America/New_York",
+ "country": "US",
"hsioindex": -1,
"rotationsounds": 1,
"configenabled": 1,
@@ -16,17 +16,17 @@
"reset_with_host": 0
},
"host": {
- "model": "c64|c64c|c128|sx64|plus4|c16|cx16|foenix|dtv|pet",
- "video": "ntsc|pal",
+ "model": "c64",
+ "video": "ntsc",
"language": "en",
- "kernal": "stock|jiffydos|dolphindos|speeddos",
- "basic": "2|3|7|10"
+ "kernal": "Stock",
+ "basic": "BASIC 2.0"
},
"hardware": {
"ps2": 1,
"userport": {
"enabled": 0,
- "mode": "serial|parallel|IEEE-488"
+ "mode": ""
}
},
"wifi": [
@@ -63,8 +63,8 @@
}
},
"bluetooth": {
- "devicename": "meatloaf",
"enabled": 0,
+ "devicename": "meatloaf",
"baud": 19200
},
"modem": {
@@ -81,13 +81,13 @@
"enabled": 1,
"vic20_mode": 0,
"vdrive": 0,
- "boot_disk": "/autoboot[.PRG|.D64|.D81|etc]",
+ "boot_disk": "",
"rom": {
- "enabled": 1,
- "default": "dos1541|dos1541.jd|dos1541ii|dos1541ii.jd|dos1571|dos1571.jd|dos1581|dos1581.jd",
- "d64": "dos1541|dos1541.jd|dos1541ii|dos1541ii.jd",
- "d71": "dos1571|dos1571.jd",
- "d81": "dos1581|dos1581.jd"
+ "enabled": 0,
+ "default": "",
+ "d64": "",
+ "d71": "",
+ "d81": ""
},
"directory": {
"force_0801": 1,
@@ -149,43 +149,43 @@
"mode": 1
},
"9": {
- "enabled": 1,
+ "enabled": 0,
"type": "drive",
"url": "/",
"mode": 1
},
"10": {
- "enabled": 1,
+ "enabled": 0,
"type": "drive",
"url": "/",
"mode": 1
},
"11": {
- "enabled": 1,
+ "enabled": 0,
"type": "drive",
"url": "/",
"mode": 1
},
"12": {
- "enabled": 1,
+ "enabled": 0,
"type": "drive",
"url": "/",
"mode": 1
},
"13": {
- "enabled": 1,
+ "enabled": 0,
"type": "drive",
"url": "/",
"mode": 1
},
"14": {
- "enabled": 1,
+ "enabled": 0,
"type": "drive",
"url": "/",
"mode": 1
},
"15": {
- "enabled": 1,
+ "enabled": 0,
"type": "drive",
"url": "/",
"mode": 1
@@ -196,32 +196,32 @@
"url": "/sd"
},
"17": {
- "enabled": 1,
+ "enabled": 0,
"type": "network",
"url": "/"
},
"18": {
- "enabled": 1,
+ "enabled": 0,
"type": "network",
"url": "/"
},
"19": {
- "enabled": 1,
+ "enabled": 0,
"type": "network",
"url": "/"
},
"20": {
- "enabled": 1,
+ "enabled": 0,
"type": "other",
"name": "CP/m"
},
"21": {
- "enabled": 1,
+ "enabled": 0,
"type": "other",
"name": "S.A.M"
},
"29": {
- "enabled": 1,
+ "enabled": 0,
"type": "other",
"name": "Clock"
},