Skip to content

Commit

Permalink
Added TIC-80
Browse files Browse the repository at this point in the history
  • Loading branch information
DustinBrett committed Jan 18, 2025
1 parent 54f9bae commit c2db213
Show file tree
Hide file tree
Showing 19 changed files with 189 additions and 0 deletions.
12 changes: 12 additions & 0 deletions components/apps/Tic80/StyledTic80.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import styled from "styled-components";

const StyledTic80 = styled.div`
iframe {
background-color: #1a1c2c;
border: 0;
height: 100%;
width: 100%;
}
`;

export default StyledTic80;
10 changes: 10 additions & 0 deletions components/apps/Tic80/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import useTic80 from "components/apps/Tic80/useTic80";
import StyledTic80 from "components/apps/Tic80/StyledTic80";
import AppContainer from "components/system/Apps/AppContainer";
import { type ComponentProcessProps } from "components/system/Apps/RenderComponent";

const Tic80: FC<ComponentProcessProps> = ({ id }) => (
<AppContainer StyledComponent={StyledTic80} id={id} useHook={useTic80} />
);

export default Tic80;
143 changes: 143 additions & 0 deletions components/apps/Tic80/useTic80.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { basename } from "path";
import { useCallback, useEffect, useRef } from "react";
import { type ContainerHookProps } from "components/system/Apps/AppContainer";
import { useProcesses } from "contexts/process";
import { bufferToUrl } from "utils/functions";
import { useFileSystem } from "contexts/fileSystem";
import { useSession } from "contexts/session";
import { PREVENT_SCROLL } from "utils/constants";
import useFileDrop from "components/system/Files/FileManager/useFileDrop";
import useTitle from "components/system/Window/useTitle";
import processDirectory from "contexts/process/directory";

const useTic80 = ({
containerRef,
id,
setLoading,
url,
}: ContainerHookProps): void => {
const { processes: { [id]: { libs = [], maximized, title } = {} } = {} } =
useProcesses();
const { foregroundId, setForegroundId } = useSession();
const { readFile } = useFileSystem();
const { onDragOver, onDrop } = useFileDrop({ id });
const loadedUrl = useRef<string>(undefined);
const initializing = useRef(false);
const { appendFileToTitle } = useTitle(id);
const createIframe = useCallback((): Window => {
containerRef.current?.querySelector("iframe")?.remove();

const iframe = document.createElement("iframe");

iframe.title = title || processDirectory[id].title;

containerRef.current?.append(iframe);

const contentWindow = iframe.contentWindow as Window;

contentWindow.document.body.style.margin = "0";
contentWindow.document.body.style.overflow = "hidden";

return contentWindow;
}, [containerRef, id, title]);
const createCanvas = useCallback(
(baseDocument: Document): HTMLCanvasElement => {
const canvas = baseDocument.createElement("canvas");

canvas.id = "canvas";
canvas.style.width = "100%";
canvas.style.height = "100%";
canvas.style.imageRendering = "pixelated";
canvas.tabIndex = -1;

baseDocument.body.append(canvas);

return canvas;
},
[]
);
const loadComputer = useCallback(
(fileUrl?: string) => {
initializing.current = true;
setLoading(true);

const iframeWindow = createIframe();
const canvas = createCanvas(iframeWindow.document);

const focusCanvas = (): void => {
canvas.focus(PREVENT_SCROLL);
setForegroundId(id);
};
const postRun = (): void => setLoading(false);

iframeWindow.Module = { canvas, postRun };

iframeWindow.addEventListener("click", focusCanvas);
iframeWindow.addEventListener("focus", focusCanvas);
iframeWindow.addEventListener("blur", () => setForegroundId(""));
iframeWindow.addEventListener("dragover", onDragOver);
iframeWindow.addEventListener("drop", onDrop);

const loadApp = (blobUrl?: string): void => {
if (blobUrl) {
iframeWindow.Module.arguments = [blobUrl];
appendFileToTitle(basename(url));
}

const [tic80Lib] = libs;
const script = iframeWindow.document.createElement("script");

script.type = "text/javascript";
script.src = tic80Lib;

iframeWindow.document.head.append(script);

loadedUrl.current = fileUrl || "";
initializing.current = false;

setLoading(false);
};

if (fileUrl) {
readFile(fileUrl).then((file) =>
loadApp(`${bufferToUrl(file)}?e=.tic`)
);
} else {
loadApp();
}
},
[
appendFileToTitle,
createCanvas,
createIframe,
id,
libs,
onDragOver,
onDrop,
readFile,
setForegroundId,
setLoading,
url,
]
);

useEffect(() => {
if (!initializing.current && url !== loadedUrl.current) {
loadComputer(url);
}
}, [loadComputer, url]);

useEffect(() => {
if (foregroundId === id) {
requestAnimationFrame(() => {
containerRef.current
?.querySelector("iframe")
?.contentWindow?.document.querySelector<HTMLCanvasElement>("#canvas")
?.focus(PREVENT_SCROLL);
});
}
// eslint-disable-next-line react-hooks-addons/no-unused-deps
}, [containerRef, foregroundId, id, maximized]);
};

export default useTic80;
5 changes: 5 additions & 0 deletions components/system/Files/FileEntry/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ const types = {
process: ["Photos", ...TEXT_EDITORS],
type: "Scalable Vector Graphics File",
},
Tic80: {
process: ["Tic80"],
type: "TIC-80 Cartridge",
},
WasmFile: {
command: "wapm",
icon: "wapm",
Expand Down Expand Up @@ -133,6 +137,7 @@ const extensions: Record<string, Extension> = {
".spl": types.FutureSplash,
".svg": types.SvgFile,
".swf": types.ShockwaveFlash,
".tic": types.Tic80,
".ttf": types.Font,
".wasm": types.WasmFile,
".whtml": types.WysiwygHtmlDocument,
Expand Down
13 changes: 13 additions & 0 deletions contexts/process/directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,19 @@ const directory: Processes = {
preferProcessIcon: true,
title: "Terminal",
},
Tic80: {
Component: dynamic(() => import("components/apps/Tic80")),
backgroundColor: "#1A1C2C",
defaultSize: {
height: 346,
width: 615,
},
dependantLibs: ["/Program Files/Tic80/tic80.wasm"],
icon: "/System/Icons/tic80.webp",
libs: ["/Program Files/Tic80/tic80.js"],
lockAspectRatio: true,
title: "TIC-80 tiny computer",
},
TinyMCE: {
Component: dynamic(() => import("components/apps/TinyMCE")),
backgroundColor: "#202124",
Expand Down
1 change: 1 addition & 0 deletions public/CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ This project is greatly augmented by code from the open source community. Thank
- [nostr-tools](https://github.com/nbd-wtf/nostr-tools)
- [DOMPurify](https://github.com/cure53/DOMPurify)
- [t-rex-runner](https://github.com/wayou/t-rex-runner)
- [TIC-80](https://tic80.com/)

## Services

Expand Down
1 change: 1 addition & 0 deletions public/Program Files/Tic80/tic80.js

Large diffs are not rendered by default.

Binary file added public/Program Files/Tic80/tic80.wasm
Binary file not shown.
Binary file added public/System/Icons/144x144/tic80.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/System/Icons/144x144/tic80.webp
Binary file not shown.
Binary file added public/System/Icons/16x16/tic80.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/System/Icons/16x16/tic80.webp
Binary file not shown.
Binary file added public/System/Icons/32x32/tic80.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/System/Icons/32x32/tic80.webp
Binary file not shown.
Binary file added public/System/Icons/48x48/tic80.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/System/Icons/48x48/tic80.webp
Binary file not shown.
Binary file added public/System/Icons/96x96/tic80.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/System/Icons/96x96/tic80.webp
Binary file not shown.
4 changes: 4 additions & 0 deletions public/Users/Public/Start Menu/Emulators/TIC-80.url
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[InternetShortcut]
BaseURL=Tic80
Comment=TIC-80 Tiny Computer
IconFile=/System/Icons/tic80.webp

0 comments on commit c2db213

Please sign in to comment.