Initial commit

moved from private version control
This commit is contained in:
2025-10-19 21:12:41 +11:00
parent 5e84773bbe
commit e64f3e881e
187 changed files with 25372 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Stops execution when a condition is false, printing an optional message.
*/
export const assertNode = createNodeModule(
{
id: "system_assert",
title: "Assert",
category: "System",
description:
"Assert that a condition is true, stopping the cart when it fails.",
searchTags: ["assert", "debug", "check", "system"],
inputs: [
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
{
id: "condition",
name: "Condition",
direction: "input",
kind: "boolean",
defaultValue: true,
},
{ id: "message", name: "Message", direction: "input", kind: "string" },
],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
const OMIT = "__pg_omit__";
const condition = resolveValueInput("condition", "true");
const message = resolveValueInput("message", OMIT);
const callArgs = message === OMIT ? condition : `${condition}, ${message}`;
const lines = [`${indent(indentLevel)}assert(${callArgs})`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,93 @@
import { createNodeModule } from "../../nodeTypes.js";
const EXT_CMD_DEFAULT = "reset";
const EXT_CMD_OPTIONS = [
{ value: "pause", label: "Pause Menu" },
{ value: EXT_CMD_DEFAULT, label: "Reset Cart" },
{ value: "go_back", label: "Return To Previous Cart" },
{ value: "label", label: "Capture Label" },
{ value: "screen", label: "Save Screenshot" },
{ value: "rec", label: "Mark Video Start" },
{ value: "rec_frames", label: "Mark Video Start (Frames)" },
{ value: "video", label: "Save Video" },
{ value: "audio_rec", label: "Start Audio Recording" },
{ value: "audio_end", label: "Finish Audio Recording" },
{ value: "shutdown", label: "Shutdown Cartridge" },
{ value: "folder", label: "Open Cartridge Folder" },
{ value: "set_filename", label: "Set Capture Filename" },
{ value: "set_title", label: "Set Window Title" },
];
/**
* Issues special host commands such as screenshots or recordings.
*/
export const extcmdNode = createNodeModule(
{
id: "system_extcmd",
title: "System Command",
category: "System",
description: "Execute a special system command using extcmd().",
searchTags: [
"extcmd",
"system",
"command",
"host",
"screenshot",
"video",
"audio",
"pause",
"reset",
],
inputs: [
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
{ id: "command", name: "Command", direction: "input", kind: "string" },
{ id: "param1", name: "Param 1", direction: "input", kind: "number" },
{ id: "param2", name: "Param 2", direction: "input", kind: "number" },
],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [
{
key: "command",
label: "Command",
type: "enum",
defaultValue: EXT_CMD_DEFAULT,
options: EXT_CMD_OPTIONS,
},
],
},
{
emitExec: ({
node,
indent,
indentLevel,
resolveValueInput,
emitNextExec,
formatLiteral,
}) => {
const OMIT = "__pg_omit__";
const fallbackCommand = formatLiteral(
"string",
node.properties.command ?? EXT_CMD_DEFAULT
);
const command = resolveValueInput("command", fallbackCommand);
const param1 = resolveValueInput("param1", OMIT);
const param2 = resolveValueInput("param2", OMIT);
const args = [command];
if (param1 !== OMIT || param2 !== OMIT) {
const param1Arg = param1 === OMIT ? "nil" : param1;
args.push(param1Arg);
if (param2 !== OMIT) {
args.push(param2);
}
}
const lines = [`${indent(indentLevel)}extcmd(${args.join(", ")})`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,27 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Performs a manual buffer flip when using a custom main loop.
*/
export const flipNode = createNodeModule(
{
id: "system_flip",
title: "Flip Buffer",
category: "System",
description:
"Flip the back buffer to the screen and wait for the next frame.",
searchTags: ["flip", "sync", "frame", "system"],
inputs: [{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" }],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, emitNextExec }) => {
const lines = [`${indent(indentLevel)}flip()`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,26 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Opens the cartridge folder on the host operating system.
*/
export const folderNode = createNodeModule(
{
id: "system_folder",
title: "Open Folder",
category: "System",
description: "Open the cartridge folder on the host operating system.",
searchTags: ["folder", "system", "directory", "open"],
inputs: [{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" }],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, emitNextExec }) => {
const lines = [`${indent(indentLevel)}folder()`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,61 @@
import { loadNode } from "./load.js";
import { saveNode } from "./save.js";
import { folderNode } from "./folder.js";
import { lsNode } from "./ls.js";
import { runNode } from "./run.js";
import { stopNode } from "./stop.js";
import { resumeNode } from "./resume.js";
import { assertNode } from "./assert.js";
import { rebootNode } from "./reboot.js";
import { resetNode } from "./reset.js";
import { infoNode } from "./info.js";
import { flipNode } from "./flip.js";
import { printhNode } from "./printh.js";
import { timeNode } from "./time.js";
import { statNode } from "./stat.js";
import { extcmdNode } from "./extcmd.js";
/**
* All system related node modules backed by PICO-8 helper functions.
*/
export const systemNodes = [
loadNode,
saveNode,
folderNode,
lsNode,
runNode,
stopNode,
resumeNode,
assertNode,
rebootNode,
resetNode,
infoNode,
flipNode,
printhNode,
timeNode,
statNode,
extcmdNode,
];
/**
* Checklist tracking coverage of documented system helpers.
* @type {Array<{ function: string, nodeId: string, implemented: boolean }>}
*/
export const systemFunctionChecklist = [
{ function: "LOAD", nodeId: "system_load", implemented: true },
{ function: "SAVE", nodeId: "system_save", implemented: true },
{ function: "FOLDER", nodeId: "system_folder", implemented: true },
{ function: "LS", nodeId: "system_ls", implemented: true },
{ function: "RUN", nodeId: "system_run", implemented: true },
{ function: "STOP", nodeId: "system_stop", implemented: true },
{ function: "RESUME", nodeId: "system_resume", implemented: true },
{ function: "ASSERT", nodeId: "system_assert", implemented: true },
{ function: "REBOOT", nodeId: "system_reboot", implemented: true },
{ function: "RESET", nodeId: "system_reset", implemented: true },
{ function: "INFO", nodeId: "system_info", implemented: true },
{ function: "FLIP", nodeId: "system_flip", implemented: true },
{ function: "PRINTH", nodeId: "system_printh", implemented: true },
{ function: "TIME", nodeId: "system_time", implemented: true },
{ function: "STAT", nodeId: "system_stat", implemented: true },
{ function: "EXTCMD", nodeId: "system_extcmd", implemented: true },
];

View File

@@ -0,0 +1,27 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Prints cartridge diagnostics to the console.
*/
export const infoNode = createNodeModule(
{
id: "system_info",
title: "Cartridge Info",
category: "System",
description:
"Print information about the cartridge including size and token counts.",
searchTags: ["info", "memory", "stats", "system"],
inputs: [{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" }],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, emitNextExec }) => {
const lines = [`${indent(indentLevel)}info()`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,57 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Loads another cartridge and optionally supplies breadcrumb and parameter metadata.
*/
export const loadNode = createNodeModule(
{
id: "system_load",
title: "Load Cartridge",
category: "System",
description:
"Load a local or BBS cartridge, optionally providing breadcrumb and parameter string.",
searchTags: ["load", "cartridge", "system", "cart"],
inputs: [
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
{
id: "filename",
name: "Filename",
direction: "input",
kind: "string",
defaultValue: "cart.p8",
},
{
id: "breadcrumb",
name: "Breadcrumb",
direction: "input",
kind: "string",
},
{ id: "param", name: "Param String", direction: "input", kind: "string" },
],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
const OMIT = "__pg_omit__";
const filename = resolveValueInput("filename", '""');
const breadcrumb = resolveValueInput("breadcrumb", OMIT);
const param = resolveValueInput("param", OMIT);
const args = [filename];
if (breadcrumb !== OMIT || param !== OMIT) {
const breadcrumbArg = breadcrumb === OMIT ? "nil" : breadcrumb;
args.push(breadcrumbArg);
if (param !== OMIT) {
args.push(param);
}
}
const lines = [`${indent(indentLevel)}load(${args.join(", ")})`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,33 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Lists cartridges within the provided directory relative to the virtual drive.
*/
export const lsNode = createNodeModule(
{
id: "system_ls",
title: "List Directory",
category: "System",
description:
"List .p8 and .p8.png files in a directory relative to the current path.",
searchTags: ["ls", "list", "files", "system"],
inputs: [
{
id: "directory",
name: "Directory",
direction: "input",
kind: "string",
},
],
outputs: [
{ id: "entries", name: "Entries", direction: "output", kind: "table" },
],
properties: [],
},
{
evaluateValue: ({ resolveValueInput }) => {
const directory = resolveValueInput("directory", "nil");
return directory === "nil" ? "ls()" : `ls(${directory})`;
},
}
);

View File

@@ -0,0 +1,70 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Prints to the host console or files for debugging utilities.
*/
export const printhNode = createNodeModule(
{
id: "system_printh",
title: "Print Host",
category: "System",
description:
"Print a string to the host console or optionally to a file or clipboard.",
searchTags: ["printh", "print", "debug", "file", "system"],
inputs: [
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
{
id: "text",
name: "Text",
direction: "input",
kind: "string",
defaultValue: "debug",
},
{ id: "filename", name: "Filename", direction: "input", kind: "string" },
{
id: "overwrite",
name: "Overwrite",
direction: "input",
kind: "boolean",
defaultValue: false,
},
{
id: "save_to_desktop",
name: "Save to Desktop",
direction: "input",
kind: "boolean",
defaultValue: false,
},
],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
const text = resolveValueInput("text", '""');
const filename = resolveValueInput("filename", "nil");
const overwrite = resolveValueInput("overwrite", "false");
const saveToDesktop = resolveValueInput("save_to_desktop", "false");
const args = [text];
const hasFilename = filename !== "nil";
if (hasFilename) {
args.push(filename);
const includeOverwrite =
overwrite !== "false" || saveToDesktop !== "false";
if (includeOverwrite) {
args.push(overwrite);
if (saveToDesktop !== "false") {
args.push(saveToDesktop);
}
}
}
const lines = [`${indent(indentLevel)}printh(${args.join(", ")})`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,26 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Reboots PICO-8, returning to a fresh command prompt.
*/
export const rebootNode = createNodeModule(
{
id: "system_reboot",
title: "Reboot",
category: "System",
description: "Reboot the virtual machine to begin a new project.",
searchTags: ["reboot", "restart", "system", "cart"],
inputs: [{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" }],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, emitNextExec }) => {
const lines = [`${indent(indentLevel)}reboot()`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,27 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Restores draw state values such as palette and camera to their defaults.
*/
export const resetNode = createNodeModule(
{
id: "system_reset",
title: "Reset Draw State",
category: "System",
description:
"Reset memory range 0x5f00..0x5f7f, restoring draw state defaults.",
searchTags: ["reset", "clear", "system", "state"],
inputs: [{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" }],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, emitNextExec }) => {
const lines = [`${indent(indentLevel)}reset()`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,26 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Resumes execution after a stop.
*/
export const resumeNode = createNodeModule(
{
id: "system_resume",
title: "Resume",
category: "System",
description: "Resume the program after it has been stopped.",
searchTags: ["resume", "continue", "system", "run"],
inputs: [{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" }],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, emitNextExec }) => {
const lines = [`${indent(indentLevel)}resume()`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,33 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Restarts the current program from the beginning.
*/
export const runNode = createNodeModule(
{
id: "system_run",
title: "Run",
category: "System",
description:
"Restart the program optionally providing a parameter string accessible via stat(6).",
searchTags: ["run", "launch", "cartridge", "system"],
inputs: [
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
{ id: "param", name: "Param String", direction: "input", kind: "string" },
],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
const OMIT = "__pg_omit__";
const param = resolveValueInput("param", OMIT);
const call = param === OMIT ? "run()" : `run(${param})`;
const lines = [`${indent(indentLevel)}${call}`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,36 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Persists the active cartridge to disk.
*/
export const saveNode = createNodeModule(
{
id: "system_save",
title: "Save Cartridge",
category: "System",
description: "Save the current cartridge to the specified filename.",
searchTags: ["save", "cartridge", "system", "cart"],
inputs: [
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
{
id: "filename",
name: "Filename",
direction: "input",
kind: "string",
defaultValue: "cart.p8",
},
],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
const filename = resolveValueInput("filename", '""');
const lines = [`${indent(indentLevel)}save(${filename})`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,31 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Queries system status values exposed through stat().
*/
export const statNode = createNodeModule(
{
id: "system_stat",
title: "System Status",
category: "System",
description: "Fetch a system status value using the stat(index) helper.",
searchTags: ["stat", "status", "system", "metrics"],
inputs: [
{
id: "index",
name: "Index",
direction: "input",
kind: "number",
defaultValue: 0,
},
],
outputs: [{ id: "value", name: "Value", direction: "output", kind: "any" }],
properties: [],
},
{
evaluateValue: ({ resolveValueInput }) => {
const index = resolveValueInput("index", "0");
return `stat(${index})`;
},
}
);

View File

@@ -0,0 +1,32 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Stops the cart and optionally prints a message to the console.
*/
export const stopNode = createNodeModule(
{
id: "system_stop",
title: "Stop",
category: "System",
description: "Stop the current cart and optionally print a message.",
searchTags: ["stop", "halt", "exit", "system"],
inputs: [
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
{ id: "message", name: "Message", direction: "input", kind: "string" },
],
outputs: [
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
],
properties: [],
},
{
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
const OMIT = "__pg_omit__";
const message = resolveValueInput("message", OMIT);
const call = message === OMIT ? "stop()" : `stop(${message})`;
const lines = [`${indent(indentLevel)}${call}`];
lines.push(...emitNextExec("exec_out"));
return lines;
},
}
);

View File

@@ -0,0 +1,23 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Returns the number of seconds elapsed since the cart started running.
*/
export const timeNode = createNodeModule(
{
id: "system_time",
title: "Time",
category: "System",
description:
"Retrieve the elapsed time in seconds since the cart launched.",
searchTags: ["time", "seconds", "system", "elapsed"],
inputs: [],
outputs: [
{ id: "value", name: "Seconds", direction: "output", kind: "number" },
],
properties: [],
},
{
evaluateValue: () => "time()",
}
);