Table of Contents

Introduction

Elsewhere we've talked about how to compile HAL/S-language programs, how to assemble AP-101S assembly-language programs, and how to link AP-101S object-code files to get executable AP-101S memory images.  The important topic of how to actually run any of these programs without an actual AP-101S computer and a Space Shuttle to provide the computer's peripheral devices remains.  Let's tackle that now.

The answer is emulation.  We provide "virtual machines" that run within your own computer — whether Linux, Mac OS, or Windows —, but which can run HAL/S or AP-101S code in some fashion.  There are several alternative ways to accomplish this feat.  You may consider these choices either a blessing or a curse, but you nevertheless need to make a decision about which approach is most-suitable for your own purposes.

There are actually two broadly-different classes of emulators available, and multiple emulators in each of the two classes.  Two of the emulators accept AP-101S memory images as alluded to above, and pretend to be an AP-101S computer, directly executing AP-101S machine code. 

Two of the emulators instead accept programs in a form that's known as the HALMAT Intermediate Language, and execute instructions of the HALMAT language.  Where would you get such a "HALMAT" program from, and why in the world would you want to?  Getting your hands on HALMAT code is not a problem, because HALMAT is the natural way that the HAL/S compiler communicates amongst its various passes; in other words, HALMAT is going to be produced by the HAL/S compilation process automatically, whether you happen to care about it or not.  There are various pro's and con's related to emulation via HALMAT versus via AP-101S:

Installation of the Emulators

You can choose to install any or all of the available emulators.  Or none of them, of course, though if so, I'd question why you're even reading this at all.

I'd note that most of these emulators are written by independent developers and reside in their own projects, separate from the Virtual AGC Project itself, so I literally have no way of giving you authoritative installation instructions for them, or of dealing with problems you encounter using them.  Nor are all of the emulators (yet) at fully-comparable levels of development or capability.  Weighing all of that, I'll very-subjectively prioritize them as follows in terms of which ones I think might be most useful to you if you're complete newbies.  Of course, the rankings are just at the time of this writing ... all of which may (and probably will!) change in time.

yaHALMAT2

I'll assume you have a local clone of the Virtual AGC source tree from GitHub, and for the sake of argument I'll refer to that local directory as virtualagc.  But use the actual directory name in the instructions below.

To build it on Linux or Mac OS, simply
cd virtualagc/yaShuttle/yaHALMAT2/src
make clean all
On Windows, you should be able to build it either in an MSYS2 environment (for which the instructions should be the same as above), or else in a Windows "developer" terminal using Visual C.  In the latter case, I'm told that instead of make you have to use nmake, along with the makefile called Makefile.win.  But I've only built yaHALMAT2 on Linux, so you can regard anything I say about Mac OS or Windows as speculative.  The default on Linux, Mac, or Windows with MSYS2 is to use clang as the compiler if available, falling back on gcc.  Regardless of the platform, you can choose any compiler you want by specifying it on the make/nmake command line with the CC variable.  I have not tried that myself.

Finally, once compiled, unless you want to invoke yaHALMAT2 by using its full pathname, you'll probably want to copy or link yaHALMAT2[.exe] somewhere into your existing path, or else change your PATH variable to include the directory that yaHALMAT2 is in.  I'll let you to figure out that part.
gpc

To my recollection, I have lost the ability to build gpc from source, but perhaps the author's instructions might work for you.  I think what worked for me was to download the pre-built "AppImage" for Linux, rename it "gpc", and copy it into my path.  There are also pre-built Mac OS "dmg" files at the same link, though I don't know how to use them myself.  As far as Windows is concerned, I haven't a clue as to what you have to do.
ap0000a

(Not yet publicly available. I've seen it privately, only in very-preliminary versions.)
yaHALMAT

You need first to clone the source tree from GitHub (or download it via a zipfile) into a local directory in your filesystem.  For the sake of discussion, let's suppose that the local directory is called Halmat.  If you've chosen to call it something else, then substitute the correct name instead.  To build it on Linux or Mac OS, do this:
cd Halmat/emu
make clean yaHALMAT
On Windows?  Maybe it will work.  I don't know, I've only tried it on Linux myself.

Finally, once compiled, unless you want to invoke yaHALMAT by using its full pathname, you'll probably want to copy or link yaHALMAT[.exe] somewhere into your existing path, or else change your PATH variable to include the directory that yaHALMAT is in.  I'll let you to figure out that part.

The Mystery of HALMAT

Supporting HALMAT is quite a bit trickier than supporting AP-101S machine language, not because of its structure, but for historical reasons.  So a few words of explanation are in order.

As you already know, the original compiler used for converting Space Shuttle flight software written in the high-level language known as HAL/S into assembly-language object code for the Space Shuttle's general purpose computers was partitioned into several successive passes as follows:

Given that any emulation is going to be run on modern computers that are many times faster than the original AP-101S computers, with incredibly more memory, one might question the continued need for "optimization" at all.  So if you were going to run a HAL/S program by emulating its HALMAT rather than its AP-101S machine code, your development pipeline could conceivably reduce from

Compiler PASS1 → OPT → PASS2 → link → AP-101S emulator
to just

Compiler PASS1 → HALMAT emulator

What makes the latter even more compelling, at least at first glance, is that we have two separate versions of the HAL/S compiler's PASS1, and in the second pipeline can use the version of the compiler that's easier to install.

Sounds promising.  But alas, not perfect!  Where this concept has fallen apart up to now is the inadequacy of surviving documentation about HALMAT.  Without a satisfactory definition of the HALMAT language, how might we be expected to create an emulator for it?  On the other hand,  some HALMAT documentation has survived:
  1. A complete description was written up in 1971.  As the document itself explains, it "is essentially a handbook of an intermediate language HALMAT produced and used during the operation of the HAL360-V1 compiler".  In case it isn't obvious, HAL360-V1 was Intermetrics's very first attempt at a HAL compiler — not yet HAL/S —, producing object code running on an IBM System/360 computer rather than an AP-101S computer.  Actually, the document says only that HAL360-V1 ran on an IBM System/360, and doesn't explicitly say that the compiled form of the HAL software ran on a System/360; but the document nowhere mentions the AP-101 computer, and that seems very telling!  Besides which, the document specifically calls HAL360-V1 a "preliminary version", or as we might think of it, a proof of concept.  The problem is, that being "preliminary", details changed later!  How much was changed or added we can't tell from a superficial examination, but changes there definitely were.
  2. Intermetrics's much later document IR-60, "HAL/S-360 Compiler System Specification", has a very large Appendix A that specifies the HALMAT instructions in detail.  We have no assurance that this is the final form of the HALMAT language, but all later documentation refers back to IR-60 as the authoritative source, so I think we should probably recognize it as such as well.  Unfortunately, the only copy of IR-60 which has survived to fall into our hands is Revision 5 of the document, IR-60-5 from 1977, and this version contains only the pages that changed between Revision 4 and Revision 5.  The complete Appendix A, which from the page markings must contain at least 118 pages, has only 20 pages in our surviving copy!  Then too, a Revision 6 is known to have been in the JSC library at one time — though not any longer — and so potentially there could have been changes later even than in what has survived in our copy.  It could be that more-complete copies of IR-60 still exist somewhere, perhaps in the hands of a collector, but for now we have no reason to believe that they weren't all simply thrown away.
  3. Though not "documentation" as such, the HAL/S-FC compiler passes PASS1, OPT, and PASS2 all outputed and/or inputed HALMAT files, so potentially one could get additional information about HALMAT's individual instructions or groupings of instructions by looking through HAL/S-FC source code.
  4. Moreover, PASS1 has the optional capability of interleaving HAL/S statements with the derived HALMAT in the compilation reports it generates.  Similarly, PASS2 has the optional capability of interleaving HALMAT with the assembly-language instructions it generates in the compilation reports it generates.  (And even OPT, which normally doesn't output much of a report, has an analogous capability.)  Therefore, by crafting sample HAL/S source-code files and compiling them, it's possible to deduce more detail about HALMAT instructions as well.

Thus although complete documentation about HALMAT in a nicely-packaged, authoritative document seems to have escaped us, it is not necessarily clear that we couldn't regenerate a complete description of the language through reverse engineering.  And if we could do that, perhaps a HALMAT emulator could become a reality.  It is, however, very tricky to do so, or to justify without advance guarantee of success.

Zane Hambly (go, Zane!) made the first key steps in that direction.  Zane's key idea was to provide a parser that roughly served to analyze the source code of the original HAL/S compiler (which was written in a computer language I call XPL/I, though the original developers misleadingly called it XPL).  This allowed picking out all references to how HALMAT was generated or used by the original compiler.  Zane's synthesis of all of that led to a preliminary description of HALMAT and its many instructions is in the form of a single document describing all that was then known or suspected about HALMAT.  Indeed, he went farther than that, and created a preliminary HALMAT emulator based on the synthesized specification.  The emulator itself is called yaHALMAT, and as we discussed in the installation section above, resides in Zane's own repository.  At this writing, the fly in the ointment is that after the extremely-rapid initial development of the HALMAT spec and of yaHALMAT, life and priorities intervened and progress came to a halt.  Zane seems clear that it will resume, and we'll keep our fingers crossed that he's right.  In the meantime, the work that has been done so far serves as a very powerful proof-of-concept.

The hiatus in yaHALMAT development just mentioned has motivated me to follow-up Zane's work by leveraging AI, and specifically ANTHROP\C Claude (using LLM Sonnet 5).  While this is pretty far-out thinking, Claude has proven up to the task, managing (albeit with guidance) to create both new documentation for HALMAT and a new emulator (yaHALMAT2, based loosely on yaHALMAT).

There's another tool for understanding HALMAT as well.  If you've read much of our discussions of the HAL/S language and the development tools provided for it, you'll have seen various examples of actual HALMAT.  But those examples have always been in the form of incomprehensible numerical codes provided in one form or another by reports output by the HAL/S compiler.  [Nota bene: Aside from being incomprehensible in themselves, they are also sometimes actually wrong, in that HALMAT instructions may be duplicated, may be shown out of order, and so on.]  Those bursts of HALMAT code, unsurprisingly, have little value to us today, or at least not as-is.  To help bridge the comprehensibility gap a little, I've written a little utility called unHALMAT.py that produces a surprisingly useful and fairly human-friendly version of the HALMAT produced by the compiler, by combining it with other available information like symbol tables, literal files, and so on.  Here's what unHALMAT.py can do with the HALMAT file generated by compiling our ubiquitous HELLO.hal program:
> HALSFC --clean --archive --parms=SRN,LSTALL,ADDRS,LISTING2 HELLO.hal
Results stored in the folder "archive.results/HALSFC HELLO.hal 2026-07-20 06-51-35.results".
Accessible also as "current.results" until next HALSFC run.
For previous runs see also "current-1.results", "current-2.results".
Compilation successful.
> cd current.results
> unHALMAT.py halmat.bin
7200 bytes read from halmat.bin
RECORD 0
HALMAT #0 (0x005, Start of HALMAT block): PXRC(1) 00 0 0
HALMAT #1 | 05C 00 00( 0) 00 00 00 01 00 00 (Matching XREC is at HALMAT #92)
HALMAT #2 (0x02B, Start of PROGRAM definition): MDEF(1) 00 0 0
HALMAT #3 | 001 00 01(SYT) 00 00 00 01 00 00 (Symbol #1: HELLO, PROGRAM LABEL)
HALMAT #4 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #5 | 001 00 00( 0) 00 00 01 01 00 01 (HAL/S statement #1)

1 M| HELLO: |
1 M| PROGRAM; |

HALMAT #6 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #7 | 002 00 00( 0) 00 00 00 01 00 00 (HAL/S statement #2)

2 M| DECLARE I INTEGER; |

HALMAT #8 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #9 | 003 00 00( 0) 00 00 00 01 00 00 (HAL/S statement #3)

3 M| DECLARE POOKIE CHARACTER(20); |

HALMAT #10 (0x841, CHARACTER INITIAL value): CINT(2) 02 0 0
HALMAT #11 | 004 00 01(SYT) 00 00 00 01 00 00 (Symbol #4: MY_NAME, CHARACTER ALIGNED STATIC INITIAL)
HALMAT #12 | 003 00 05(LIT) 00 00 00 01 00 00 (Literal #3: Type CHARACTER, 'RON BURKEY')
HALMAT #13 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #14 | 004 00 00( 0) 00 00 00 01 00 00 (HAL/S statement #4)

4 M| DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); |

HALMAT #15 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #16 | 005 00 00( 0) 00 00 00 01 00 00 (HAL/S statement #5)

5 M| DECLARE INTEGER, J; |

HALMAT #17 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #18 | 006 00 00( 0) 00 00 00 01 00 00 (HAL/S statement #6)

6 M| REPLACE PRINTER BY "6"; |

HALMAT #19 (0x031, End of DECLAREs): EDCL(0) 01 1 0
HALMAT #20 (0x025, Start of argument list): XXST(1) 00 1 0
HALMAT #21 | 002 00 06(IMD) 00 00 00 01 00 00 (Immediate integer data 2 0x2)
HALMAT #22 (0x027, Argument): XXAR(1) 00 1 0
HALMAT #23 | 005 02 05(LIT) 00 00 00 01 00 00 (Literal #5: Type CHARACTER, 'THE BEGINNING')
HALMAT #24 (0x021, WRITE statement): WRIT(1) 00 0 0
HALMAT #25 | 006 00 06(IMD) 00 00 00 01 00 00 (Immediate integer data 6 0x6)
HALMAT #26 (0x026, End of argument list): XXND(0) 00 0 0
HALMAT #27 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #28 | 007 00 00( 0) 00 00 01 01 00 01 (HAL/S statement #7)

7 M| WRITE(PRINTER) 'THE BEGINNING'; |
.
.
.

 HALMAT #79 (0x025, Start of argument list): XXST(1) 00 1 0
HALMAT #80 | 002 00 06(IMD) 00 00 00 01 00 00 (Immediate integer data 2 0x2)
HALMAT #81 (0x027, Argument): XXAR(1) 00 1 0
HALMAT #82 | 011 02 05(LIT) 00 00 00 01 00 00 (Literal #17: Type CHARACTER, 'THE END')
HALMAT #83 (0x021, WRITE statement): WRIT(1) 00 0 0
HALMAT #84 | 006 00 06(IMD) 00 00 00 01 00 00 (Immediate integer data 6 0x6)
HALMAT #85 (0x026, End of argument list): XXND(0) 00 0 0
HALMAT #86 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #87 | 00E 00 00( 0) 00 00 01 01 00 01 (HAL/S statement #14)

14 M| WRITE(6) 'THE END'; |

HALMAT #88 (0x030): CLOS(1) 00 0 0
HALMAT #89 | 001 00 01(SYT) 00 00 00 01 00 00 (Symbol #1: HELLO, PROGRAM LABEL)
HALMAT #90 (0x004, HAL/S statement marker): SMRK(1) 00 1 0
HALMAT #91 | 00F 00 00( 0) 00 00 01 01 00 01 (HAL/S statement #15)

15 M| CLOSE HELLO; |

HALMAT #92 (0x002, End of HALMAT block): XREC final

Human-friendly, you say?  What kind of dope dream is that?  Well, let's just go through a few lines of it:

Emulating HALMAT

One characteristic of HALMAT files is that they don't quite contain all of the information needed to run the program.  The thing they're missing is the values of literals, and HALMAT emulators have to be supplied that information separately from the HALMAT file itself.  The values of literals are actually provided in two files, both of which are needed, with filenames differing according to the compiler or compiler pass that produced them. One of the files contains the values and indications of datatypes for all of the literals, except that the textual data for CHARACTER literals instead appears in the second of the files, with the first file providing only an index into the second file.  Too complex for your tastes?  Mine too!  But I'm not the one who set it up that way.  Here's a handy lookup table for the default filenames involved:
Compiler/Pass
HALMAT Filename
First Literal File
Second Literal File
HALSFC-PASS1
halmat.bin
litfile0.bin
COMMON0.out.bin.gz
HALSFC-OPT
optmat.bin
litfile2.bin
COMMON2.out.bin.gz
HAL_S_FC.py
FILE1.bin
FILE2.bin
LIT_CHAR.bin

But ... literals?  What are they?  If you're actually interested, here's a long digression to sate your curiosity. There are 3 types of literals in HAL/S: numeric literals (corresponding to INTEGER and SCALAR datatypes), string literals (CHARACTER datatype), and bit literals (BIT datatype).  It's best to illustrate them by looking at the source-code itself, where I've highlighted all of the literals in purple:
DEBUG ¢C¢D¢E¢F
HELLO: PROGRAM;
DECLARE I INTEGER;
DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY');
DECLARE INTEGER, J;
REPLACE PRINTER BY "6";
WRITE(PRINTER) 'THE BEGINNING';
DO FOR I = 1 TO 5;
WRITE(PRINTER) I, 'HELLO, WORLD!';
DO FOR J = 2 TO 8 BY 2;
WRITE(PRINTER) ' ', J, MY_NAME||' SAYS ISN''T THIS FUN?';
END;
END;
WRITE(6) 'THE END';
CLOSE HELLO;
I bet you're scratching your head over that, aren't you?    You're asking why "6" is not a literal but PRINTER is one?  Remember that in HAL/S, something like REPLACE PRINTER BY "6" is really a preprocessor instruction causing every instance of PRINTER to be replaced by 6.  So as far as the HALMAT is concerned, there isn't any such thing as "PRINTER", there's only 6, whereas to the compiler the opposite is true.

In fact, we have a handy utility (unLitfile) that parses these litfiles into human-readable form, so you can see exactly what literals they are communicating:
> unLitfile litfile0.bin
Literal 1: FIXED 42140000,00000000 ' 2.000000000000000E+01'
Literal 2: STRING 'RON BURKEY'
Literal 3: FIXED 41600000,00000000 ' 6.000000000000000E+00'
Literal 4: STRING 'THE BEGINNING'
Literal 5: FIXED 41100000,00000000 ' 1.000000000000000E+00'
Literal 6: FIXED 41500000,00000000 ' 5.000000000000000E+00'
Literal 7: FIXED 41600000,00000000 ' 6.000000000000000E+00'
Literal 8: STRING 'HELLO, WORLD!'
Literal 9: FIXED 41200000,00000000 ' 2.000000000000000E+00'
Literal 10: FIXED 41800000,00000000 ' 8.000000000000000E+00'
Literal 11: FIXED 41200000,00000000 ' 2.000000000000000E+00'
Literal 12: FIXED 41600000,00000000 ' 6.000000000000000E+00'
Literal 13: STRING ' '
Literal 14: STRING ' SAYS ISN'T THIS FUN?'
Literal 15: FIXED 41600000,00000000 ' 6.000000000000000E+00'
Literal 16: STRING 'THE END'
Exactly as you might guess from our purple highlights!
Aside: Beware, though, because the litfile format doesn't allow determination of the total number of literals contained within it — you just have to know! —, so unLitfile doesn't know for sure where the list ends.  There may be extra literals at the end of the list that look like real literals but have little to do with anything in the HAL/S source code.  More precisely: the litfile is formatted as a series of "pages" of 130 literals each, and generally speaking, any unused areas in the final page will be duplicates of literals found in corresponding locations on the penultimate page.  If there are 130 or less literals, as in the example above, all is well.  If there are more than 130, but not an exact multiple of 130, there will be bogus literals at the end.
But you don't really need unLitfile if you're just curious about how literals are communicated between compiler passes.  When ¢E is present in a DEBUG directive in the HAL/S file, it causes the compiler to print the entire literal table in the report (pass1.rpt) it emits from its parsing path.  Not surprisingly, you get the same info as from unLitfile, albeit with a little less info ... but with the added benefit that since the compiler actually knows how many literals there are, it doesn't print any bogus ones at the end of the list!
L I T E R A L   T A B L E   D U M P:

LOC TYPE LITERAL

1 ARITH 4214000000000000
2 CHAR RON BURKEY
3 ARITH 4160000000000000
4 CHAR THE BEGINNING
5 ARITH 4110000000000000
6 ARITH 4150000000000000
7 ARITH 4160000000000000
8 CHAR HELLO, WORLD!
9 ARITH 4120000000000000
10 ARITH 4180000000000000
11 ARITH 4120000000000000
12 ARITH 4160000000000000
13 CHAR
14 CHAR SAYS ISN'T THIS FUN?
15 ARITH 4160000000000000
16 CHAR THE END

The other little mystery, if you've kept your eyes open, is that unLitfile seems to be implying that literals like 1, 8, or 6 are really floating-point.  Or at least, are stored that way.   It's true.  The numeric literals, whether SCALAR or INTEGER, double or single precision, are stored in the litfiles as double-precision floating point in so-called IBM Hexadecimal (HFP) format.  BIT literals, on the other hand, of which there are none in our example, are all stored as 32-bit big-endian form.

Zane Hambly's Emulator

My illustrating comments here are frozen at the emulator's condition when I first wrote about it, so you may find some differences if you try out the emulator now.  All of Zane's material is in his own GitHub repositoryThat's also where bugs should be reported, as "issues" in the repository.

This program itself is called yaHALMAT — or probably yaHALMAT.exe on Windows, though I haven't tried it there myself — and you'll want to make sure that it gets into your PATH.  Assuming you've done all that, it's time to play!  I'll give a few examples of my own below, although Zane has some of his own as well.

What's the first thing to try out?  You know the answer, so why even ask?  Here's a program I call REALLY_HELLO.hal (to distinguish it from the entirely-different sample program I foolishly called HELLO.hal that we've been using throughout many of our discussions of HAL/S):
 HELLO: PROGRAM;
WRITE(6) 'Hello, world!';
CLOSE HELLO;
Compile it:
HALSFC --test REALLY_HELLO.hal
And now we want to run it.  As we saw above, there are several different HALMAT files we could use, so there are several different yaHALMAT invocations we could use.  Running the unoptimized HALMAT from HALSFC would be done like this:
yaHALMAT halmat.bin
Whereas running the optimized HALMAT would look like:
yaHALMAT optmat.bin
Or we could use the unoptimized HALMAT from HAL_S_FC.py.  In principle, the compilation command for that would have been
HAL_S_FC.py --hal=REALLY_HELLO.hal
but I accomplished the same thing by adding the --test switch to the HALSFC command line, so we end up with the files we wanted anyway:
yaHALMAT --litfile FILE2.bin --common LIT_CHAR.bin FILE1.bin
The output in any of these emulations looks exactly the same:
Hello, world!
But instead, let's try the goofy HELLO.hal we've been using to demonstrate lots of stuff, namely
DEBUG ¢C¢D¢E¢F
HELLO: PROGRAM;
DECLARE I INTEGER;
DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY');
DECLARE INTEGER, J;
REPLACE PRINTER BY "6";
WRITE(PRINTER) 'THE BEGINNING';
DO FOR I = 1 TO 5;
WRITE(PRINTER) I, 'HELLO, WORLD!';
DO FOR J = 2 TO 8 BY 2;
WRITE(PRINTER) ' ', J, MY_NAME||' SAYS ISN''T THIS FUN?';
END;
END;
WRITE(6) 'THE END';
CLOSE HELLO;
Compile and run it:
> HALSFC HELLO.hal
Compilation successful. Results in "HALSFC HELLO.hal Tue 02-24-2026 6-50-07.00.results".
> yaHALMAT halmat.bin
THE BEGINNING
1 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
0 RON BURKEY SAYS ISN'T THIS FUN?
0 RON BURKEY SAYS ISN'T THIS FUN?
0 RON BURKEY SAYS ISN'T THIS FUN?
0 RON BURKEY SAYS ISN'T THIS FUN?
0 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
0 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
0 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
0 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
0 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
THE END

And just for OCD's sake, a final example source-code example:
 POWER_TABLE: PROGRAM;
WRITE(6) ' N N**2 N**3 N**4 N**5';
WRITE(6) ' ---------- ---------- ---------- ---------- ----------';
DO FOR TEMPORARY N = 1 TO 10;
WRITE(6) N, N N, N**3, N**4, N**5;
END;
CLOSE POWER_TABLE;
Emulating this we get:
          N       N**2       N**3       N**4       N**5
---------- ---------- ---------- ---------- ----------
1 1 1 1 1
2 4 8 16 32
3 9 27 81 243
4 16 64 256 1024
5 25 125 625 3125
6 36 216 1296 7776
7 49 343 2401 16807
8 64 512 4096 32768
9 81 729 6561 59049
10 100 1000 10000 100000

Claude's Emulator

As I mentioned earlier, the "Claude" in this case is ANTHROP\C Claude.  Unlike the other emulators described herein, the emulator Claude (with some advice from me) developed is actually part of Virtual AGC itself, so it's the one emulator over which we can actually exhibit some control. 

Our first step was to regenerate complete HALMAT documentation, using not only the technique pioneered earlier by Zane Hambly, but also extensive compilation of HAL/S test code, comparison of HALMAT to generated object code, and refering to additional documentation not specific to HALMAT that might not have been previously consulted ... in other words, to hit the problem with an enormous helping of obsessive attention to detail.  After all of that had been completed, and only then, a final cross-check was done against Zane's earlier reconstructed documentation.  While there were discrepancies (i.e., errors) on both sides when the cross-check was performed, they were surprisingly few, which should give us some confidence in the results.  Of course, Claude's errors have been corrected by the time you've read this.

This new, full HALMAT documentation can be seen on GitHub.  As a slap in the face to the current hubbub about how "human" A.I. is, this new documentation looks very much as though a machine wrote it ... or at least someone with little interest in engaging the reader.  With that's said, it's kind of fascinating to look at, and indeed very informative if you're the kind of person who really likes to get at the nuts and bolts of everything.  If you're that person, you might be interested in the document that describes the current state of development, or the document used to plan development.  All of this documentation is in so-called "markdown" format to make it easy to update as further corrections become necessary, as well as being extensively annotated to describe how the results were arrived at.  I'd recommend just looking at it directly on GitHub if you're interested.  Of course, you could also download it and view it locally if you have a markdown viewer, though I'd note that not all markdown viewers are as capable as GitHub's.  In other words, your results may vary.

The next step was to proceed to implementation of the emulator itself, called yaHALMAT2 to distinguish itself from Zane's yaHALMAT.  To give credit where credit is due, Claude concluded that yaHALMAT had a nice, clean design, and therefore may have based yaHALMAT2 at least partially on it.

Enough yapping!  Let's compile and emulate our ever-present HELLO.hal sample code that's not a "HELLO" program at all, namely (in its latest incarnation as of this writing):
DEBUG ¢4 ¢E
HELLO: PROGRAM;
DECLARE I INTEGER;
DECLARE POOKIE CHARACTER(20);
DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY');
DECLARE INTEGER, J;
REPLACE PRINTER BY "6";
WRITE(PRINTER) 'THE BEGINNING';
DO FOR I = 1 TO 5;
WRITE(PRINTER) I, 'HELLO, WORLD!';
DO FOR J = 2 TO 8 BY 2;
WRITE(PRINTER) ' ', J, MY_NAME||' SAYS ISN''T THIS FUN?';
END;
END;
WRITE(6) 'THE END';
CLOSE HELLO;

Compile it and run it:
> HALSFC  HELLO.hal
Results stored in the folder "HALSFC HELLO.hal 2026-07-20 11-50-02.results".
Accessible also as "current.results" until next HALSFC run.
For previous runs see also "current-1.results", "current-2.results".
Compilation successful.
> yaHALMAT2 halmat.bin
THE BEGINNING
1 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
2 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
3 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
4 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
5 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
THE END
The emulator also has a debugging mode built into it, modeled after the gdb debugger.  Below, I load halmat.bin in debugging mode and single step through a few HALMAT instructions:
> yaHALMAT2 --debug halmat.bin
yaHALMAT2 debugger. Type 'help' for commands. 1 HELLO: 1 PROGRAM; [task 0] #0 0x005 PXRC numop=1 tag=0x00 copt=0x0 ; Record header, points to closing XREC [0] data=0x005C(92) qual= 0 tag1=0x00 tag2=0x0 (halmat) step [task 0] #2 0x02B MDEF numop=1 tag=0x00 copt=0x0 ; Program definition header [0] data=0x0001(1) qual=SYT tag1=0x00 tag2=0x0 (halmat) step [task 0] #4 0x004 SMRK numop=1 tag=0x00 copt=0x1 ; Statement marker [0] data=0x0001(1) qual= 0 tag1=0x00 tag2=0x1 (halmat) step 2 DECLARE I INTEGER; [task 0] #6 0x004 SMRK numop=1 tag=0x00 copt=0x1 ; Statement marker [0] data=0x0002(2) qual= 0 tag1=0x00 tag2=0x0 (halmat) step 3 DECLARE POOKIE CHARACTER(20); [task 0] #8 0x004 SMRK numop=1 tag=0x00 copt=0x1 ; Statement marker [0] data=0x0003(3) qual= 0 tag1=0x00 tag2=0x0 (halmat) step 4 DECLARE MY_NAME CHARACTER(20) INITIAL('RON BURKEY'); [task 0] #10 0x841 CINT numop=2 tag=0x02 copt=0x0 ; Character initialize [0] data=0x0004(4) qual=SYT tag1=0x00 tag2=0x0 [1] data=0x0003(3) qual=LIT tag1=0x00 tag2=0x0 (halmat) step [task 0] #13 0x004 SMRK numop=1 tag=0x00 copt=0x1 ; Statement marker [0] data=0x0004(4) qual= 0 tag1=0x00 tag2=0x0 (halmat) step 5 DECLARE INTEGER, J; [task 0] #15 0x004 SMRK numop=1 tag=0x00 copt=0x1 ; Statement marker [0] data=0x0005(5) qual= 0 tag1=0x00 tag2=0x0 (halmat) step 6 REPLACE PRINTER BY "6"; [task 0] #17 0x004 SMRK numop=1 tag=0x00 copt=0x1 ; Statement marker [0] data=0x0006(6) qual= 0 tag1=0x00 tag2=0x0 (halmat) step 7 WRITE(PRINTER) 'THE BEGINNING'; [task 0] #19 0x031 EDCL numop=0 tag=0x01 copt=0x1 ; End-of-declarations marker (halmat) step [task 0] #20 0x025 XXST numop=1 tag=0x00 copt=0x1 ; I/O statement start, carries I/O-kind code [0] data=0x0002(2) qual=IMD tag1=0x00 tag2=0x0 (halmat) kill execution stopped (halmat) quit
The colors are adjustable via the command line, or can be disabled entirely.  HALMAT instructions aren't just dumped on you willy-nilly in binary, but are instead parsed into a somewhat human-readable format like the unHALMAT.py utility discussed earlier, along with embedding the HAL/S source code so you can see the larger context.

But I'm bored with HELLO.hal!  Let's look at some other examples that aren't quite so lame.

Another feature supported by yaHALMAT2 is loading multiple HALMAT files at once.  Or to put it loosely, yaHALMAT2 can act like an on-the-fly "linker" for HALMAT files.  Each HALMAT file corresponds to a HAL/S source-code file, and very few significant programs are written as a single source-code file, so this is a necessary feature.

The yaHALMAT2 command line supports two different formats for selecting the HALMAT file(s) to load for emulation.  The syntax we used above supports only a single file:
yaHALMAT2 [OPTIONS] HALMAT_FILE
Pragmatically speaking, while HALMAT_FILE could be anything you desire, it's actually always halmat.bin, optmat.bin, or FILE1.bin, and it expects to find those files in the current directory.  (You could use a path to somewhere else, but trust me, it would turn out to be a lot more hassle than it's worth.)  The problem with directly extending this kind of command-line format to multiple HALMAT files (or to not use the current working directory) is that each HALMAT file is accompanied by various auxiliary files that are either absolutely necessary (like the literal files described earlier) or else really nice to have for the debugger (such as the output report from PASS1 of the HAL/S compiler).  The HAL/S compiler produces these files, and lots of others, for each HAL/S source-code files it compiles.  To keep your working directory clean of this multitude of files, as well as to maintain order, a typical strategy is to perform all of your HAL/S compilations with the HALSFC command-line switch --clean, or possibly --clean --archive.  This strategy creates a new subdirectory for each compilation and shoves all of the files that were generated into it.

We can exploit this when we invoke yaHALMAT2 by using the alternate syntax
yaHALMAT2 [OPTIONS] @LIST
That's for running unoptimized HALMAT (output by the compiler's PASS1), whereas to run optimized HALMAT (output by the compilers OPT pass) we could instead say
yaHALMAT2 [OPTIONS] --opt @LIST
But the results are indistinguishable.  Here, LIST is the name of a file that contains a list of directories of the kind that HALSFC produces for its output products. 
Aside: One useful trick is to make a file — let's call it CURRENT — that just contains the single line "current.results".  Then invoking yaHALMAT2 @CURRENT always runs the HAL/S program that you've compiled most recently.
Actually demonstrating how this works in practice is a little more involved that our simple HELLO.hal example, so bear with me!  Let's imagine a HAL/S PROGRAM that prints a table of squares and square roots of integers, and that for some inexplicable reason we've decided to provide two external functions, one that squares a number, and one that computes a square root.  Here's what our code might look like:

C SQUARE.hal
SQUARE: FUNCTION(X) SCALAR;
DECLARE X SCALAR;
RETURN X X;
CLOSE SQUARE;
C MYTABLE.hal
D INCLUDE TEMPLATE SQUARE
D INCLUDE TEMPLATE SQUROO
MYTABLE: PROGRAM;
DO FOR TEMPORARY I = 1 TO 10;
WRITE(6) I, SQUARE(I), SQU_ROOT(I);
END;
CLOSE MYTABLE;
C SQUROO.hal
SQU_ROOT: FUNCTION(X) SCALAR;
DECLARE X SCALAR;
RETURN SQRT(X);
CLOSE SQU_ROOT;
Compile it:
HALSFC --clean --archive --parms=TEMPLATE SQUARE.hal
HALSFC --clean --archive --parms=TEMPLATE SQUROO.hal
HALSFC --clean --archive MYTABLE.hal
This creates directories for the compiler output products of:
For you, of course, the directory names would be different, since they'd have different dates/times.  Next you have to create a file called "LIST" that points to these directories:
archive.results/HALSFC SQUARE.hal 2026-07-20 18-20-58.results
archive.results/HALSFC SQUROO.hal 2026-07-20 18-19-01.results
archive.results/HALSFC MYTABLE.hal 2026-07-20 18-21-04.results
Notice that there are spaces in these directory names as stored in LIST, but no surrounding quotation marks are used.  (Quotation marks would break it!)  Run it:
> yaHALMAT2 @LIST
1 1.0000000E+00 1.0000000E+00
2 4.0000000E+00 1.4142132E+00
3 9.0000000E+00 1.7320499E+00
4 1.6000000E+01 2.0000000E+00
5 2.5000000E+01 2.2360678E+00
6 3.6000000E+01 2.4494896E+00
7 4.9000000E+01 2.6457510E+00
8 6.4000000E+01 2.8284264E+00
9 8.1000000E+01 3.0000000E+00
10 1.0000000E+02 3.1622772E+00
Multi-file capability isn't fully implemented yet in yaHALMAT2.  HAL/S real-time mechanisms allow multiple PROGRAM's to be simultanously running, while flipping back and forth between them, whereas all we have implemented so far is a single PROGRAM plus multiple COMPOOL's, PROCEDURE's, and FUNCTION's.  First things first!

Actually, I gave yaHALMAT2 short shrift earlier when I said that it could act as an "on-the-fly" HALMAT linker.  While that's true, it can act as an actual HALMAT linker as well.  What do I mean by that?  Well, while this @LIST mechanism may be reasonably-efficient for development purposes, it's not very convenient for actually distributing a program in HALMAT form to anybody.  If a program consisted of (say) 10 HAL/S source-code files, to give the program's HALMAT to anybody we'd have to send out 40 files generated by the HAL/S compiler, some of them big ones, stored in a rigid directory hierarchy.  Sure, we could do it — that's what zipfiles are for, after all — but it seems like a bit of overkill.  We can bypass that problem by running yaHALMAT2 with the --link-only option:
yaHALMAT2 --link-only MYTABLE.yhla @LIST
This doesn't perform any emulation, but instead just produces a new file (MYTABLE.yhla) that we can think of as the "linked" form of the program.  And MYTABLE.yhla doesn't just contain the HALMAT instructions, but it also contains the literal files, as well as the HAL/S source-code lines for display in the emulator's debugger ... i.e., it's entirely self-contained.  Obviously, there is no pre-existing file format for "linked" HALMAT, and never was one, so Claude invented one for us, and documented it too.  Why the filename extension ".yhla"?  I asked, using up hundreds of precious tokens, and got this answer: 
"YHLA" is my own abbreviation for YaHalmat Linked Archive — I picked it as the 4-byte magic when I specified the container format for the implementing agent, following the convention of short ASCII magic-number prefixes (like "PK" for zip, "GZ"-ish headers for gzip). No deeper significance than that.
Makes sense to me.  Anyway, you can run a YHLA without any particular to-do; yaHALMAT2 just recognizes from the embedded magic numbers that it's a YHLA file rather than a HALMAT file:
> yaHALMAT2 MYTABLE.yhla
1 1.0000000E+00 1.0000000E+00
2 4.0000000E+00 1.4142132E+00
3 9.0000000E+00 1.7320499E+00
4 1.6000000E+01 2.0000000E+00
5 2.5000000E+01 2.2360678E+00
6 3.6000000E+01 2.4494896E+00
7 4.9000000E+01 2.6457510E+00
8 6.4000000E+01 2.8284264E+00
9 8.1000000E+01 3.0000000E+00
10 1.0000000E+02 3.1622772E+00
yaHALMAT2 also supports HAL/S's so-called "real time" features.  Consider the following example program, which simply counts up from 1 to 20, once per second:
 COUNTUP: PROGRAM;
DECLARE I INTEGER INITIAL(1);

NEXT: TASK;
WRITE(6) I;
I = I + 1;
CLOSE NEXT;

SCHEDULE NEXT PRIORITY(80), REPEAT EVERY 1.0;
WAIT 19.5;
CLOSE COUNTUP;
> HALSFC --clean --archive COUNTUP.hal
> # Note that LISTC contains a single entry: current.results
> time yaHALMAT2 @LISTC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

real 0m19.555s
user 0m0.045s
sys 0m0.010s
Windows users may wonder why the command to start the emulation has the word time in front of it.  It has nothing to do with using the SCHEDULE or WAIT feature.  Rather, in Linux or Mac OS that just means to time how long the program took, which was 19.555 seconds.  And why 19.5 seconds?  Because it only takes 19 seconds to count from 1 to 20 if you do so once per second.

Here's another example which is somewhat similar, but which illustrates a different use of real-time features, not to mention matrix multiplication, subscript slicing, printing of vectors, and repetition factors in initializers.  It performs the silly functionality of taking a "random" 5×5 orthogonal matrix (i.e., a rotation matrix in 5 dimensions) that I got from Google's A.I. assistant, and just prints several powers of it.  Who wouldn't want to do that?
 MPOWERS: PROGRAM;
DECLARE P5D MATRIX(5,5) INITIAL(4#(1,5#0),1);
DECLARE M5D MATRIX(5,5) INITIAL(
-0.2877, 0.0722, -0.6645, -0.6217, -0.2898,
0.1356, -0.8101, -0.4713, 0.2571, 0.1928,
0.2684, 0.2374, -0.3093, 0.5534, -0.6853,
0.3257, 0.5176, -0.4731, 0.1254, 0.6217,
-0.8489, 0.1197, -0.1294, 0.4748, 0.1508);
DECLARE COUNT INTEGER INITIAL(0);

PRINT_MATRIX_5D: PROCEDURE(M);
DECLARE M MATRIX(5,5);
DO FOR TEMPORARY I = 1 TO 5;
WRITE(6) '', M$(I,*);
END;
CLOSE PRINT_MATRIX_5D;

WRITE(6) 'Powers of a "random" 5D rotation matrix:';
WRITE(6) '';

MUL5D: TASK;
WRITE(6) COUNT;
CALL PRINT_MATRIX_5D(P5D);
WRITE(6) '';
COUNT=COUNT+1;
IF COUNT > 5 THEN
CANCEL MUL5D;
P5D = M5D P5D;
SCHEDULE MUL5D IN 1.0 PRIORITY(80) DEPENDENT;
CLOSE MUL5D;

SCHEDULE MUL5D PRIORITY(80) DEPENDENT;
CLOSE MPOWERS;
Aside: For full disclosure, I should add that having a TASK re-SCHEDULE itself is not something it's entirely clear from the original documentation that it's something actually allowed.  Also, you'll notice that the PROGRAM ends immediately after the SCHEDULE statement, yet the TASK keeps running, which is again something we're not 100% certain about.  Both questions could be argued either way.  The HAL/S compiler certainly allows both.
And here's what happens when yaHALMAT2 runs it:
> HALSFC MPOWERS.hal
> yaHALMAT2 --line-length 132 halmat.bin
Powers of a "random" 5D rotation matrix:

0
1.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00
0.0000000E+00 1.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00
0.0000000E+00 0.0000000E+00 1.0000000E+00 0.0000000E+00 0.0000000E+00
0.0000000E+00 0.0000000E+00 0.0000000E+00 1.0000000E+00 0.0000000E+00
0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 1.0000000E+00

1
-2.8770000E-01 7.2199941E-02 -6.6450000E-01 -6.2169999E-01 -2.8979999E-01
1.3559997E-01 -8.1009996E-01 -4.7129995E-01 2.5709999E-01 1.9279999E-01
2.6839995E-01 2.3740000E-01 -3.0929995E-01 5.5339998E-01 -6.8529999E-01
3.2569999E-01 5.1760000E-01 -4.7309995E-01 1.2539995E-01 6.2169999E-01
-8.4889996E-01 1.1969995E-01 -1.2939996E-01 4.7479999E-01 1.5079999E-01

2
-4.2266667E-02 -5.9349424E-01 6.9430482E-01 -3.8586676E-01 1.2246466E-01
-3.5528886E-01 7.1031874E-01 2.9088461E-01 -4.2961472E-01 3.1641096E-01
6.3395023E-01 -4.1957617E-02 -3.6770761E-01 -5.3297925E-01 4.2065722E-01
-6.3741559E-01 -3.6878169E-01 -4.5381731E-01 -2.0317852E-02 5.0133419E-01
2.5235707E-01 7.4828267E-02 3.0356145E-01 6.1806560E-01 6.7569083E-01

3
-1.1160338E-01 4.5750028E-01 2.5975823E-01 2.6767653E-01 -7.9940951E-01
-1.3191772E-01 -7.1651912E-01 -2.6347093E-02 6.6083968E-01 -1.7880785E-01
-8.1745660E-01 -2.3305011E-01 -9.0033829E-02 -4.7551090E-01 -2.0773649E-01
-4.2062706E-01 1.9448555E-01 6.8247473E-01 2.8581071E-01 4.8759234E-01
-3.5327041E-01 4.3045807E-01 -6.7669034E-01 4.2866218E-01 2.1940875E-01

4
9.2966521E-01 -2.7415204E-01 -2.4499685E-01 -1.5235722E-02 -1.1599779E-02
3.0074650E-01 8.8532001E-01 1.4399827E-01 -1.1881304E-01 3.0202043E-01
2.0088887E-01 -1.6259080E-01 9.3272901E-01 2.4020857E-01 -7.3284745E-02
9.7340941E-03 1.8039769E-01 -2.2155517E-01 9.5653683E-01 -5.7088077E-02
-6.8258524E-02 -2.8672779E-01 9.9819899E-03 1.1374819E-01 9.4869202E-01

5
-3.6551166E-01 2.2177559E-01 -4.0406817E-01 -7.9145658E-01 -1.6559845E-01
-2.2290856E-01 -6.8664449E-01 -6.4450681E-01 2.4883038E-01 -4.3470025E-02
3.1094873E-01 4.8320842E-01 -4.4951409E-01 3.4480387E-01 -5.9047794E-01
3.2220203E-01 2.9023510E-01 -4.6811306E-01 1.0564327E-02 7.6986158E-01
-7.8485996E-01 4.0215373E-01 8.3014206E-04 4.3894553E-01 1.7143917E-01

In case you wonder about the command-line option --line-length 132, printouts by default wrap around to the next line afer 80 columns.  This option just increases that to 132 columns instead.

Emulating AP-101

Both of the emulators presented below accept an AP-101S memory image as input, as opposed (say) to an IBM "load file".  To produce such a memory image, it's necessary first to compile or assemble all of the individual source code modules comprising the program, and then to use a linker program to combine the separate object files generated by compilation/assembly.  Please refer to our linker page for more information for more specifics.  Below, for simplicity of expossion, we'll just suppose that you've compiled a HAL/S program called MYPROGRAM.hal, and have produced a memory image from it that's called MYPROGRAM.fcm, with ".fcm" being the conventional filename extension we use for memory images.

Specifically, we'll use the following test code called HELLO_WORLD.hal.

C A TEST PROGAM
  HELLO_WORLD: PROGRAM;
WRITE(6) 'Hello, world!';
WRITE(6) '';
CLOSE HELLO_WORLD;

Compiling it and linking it like so,

HALSFC -o HELLO_WORLD.obj HELLO_WORLD.hal
lnk101 -o HELLO_WORLD.fcm --json-symbols HELLO_WORLD.sym.json HELLO_WORLD.obj
gives us HELLO_WORLD.fcm.

Don Schmidt's Emulator

Don's emulator, gpc, can be run in either a simple mode that just executes the code without fanfare, or else in a fancy graphical debugging mode.  Let's just look at the simple mode first:

gpc run --interactive HELLO_WORLD.fcm

This results in:

Hello, world!

*** HAL/S PROGRAM HALT (SVC 0)

The --interactive switch tells the emulator to accept keyboard input on device 5 (as in the HAL/S READ(5) ...;) and output to device 6 (as in the HAL/S WRITE(6) ...;).  In this example, we could hav just omitted it.

Or if we were to try the same thing but with our ubiquitous but misnamed HELLO.hal, we'd get this instead:

THE BEGINNING
1 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
2 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
3 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
4 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
5 HELLO, WORLD!
2 RON BURKEY SAYS ISN'T THIS FUN?
4 RON BURKEY SAYS ISN'T THIS FUN?
6 RON BURKEY SAYS ISN'T THIS FUN?
8 RON BURKEY SAYS ISN'T THIS FUN?
THE END

*** HAL/S PROGRAM HALT (SVC 0)

There are actually lots of command-line options, which you can view with the command gpc help run.

The second way to run the emulator is, as I mentioned, with a GUI debugging interface.  You could use a command like,

gpc gui HELLO_WORLD.fcm

resulting in:

Just hit the Run hot-button and you'll see it change (look at the TERMINAL pane near the bottom of the window) to


No obvious way to exit the GUI emulator in these old screenshots, but when you actually run the program you'll see a Quit button near the top right.

If HELLO_WORLD.hal had been a more-interactive program, in which it not only used WRITE(6) to display messages but also READ(5) to get keyboard input from you, you could have typed your input into the pane at the bottom of the window, where it now shows the message "(waiting for program input...)".

Dan Weaver's Emulator

(Not yet publicly available.)




This page is available under the Creative Commons No Rights Reserved License
Last modified by Ronald Burkey on 2026-07-22

Virtual AGC is
              hosted by ibiblio.org