fix(examples): board-less chip example — Run enabled on load + editable program

Two UX bugs in the board-less "Z80 Larson Scanner (no board)" example:

- It loaded "running" (electrical sim defaults to paused=false), so Run was
  disabled and Stop enabled even though the chip hadn't started — the user had
  to Stop then Run. loadExample now starts a board-less example that contains a
  custom chip in the STOPPED state (paused=true) so Run is enabled; pure
  analog/digital circuits stay live.
- The chip's program wasn't editable: it shipped a pre-baked ROM and the
  board-less loader only setCode'd into an orphan file group (no-op → blank
  editor). The example now ships larson.s as a real file (programFile), and
  the board-less loader points the editor at the default group and loadFiles()
  the example's files, so the program shows on the left and is editable, like
  the board-backed examples. Run compiles it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
David Montero 2026-06-03 21:30:42 +02:00
parent d5b9a9ceb5
commit fe001d728c
2 changed files with 30 additions and 8 deletions

View File

@ -638,7 +638,8 @@ export const retroIntelExamples: ExampleProject[] = [
difficulty: 'intermediate',
boardFilter: 'digital',
tags: ['retro', 'z80', 'zilog', 'cpu', 'leds', 'larson', 'no-board', 'power-supply', 'custom-chip', 'spice', 'programmable'],
code: `// Z80 Larson Scanner — NO Arduino, just the chip + a power supply.\n//\n// Velxio runs custom chips as a general-purpose electronics simulator: the\n// programmable Z80 on the canvas executes its ROM and drives the 8 LEDs\n// directly, powered by the regulated supply (no MCU needed). Click Run.\n\nvoid setup() {}\nvoid loop() {}\n`,
code: larsonZ80Asm,
files: [{ name: 'larson.s', content: larsonZ80Asm }],
components: [
{
type: 'power-supply',
@ -657,9 +658,8 @@ export const retroIntelExamples: ExampleProject[] = [
sourceC: z80CpuC,
chipJson: z80CpuJ,
wasmBase64: '',
// Pre-baked larson.s ROM (LD SP,0xBFFF; rotate a bit across 0xC000).
romBytes: 'Mf+/PgEyAMD1zRAA8QcY9Q5QBgAQ/g0g+ck=',
programFile: '',
romBytes: '',
programFile: 'larson.s',
programTarget: 'z80',
},
},

View File

@ -248,10 +248,21 @@ export async function loadExample(
const filename = isPiBoardKind(liveBoard.boardKind) ? 'main.cpp' : 'sketch.ino';
editorStore.loadFiles([{ name: filename, content: example.code }]);
} else {
// Truly board-less: write the placeholder code to whatever the editor
// currently shows (boardless examples ship a `void setup()/loop()`
// stub — content barely matters since the user won't compile it).
useEditorStore.getState().setCode(example.code);
// Truly board-less. There is no board file-group, so point the editor at
// the default group and load the example's files THERE — otherwise the
// editor's activeGroupId still points at a deleted board's group and
// setCode silently no-ops, leaving the editor blank/uneditable. This is
// what lets a board-less custom-chip example show its program (.s/.c) on
// the left, editable, just like the board-backed examples.
const editorStore = useEditorStore.getState();
if (example.files && example.files.length > 0) {
editorStore.setActiveGroup('group-arduino-uno'); // = DEFAULT_GROUP_ID
editorStore.loadFiles(example.files);
} else {
// Pure analog/digital circuits ship no editable program — keep the
// legacy behaviour (write the placeholder to the current file).
editorStore.setCode(example.code);
}
}
const componentsWithoutBoard = example.components.filter(
@ -270,6 +281,17 @@ export async function loadExample(
})),
);
// A board-less example with a custom chip must START STOPPED so the Run
// button is enabled: the chip needs an explicit Run to compile its
// WASM/ROM and begin executing. Pure analog/digital circuits stay live
// (paused=false) as before.
if (isBoardless) {
const hasCustomChip = componentsWithoutBoard.some(
(c) => stripBrandPrefix(c.type) === 'custom-chip',
);
useElectricalStore.getState().setPaused(hasCustomChip);
}
// After possibly removing every board, re-read activeBoardId.
const liveActiveBoardId = useSimulatorStore.getState().activeBoardId;
// For analog (board-less) examples we leave any 'arduino-uno' references