Instant PET: Commodore BASIC as Data-URL
mass:werk proudly presents: Running BASIC on a virtual PET 2001 from URL-data.
So you want to show your friends a little BASIC program or want to solve some problem with (retro) style? Despair no more, since help is near…
More specifically, just a click away, at www.masswerk.at/pet, where you find my enhanced version of Thomas Skibo’s in-browser PET 2001 emulation. What’s new is an additional mode, where the emulator loads (and runs) a program from data encoded in URL-parameters — as provided either in the query-string or in the URL-fragment (hash). And you may use this for immediate execution in direct mode, as well!
And here is how we do it:
Loading BASIC Programs from URL-Data
Entire programs may be submitted in the URL, encoded in an optional URL-parameter “data
”. The plain text of the program may be either encoded as URL-encoded text (default) or in base64 (using the prefix “base64:
” before your data stream. The program text may be either in upper-case or lower-case (auto-detected) and may contain encoded linebreaks.
Let’s say we want to encode this terrific little BASIC program:
10 PRINT "HELLO WORLD" 20 GOTO 10
To link this program, we encode the BASIC text as URI-encoded (x-www-form-urlencoded) and get something like this:
https://www.masswerk.at/pet/?data=10%20PRINT%20%22HELLO%20WORLD%22%0A20%20GOTO%2010
Note: Mind to replace any PETSCII screen characters by CHR$()
sequences! The emulator does this for you, see below.
This will load the decoded text as a program into memory, but will not start the program. In order to execute it automatically, we add the parameter “autostart=true
”:
https://www.masswerk.at/pet/?data=10%20PRINT%20%22HELLO%20WORLD%22%0A20%20GOTO%2010&autorun=true
Alternatively, we may want to encode the program in base64. For this, we use the prefix “base64:
” just before the encoded program:
https://www.masswerk.at/pet/?data=base64:MTAgUFJJTlQgIkhFTExPIFdPUkxEIgoyMCBHT1RPIDEw&autorun=true
We may also choose to supply the program in the URL-fragment (has) instead of in the query string:
https://www.masswerk.at/pet/#data=10%20PRINT%20%22HELLO%20WORLD%22%0A20%20GOTO%2010&autorun=true
Technically, the encoded text will be converted and tokenized and then transferred into the virtual PET by executing a load instruction. The default filename for this is “URL-DATA
”, but we may supply our own by use of the parameter “filname
” (or “fname
”, or just “name
”).
Note: For technical reasons (JavaScript’s methods “atob()
” and “btoa()
” for converting base64-encoded data to and from text) the special character π has to be escaped as “\pi
” (which may also come handy, when writing a short snippet — see below).
Here’s the full grammar (case insensitive):
<data-url> ::= ( "?" | "#" ) <parameters> <parameters> ::= <data-paramter> ["&" <autostart-parameter>] ["&" <filenname-parameter>] <data-paramter> ::= "data=" ( "base64:"<base64-data> | <uri-component> ) <autostart-parameter> ::= "autostart=" ( "true" | "yes" | "y" | "1" ) <filenname-parameter> ::= ( "filename" | "fname" | "name" ) "=" <filename> <escaped-π> ::= "\pi"
Ecexuting Snippets in Direct Mode
We may also submit a tiny problem in direct mode to solve it at once in (retro) style: Just use “exec
” or “execute
” instead of the “data
” keyword! Direct mode will be always executed at once, no need for the autostart
-parameter. (You may still use the URL-fragment/hash instead of the query-string and base64-encoding as well.)
This will automatically type and enter the provided text line by line.
For example,
https://www.masswerk.at/pet/?exec=print(100+20)*5
or
https://www.masswerk.at/pet/?exec=printsin(\pi/6)
Note: In case a snippet starts with a number, it will be treated as a program and executed at once.
Query String or Fragment (Hash)?
Both methods have their pros and cons: A query string is more robust and will pass through redirects, however, it is subject to logging and may be truncated due to limits set in server or proxy/gateway configurations. A hash is more private and will be handled in the browser only, but is likely to be lost in redirects.
Too Complicated? Let the Emulator Do the Work!
If this sounds too complicated, just let the emulator do the work: Type and test your program in the emulator. When happy, open the “Export” menu at the bottom of the emulated screen and select “BASIC Program as URL”. This will bring up the follow dialog, where you may select encoding, format and auto-start to your liking. Finally, copy the link by a right-click onto the displayed URL.
Just like the “portable listing” option, this will also take care of any special PETSCII characters and convert them automatically to “CHR$()
” sequences!
Further Examples
Some examples for some real program demos:
Hello World — More or Less
This will run a program producing an output like this:
### COMMODORE BASIC ###
7167 BYTES FREE
READY.
LOAD "URL-DATA",8
SEARCHING FOR URL-DATA
LOADING
READY.
RUN
HELLO WORLD
MORE OF THIS? [Y,N] Y
HELLO WORLD HELLO WORLD HELLO WORLD
HELLO WORLD HELLO WORLD HELLO WORL
D HELLO WORLD HELLO WORLD HELLO WO
RLD HELLO WORLD HELLO WORLD HELLO
WORLD HELLO WORLD HELLO WORLD HELL
O WORLD HELLO WORLD HELLO WORLD HE
Mind the “Screen Text as Unicode” export option to copy any output. :-)
Data-Link: Hello World (more or less).
A Fancy Password Routine
Here’s a subroutine for hidden password input, just give it a try…
10 PRINT:PRINT "PASSWORD: "; 20 GOSUB 3000 30 PRINT "YOU ENTERED: ";PW$ 40 END 3000 REM PASSWORD INPUT, RESULT IN PW$ 3001 ML=20:REM MAX LENGTH (1..255) 3002 REM CF: CURSOR FLAG, REM 3004 OR 3006 3003 REM PET (ROM 1 & 2) 3004 CF=548:IF PEEK(50003) THEN CF=167 3005 REM C64 3006 REM CF=204 3010 GET C$:IF C$<>"" THEN 3010 3020 PW$="":POKE CF,0 3030 PL=LEN(PW$) 3040 GET C$:IF C$="" THEN 3040 3050 A=ASC(C$):IF A=13 THEN POKE CF,1:PRINT " ":RETURN 3060 IF A=20 AND PL>0 THEN 3090 3070 IF (A AND 127) > 31 AND PL<ML THEN PW$=PW$+C$:PRINT "*"; 3080 GOTO 3030 3090 PW$=MID$(PW$,1,PL-1):PRINT" ";CHR$(157);CHR$(157);" ";CHR$(157);:GOTO 3030
Data-Link: Password Demo.
10 Line Adventure
And here’s Robin Harbron’s “10 Line Adventure”, a port to Commodore BASIC of Einar Saukas' “Tenliner Cave Adventure” (for Sinclair ZX81, 2016), encoded in a data-URL. A tiny text adventure in just 10 lines of BASIC and encoded in a single link! (Mind the use of a custom filename in the data-link.)
Data-Link: 10 Line URL-Data Adv.
An A-Mazing Code Snippet
Finally, here’s a maze oneliner as a code snippet (direct mode), no GOTO
involved:
Data-Link: No-Go Maze.
A Console to Assemble Your BASIC Link
Hint: Use “\pi
” or “{PI}
” for “π”.
Update:
You may now also use escape markup for special PETSCII characters, as in “{ddd}
” “{$hh}
” or “{label}
”. E.g., “{147}
” or “{$93}
” or “{CLEAR}
” (case insensitive) for the control character to clear the screen.
For a refresher on Commodore BASIC, see the “Pocket Reference Guide To Commodore’s 2001 PET™” (PDF).
P.S.: Just in case you didn’t know, you may also run BASIC programs in the emulator by drag and drop, from binary files (.prg
, .pet
and .d64
) or BASIC source files (.txt
or .bas
).
Just use your favorite text editor and drop the file onto the virtual screen…
Norbert Landsteiner,
Vienna, 2019-07-02