diff --git a/src/components/Actions.jsx b/src/components/Actions.jsx index 7dfd232..adbe6db 100644 --- a/src/components/Actions.jsx +++ b/src/components/Actions.jsx @@ -2,13 +2,10 @@ import { createSignal, onCleanup, onMount, useContext } from "solid-js"; import { VsClearAll, VsDebug, VsDebugLineByLine, VsDebugStart, VsDebugStepInto, VsDebugStepOver, VsDebugStop, VsInfo, VsPlay, VsQuestion } from 'solid-icons/vs'; import { HiOutlineWrench, HiSolidArrowRight, HiSolidPlay, HiSolidStop, HiSolidWrench } from 'solid-icons/hi'; import Module from '../core/8085.js'; -import { StoreContext } from "./StoreContext.js"; import { produce } from "solid-js/store"; import { initSimulator, loadProgram, runProgram, runSingleInstruction, setAllMemoryLocations, setFlags, setPC, setRegisters, startDebug, unloadProgram } from "../core/simulator.js"; -import { AiFillFastForward, AiFillStop, AiOutlineClear } from "solid-icons/ai"; +import { AiOutlineClear } from "solid-icons/ai"; import { Tooltip } from "@kobalte/core/tooltip"; -import { FiFastForward } from "solid-icons/fi"; -import { BsFastForwardFill, BsStop } from "solid-icons/bs"; import { store, setStore } from '../store/store.js'; import { Toast, toaster } from "@kobalte/core/toast"; import { trackEvent } from "./analytics/tracker.js"; @@ -90,7 +87,6 @@ export function Actions() { } } - console.log("pcStartValue", result.pcStartValue); if (result) { setStore( produce((draftStore) => { @@ -165,7 +161,9 @@ export function Actions() { } } catch (e) { if (e.status === 1) showToaster("error", "Program existed with error", "Unknown instruction encountered in the program."); - else if (e.status === 2) showToaster("error", "Program existed with error", "Infinite loop detected. Did you forget to add HLT."); + else if (e.status === 2) { + showToaster("error", "Program existed with error", ()); + } else showToaster("error", "Program existed with error", "We could not identify the error."); errorStatus = e.status; trackEvent("run failed", { @@ -221,7 +219,9 @@ export function Actions() { if (errorStatus > 0) { setStore('programState', 'Loaded'); if (errorStatus === 1) showToaster("error", "Program existed with error", "Unknown instruction encountered in the program."); - else if (errorStatus === 2) showToaster("error", "Program existed with error", "Infinite loop detected. Did you forget to add HLT."); + else if (errorStatus === 2) { + showToaster("error", "Program existed with error", ()); + } else showToaster("error", "Program existed with error", "We could not identify the error."); trackEvent("run failed", { code: store.code, @@ -344,13 +344,13 @@ export function Actions() { return ( -
-
-
- 0x +
+
+
+ 0x setPCStartValue(e.target.value)} @@ -364,18 +364,21 @@ export function Actions() {

Your program will start executing at this address instead of 0h. - This is equivalent to the operation of GO & EXEC in SDK-85. + This is equivalent to the operation of GO & EXEC in SDK-85. See page 4-6 in the manual.

-

- This can be also manipulated using the END directive. +

+ This can be also manipulated using the END directive. +

+

+ You must specify this value if your code uses ORG directive.

} + icon={} title="Load & Run" shortcut="Ctrl + F5" onClick={loadAndRun} @@ -387,7 +390,7 @@ export function Actions() { store.programState === 'Idle' ? ( ) : ( - + ) } onClick={loadOrUnload} @@ -430,11 +433,11 @@ export function Actions() { function ActionButton(props) { return ( - -
+
{props.icon}
@@ -444,7 +447,7 @@ function ActionButton(props) {

{props.title}

{props.shortcut ? ( - {props.shortcut} + {props.shortcut} ) : null}
@@ -452,3 +455,27 @@ function ActionButton(props) { ); }; + +function InfiniteLoopError(props) { + return ( + <> +

Infinite loop detected

+ {!props.code.match(/\s+HLT(\s+|$)/i) ?

Did you forget to add HLT?

: + props.code.match(/(^|\s+)ORG(\s+|$)/i) ? ( + <> +

+ Using ORG may cause the program to load at a different address. +

+
+ Enter the address where your program begins execution in the text box near the + + + Run + button. +
+ + ) :

Please check your program for logic errors.

+ } + + ); +} diff --git a/src/components/Assembled.jsx b/src/components/Assembled.jsx index 31279e5..edc2f82 100644 --- a/src/components/Assembled.jsx +++ b/src/components/Assembled.jsx @@ -1,4 +1,4 @@ -import { createEffect, createSignal } from 'solid-js'; +import { createEffect, createSignal, onMount } from 'solid-js'; import { store } from '../store/store.js'; import { toByteString } from '../utils/NumberFormat.js'; import { HiSolidWrench } from 'solid-icons/hi'; @@ -6,20 +6,71 @@ import { VsCopy, VsError } from 'solid-icons/vs'; import { FiAlertCircle, FiAlertTriangle } from 'solid-icons/fi'; import CopyComponent from './CopyComponent.jsx'; import { Tooltip } from '@kobalte/core/tooltip'; +import { BsArrowBarLeft, BsArrowBarRight } from 'solid-icons/bs'; export function Assembled() { let [lines, setLines] = createSignal([]); + let [expanded, setExpanded] = createSignal(true); + const [width, setWidth] = createSignal(300); + createEffect(() => { setLines(zipAssembledSource(store.assembled, store.code)); }); + + const toggleExpanded = () => { + setExpanded((expanded) => !expanded); + }; + + onMount(() => { + setWidth(window.innerWidth * 0.3); + const handleResize = () => { + const isMd = window.matchMedia("(min-width: 768px)").matches; + setExpanded(isMd); + }; + + // Initial check + handleResize(); + + // Listen for resize events + window.addEventListener("resize", handleResize); + + // Cleanup listener on component unmount + return () => { + window.removeEventListener("resize", handleResize); + }; + }); + + const startResize = (event) => { + const onMouseMove = (e) => setWidth((prev) => prev - e.movementX); + const onMouseUp = () => { + window.removeEventListener("mousemove", onMouseMove); + window.removeEventListener("mouseup", onMouseUp); + }; + window.addEventListener("mousemove", onMouseMove); + window.addEventListener("mouseup", onMouseUp); + onCleanup(() => onMouseUp()); // Cleanup when SolidJS destroys the component + }; + return ( -
-
-

Assembled Output

+
+ +
+
+

Assembled Output

- + copyOutputAsText(lines())} /> @@ -31,127 +82,140 @@ export function Assembled() {
-
-
-
-
+ + + {expanded() ? : } + + + + +

{expanded() ? "Collapse Panel" : "Expand Panel"}

+
+
+
+
+
+
+
+ + {((line, i) => { + const code = showCode(line[0]); + return ( +
+ {i() + 1} + + { code.length ? `0x${code[0].currentAddress.toString(16).toUpperCase()}` : '' } + +
+ + {(item) => ( +
+
+ {item.data} +
+
+ )} +
+
+
{ line[1] }
+
+ ); + })} +
+
+
- - {((line, i) => { - const code = showCode(line[0]); + > + {store.errors.map((e) => { + const codeLines = store.codeWithError.split('\n'); + const startLine = e.location.start.line - 1; + const endLine = e.location.end.line - 1; + + const displayedLines = codeLines.slice(startLine, endLine + 1); // All lines in the range + return ( -
- {i() + 1} - - { code.length ? `0x${code[0].currentAddress.toString(16).toUpperCase()}` : '' } - -
- - {(item) => ( -
-
- {item.data} -
-
+ <> + {e.type ? ( +

+ + + +
{e.type.toUpperCase()}
+

+ ) : null} +
+ {e.hint.length ? null : (Line {e.line}, Column: {e.column}: )} + {e.msg} {e.hint.length ? (on line {e.line}) : null} +
+ {e.hint.length ? ( + + {(hint) => ( +

+ Hint: {hint} +

)}
+ ) : null} +
+ {displayedLines.map((line, index) => { + const lineNumber = startLine + index + 1; + + const startColMinusOne = e.location.start.column === 0 ? 1 : e.location.start.column - 1; + if (index === 0) { + // Start Line + const startMarker = ' '.repeat(startColMinusOne) + '^'.repeat(line.length - startColMinusOne > 0 ? line.length - startColMinusOne : 0); + return ( +
+
+                                {lineNumber}|  {line}
+                              
+
+                                {' '.repeat(lineNumber.toString().length) + '| '}{startMarker}
+                              
+
+ ); + } else if (index === displayedLines.length - 1) { + // End Line + const endMarker = '^'.repeat(startColMinusOne); + return ( +
+
+                                {lineNumber}|  {line}
+                              
+
+                                {' '.repeat(lineNumber.toString().length) + '|  '}{endMarker}
+                              
+
+ ); + } else { + // Middle lines, show without any marker + return ( +
+
+                                {lineNumber}|  {line}
+                              
+
+ ); + } + })}
-
{ line[1] }
-
+ ); })} - -
-
- {store.errors.map((e) => { - const codeLines = store.codeWithError.split('\n'); - const startLine = e.location.start.line - 1; - const endLine = e.location.end.line - 1; - - const displayedLines = codeLines.slice(startLine, endLine + 1); // All lines in the range - - return ( - <> - {e.type ? ( -

- - - -
{e.type.toUpperCase()}
-

- ) : null} -
- {e.hint.length ? null : (Line {e.line}, Column: {e.column}: )} - {e.msg} {e.hint.length ? (on line {e.line}) : null} -
- {e.hint.length ? ( - - {(hint) => ( -

- Hint: {hint} -

- )} -
- ) : null} -
- {displayedLines.map((line, index) => { - const lineNumber = startLine + index + 1; - - const startColMinusOne = e.location.start.column === 0 ? 1 : e.location.start.column - 1; - if (index === 0) { - // Start Line - const startMarker = ' '.repeat(startColMinusOne) + '^'.repeat(line.length - startColMinusOne > 0 ? line.length - startColMinusOne : 0); - return ( -
-
-                              {lineNumber}|  {line}
-                            
-
-                              {' '.repeat(lineNumber.toString().length) + '| '}{startMarker}
-                            
-
- ); - } else if (index === displayedLines.length - 1) { - // End Line - const endMarker = '^'.repeat(startColMinusOne); - return ( -
-
-                              {lineNumber}|  {line}
-                            
-
-                              {' '.repeat(lineNumber.toString().length) + '|  '}{endMarker}
-                            
-
- ); - } else { - // Middle lines, show without any marker - return ( -
-
-                              {lineNumber}|  {line}
-                            
-
- ); - } - })} -
- - ); - })} -
-
-

- Load or Run the program to view the assembled output. -

+
+
+

+ Load or Run the program to view the assembled output. +

+
diff --git a/src/components/CopyComponent.jsx b/src/components/CopyComponent.jsx index b7ef808..b2c4f1e 100644 --- a/src/components/CopyComponent.jsx +++ b/src/components/CopyComponent.jsx @@ -18,7 +18,7 @@ function CopyComponent(props) { return (
@@ -53,7 +53,7 @@ export function Flags() { function Flag(props) { const id = `flag-${props.id}`; return ( -
+