Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions public/madness/2026/angle-bracket-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/madness/2026/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion public/madness/2026/discord.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
132 changes: 132 additions & 0 deletions public/madness/2026/doom.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Play DOOM</title>
<link rel="stylesheet" href="index.css" />
<link rel="icon" type="image/svg+xml" href="favicon-96x96.png" />
<style>
:root {
--canvas-width: 1200px;
}

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
font-family: 'Courier New', monospace;
color: #fff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
}

#dosbox {
width: 90%;
max-width: var(--canvas-width);
aspect-ratio: 1.6/1;
border: 4px solid #333;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.8);
z-index: 10;
}

#dosbox .play-button {
max-width: var(--canvas-width);
aspect-ratio: 1.6/1;
}

.controls {
margin-top: 20px;
text-align: center;
font-size: 0.9em;
color: #888;
max-width: var(--canvas-width);
z-index: 20;
}
.controls h3 {
color: var(--red);
margin-bottom: 10px;
}
.controls-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
text-align: left;
margin-top: 10px;
}
.control-item {
background: rgba(0, 0, 0, 0.9);
padding: 8px;
border-radius: 4px;
}

.key {
color: var(--lightred);
font-weight: bold;
}

.sidebar {
display: none !important;
}

.header {
position: static;
width: 100%;
z-index: 20;
padding-top: 0;
display: flex;
justify-content: center;
align-items: center;
padding-bottom: 1rem;
}

.header a {
min-width: 40rem;
}
</style>
</head>
<body>
<div class="header">
<a href="/"><img class="logo" src="mm-logotext.svg" alt="mountain madness" /></a>
</div>
<div id="sky"></div>
<div id="stars"></div>
<div id="peak">
<picture class="mountain-svg">
<source srcset="mountain_sm.svg" media="(width < 1280px)" />
<img src="mountain.svg" alt="mountain" />
</picture>
</div>
<div id="dosbox"></div>
<div class="controls">
<h3>Controls</h3>
<div class="controls-grid">
<div class="control-item"><span class="key">Arrow Keys</span> - Move/Turn</div>
<div class="control-item"><span class="key">S</span> - Shoot</div>
<div class="control-item"><span class="key">A</span> - Strafe Left</div>
<div class="control-item"><span class="key">D</span> - Strafe Right</div>
<div class="control-item"><span class="key">W</span> - Use/Open Doors</div>
<div class="control-item"><span class="key">1-7</span> - Select Weapon</div>
<div class="control-item"><span class="key">Tab</span> - Map</div>
<div class="control-item"><span class="key">ESC</span> - Menu</div>
<div class="control-item"><span class="key">Enter</span> - Select Menu Item</div>
</div>
</div>

<script src="doom/js-dos.js"></script>
<script>
Dos(document.getElementById('dosbox'), {
url: 'doom/doom.jsdos'
});
</script>
</body>
</html>
Binary file added public/madness/2026/doom/doom.jsdos
Binary file not shown.
2 changes: 2 additions & 0 deletions public/madness/2026/doom/emulators/emulators.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/madness/2026/doom/emulators/emulators.js.map

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions public/madness/2026/doom/emulators/types/build.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export declare const Build: {
version: string;
buildSeed: number;
"wdosbox-x.wasm": {
size: number;
gzSize: number;
};
"wdosbox-x.js": {
size: number;
gzSize: number;
};
"wdosbox.wasm": {
size: number;
gzSize: number;
};
"wdosbox.js": {
size: number;
gzSize: number;
};
"wlibzip.wasm": {
size: number;
gzSize: number;
};
"wlibzip.js": {
size: number;
gzSize: number;
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { WasmModule } from "../../impl/modules";
export interface DosArchiveSource {
url: string;
path: string;
type?: "zip";
}
export default class DosBundle {
dosboxConf: string;
jsdosConf: {
version: string;
};
sources: DosArchiveSource[];
private libzipWasm;
constructor(libzipWasm: WasmModule);
autoexec(...lines: string[]): DosBundle;
extract(url: string, path?: string, type?: "zip"): DosBundle;
extractAll(sources: DosArchiveSource[]): DosBundle;
toUint8Array(overwriteConfig?: boolean): Promise<Uint8Array>;
}
export declare const defaultConfig: string;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { WasmModule } from "../../../impl/modules";
import { TransportLayer } from "../../../protocol/protocol";
export declare function dosDirect(wasmModule: WasmModule, sessionId: string): Promise<TransportLayer>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { WasmModule } from "../../../impl/modules";
import { TransportLayer } from "../../../protocol/protocol";
export declare function dosWorker(workerUrl: string, wasmModule: WasmModule, sessionId: string): Promise<TransportLayer>;
84 changes: 84 additions & 0 deletions public/madness/2026/doom/emulators/types/emulators.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import DosBundle from "./dos/bundle/dos-bundle";
import { AsyncifyStats, TransportLayer, FsNode } from "./protocol/protocol";
export interface DosConfig {
dosboxConf: string;
jsdosConf: {
version: string;
};
}
export declare enum NetworkType {
NETWORK_DOSBOX_IPX = 0
}
export interface BackendOptions {
token?: string | undefined;
onExtractProgress?: (bundleIndex: number, file: string, extracted: number, total: number) => void;
}
export type InitBundleEntry = Uint8Array;
export interface InitFileEntry {
path: string;
contents: Uint8Array;
}
export type InitFsEntry = InitBundleEntry | InitFileEntry | DosConfig | string;
export type InitFs = InitFsEntry | InitFsEntry[];
export type PersistedSockdrives = {
drives: {
url: string;
persist: Uint8Array;
}[];
} | null;
export interface Emulators {
pathPrefix: string;
pathSuffix: string;
version: string;
wdosboxJs: string;
bundle: () => Promise<DosBundle>;
bundleConfig: (bundle: InitBundleEntry) => Promise<DosConfig | null>;
bundleUpdateConfig: (bundle: InitBundleEntry, config: DosConfig) => Promise<Uint8Array>;
dosboxNode: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
dosboxDirect: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
dosboxWorker: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
dosboxXNode: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
dosboxXDirect: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
dosboxXWorker: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
backend: (init: InitFs, transportLayer: TransportLayer, options?: BackendOptions) => Promise<CommandInterface>;
}
export interface CommandInterface {
config: () => Promise<DosConfig>;
height: () => number;
width: () => number;
soundFrequency: () => number;
screenshot: () => Promise<ImageData>;
pause: () => void;
resume: () => void;
mute: () => void;
unmute: () => void;
exit: () => Promise<void>;
simulateKeyPress: (...keyCodes: number[]) => void;
sendKeyEvent: (keyCode: number, pressed: boolean) => void;
sendMouseMotion: (x: number, y: number) => void;
sendMouseRelativeMotion: (x: number, y: number) => void;
sendMouseButton: (button: number, pressed: boolean) => void;
sendMouseSync: () => void;
sendBackendEvent: (event: any) => void;
persist(onlyChanges?: boolean): Promise<Uint8Array | PersistedSockdrives | null>;
events(): CommandInterfaceEvents;
networkConnect(networkType: NetworkType, address: string): Promise<void>;
networkDisconnect(networkType: NetworkType): Promise<void>;
asyncifyStats(): Promise<AsyncifyStats>;
fsTree(): Promise<FsNode>;
fsReadFile(file: string): Promise<Uint8Array>;
fsWriteFile(file: string, contents: ReadableStream<Uint8Array> | Uint8Array): Promise<void>;
fsDeleteFile(file: string): Promise<boolean>;
}
export type MessageType = "log" | "warn" | "error" | string;
export interface CommandInterfaceEvents {
onStdout: (consumer: (message: string) => void) => void;
onFrameSize: (consumer: (width: number, height: number) => void) => void;
onFrame: (consumer: (rgb: Uint8Array | null, rgba: Uint8Array | null) => void) => void;
onSoundPush: (consumer: (samples: Float32Array) => void) => void;
onExit: (consumer: () => void) => void;
onMessage: (consumer: (msgType: MessageType, ...args: any[]) => void) => void;
onNetworkConnected: (consumer: (networkType: NetworkType, address: string) => void) => void;
onNetworkDisconnected: (consumer: (networkType: NetworkType) => void) => void;
onUnload: (consumer: () => Promise<void>) => void;
}
9 changes: 9 additions & 0 deletions public/madness/2026/doom/emulators/types/http.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface XhrOptions {
method?: string;
progress?: (total: number, loaded: number) => void;
data?: string;
responseType?: XMLHttpRequestResponseType;
}
export declare const httpRequest: typeof XhrRequest;
declare function XhrRequest(url: string, options: XhrOptions): Promise<string | ArrayBuffer>;
export {};
32 changes: 32 additions & 0 deletions public/madness/2026/doom/emulators/types/impl/ci-impl.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { CommandInterfaceEvents, MessageType, NetworkType } from "../emulators";
export declare class CommandInterfaceEventsImpl implements CommandInterfaceEvents {
private onStdoutConsumers;
private delayedStdout;
private onFrameSizeConsumers;
private onFrameConsumers;
private onSoundPushConsumers;
private onExitConsumers;
private onMessageConsumers;
private delayedMessages;
private onNetworkConnectedConsumers;
private onNetworkDisconnectedConsumers;
private onUnloadConsumers;
onStdout: (consumer: (message: string) => void) => void;
onFrameSize: (consumer: (width: number, height: number) => void) => void;
onFrame: (consumer: (rgb: Uint8Array | null, rgba: Uint8Array | null) => void) => void;
onSoundPush: (consumer: (samples: Float32Array) => void) => void;
onExit: (consumer: () => void) => void;
onMessage: (consumer: (msgType: MessageType, ...args: any[]) => void) => void;
onNetworkConnected(consumer: (networkType: NetworkType, address: string) => void): void;
onNetworkDisconnected(consumer: (networkType: NetworkType) => void): void;
onUnload: (consumer: () => Promise<void>) => void;
fireStdout: (message: string) => void;
fireFrameSize: (width: number, height: number) => void;
fireFrame: (rgb: Uint8Array | null, rgba: Uint8Array | null) => void;
fireSoundPush: (samples: Float32Array) => void;
fireExit: () => void;
fireMessage: (msgType: MessageType, ...args: any[]) => void;
fireNetworkConnected: (networkType: NetworkType, address: string) => void;
fireNetworkDisconnected: (networkType: NetworkType) => void;
fireUnload: () => Promise<void>;
}
27 changes: 27 additions & 0 deletions public/madness/2026/doom/emulators/types/impl/emulators-impl.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Emulators, CommandInterface, BackendOptions, DosConfig, InitFs, InitBundleEntry } from "../emulators";
import { IWasmModules } from "./modules";
import DosBundle from "../dos/bundle/dos-bundle";
import { TransportLayer } from "../protocol/protocol";
declare class EmulatorsImpl implements Emulators {
pathPrefix: string;
pathSuffix: string;
version: string;
wdosboxJs: string;
wdosboxxJs: string;
private wasmModulesPromise?;
bundle(): Promise<DosBundle>;
bundleConfig(bundle: InitBundleEntry): Promise<DosConfig | null>;
bundleUpdateConfig(bundle: InitBundleEntry, config: DosConfig): Promise<Uint8Array>;
dosboxNode(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
dosboxDirect(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
dosboxWorker(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
dosboxXNode(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
dosboxXDirect(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
dosboxXWorker(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
backend(init: InitFs, transportLayer: TransportLayer, options?: BackendOptions): Promise<CommandInterface>;
wasmModules(): Promise<IWasmModules>;
dosDirect(init: InitFs): Promise<CommandInterface>;
dosWorker(init: InitFs): Promise<CommandInterface>;
}
declare const emulators: EmulatorsImpl;
export default emulators;
42 changes: 42 additions & 0 deletions public/madness/2026/doom/emulators/types/impl/modules.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export interface WasmModule {
instantiate: (module?: any) => Promise<any>;
}
export interface IWasmModules {
libzip: () => Promise<WasmModule>;
dosbox: () => Promise<WasmModule>;
dosboxx: () => Promise<WasmModule>;
}
interface Globals {
exports: {
[moduleName: string]: any;
};
module: {
exports?: () => void;
};
compiled: {
[moduleName: string]: Promise<WasmModule>;
};
}
declare class Host {
wasmSupported: boolean;
globals: Globals;
constructor();
}
export declare const host: Host;
export declare class WasmModulesImpl implements IWasmModules {
private pathPrefix;
private pathSuffix;
private wdosboxJs;
private wdosboxxJs;
private libzipPromise?;
private dosboxPromise?;
private dosboxxPromise?;
wasmSupported: boolean;
constructor(pathPrefix: string, pathSuffix: string, wdosboxJs: string, wdosboxxJs: string);
libzip(): Promise<WasmModule>;
dosbox(): Promise<WasmModule>;
dosboxx(): Promise<WasmModule>;
private loadModule;
}
export declare function loadWasmModule(url: string, moduleName: string, onprogress: (stage: string, total: number, loaded: number) => void): Promise<WasmModule>;
export {};
Loading
Loading