In a recent article here, I explored the Logiker Vintage Computing Christmas Challenge 2021. The goal was to create a BASIC program that displayed a test Christmas tree:
The discussion continued in a follow-up article I posted a bit later. Check out those two postings, as well as the comments, for the full discussion. In the end, I used a suggested approach of encoding the length of each line (the number of characters to print as a centered string) in ASCII, so an ‘A’ represented one, ‘B’ would be two, and so on. To convert ASCII to the values needed, the program would do a subtract 64:
On May 30, Sebastian T posted a new comment to that article with a suggestion that would reduce this program’s 64-byte size to 61 by getting rid of the “-64” bytes:
It would be nice to get rid of the “-64” part after the ASC() function, as this would save another 3 bytes, reducing the program size from 64 to 61 bytes.
All you have to do is to replace the characters inside the string with lower ASCII values just as needed, like &H01, &H03, &H05 and so on.– Sebastian T. (5/30/2022)
Indeed, if instead of having “A”, “B”, “C”, etc. you could put in the raw bytes of 0, 1 and 2, that subtraction would not be needed. It is possible to alter BASIC programs to do this, but they create programs that are impossible for a user to type in from a listing. (I experimented with such a trick when I was working on a BASIC Pac-Man program.)
Or so I thought. Sebastian continued with a very clever approach/solution to typing in an un-typeable program:
You cannot use the keyboard to edit the string in this way, but I did write some self-modifying code that replaced the characters directly in program memory. After this, you can erase the extra code and you are left with a fully functional version that is 61 bytes long.– Sebastian T. (5/30/2022)
What an interesting approach! Provide a fully typeable BASIC program which contains self-modifying code. Run the routine that self-modifies, then delete the self-modifying routine and save out the final program. Here is Sabastian’s example:
0 FORC=1TO14:W=ASC(MID$(“ACEGCGKOEKQWCC”,C)):PRINTTAB(16-W/2)STRING$(W,42):NEXT 10 ‘ 20 ‘FIND FIRST STRING IN THE BASIC PROGRAM MEMORY AND HACK IT! 30 S=PEEK(25)256+PEEK(26) ‘START OF BASIC CODE IN MEMORY 40 E=PEEK(27)256+PEEK(28) ‘END OF BASIC CODE IN MEMORY 50 FOR A=S TO E 60 IF F THEN READ V : IF V<0 THEN END ELSE POKE A,V 70 IF PEEK(A)=34 THEN F=-1 ‘TOGGLE FLAG UPON REACHING THE FIRST QUOTATION MARK 80 NEXT A 90 DATA 1,3,5,7,3,7,11,15,5,11,17,23,3,3,-1
Run it once, then do a DEL 10-90. Run it again to verify it still fulfills the original task, and it does!
1) All tests done in XROAR 1.0.1 emulating a COCO 1 with 32k RAM.
2) I removed the “-64” before modifying the string, but you can also do it afterwards, even though the EDIT function will behave a bit funny while skipping over the non-printable characters in the string constant, but it works. I tested both ways.
3) If one of the characters had been 0 or 34 (quotation mark) this would have not worked. But this was not the case, so I got away with this. I’m not sure if there are other forbidden characters to consider, if somebody knows about this please comment.
4) In order to make sure this was still a valid program, I CSAVE’d it in a virtual cassette file, did a cold restart and reloaded the saved program. It works!
5) If you LIST the program, you’ll see a supposedly empty string inside the MID$() function, however it is not empty! I wrote a small memory monitor to verify this.
6) RENUM function won’t work now, though.
In summary, this trickery allows reduction of the final program size from 64 to 61 bytes.
Best regards!– Sebastian T. (5/30/2022)
What an interesting approach. One can now type in a longer BASIC program, run it, DELete some lines, then end up with a smaller final program.
For BASIC programmers who used modified code for things like this, I suppose they were doing something like this. There would be a master program that could be edited and worked on, with routines at the end to modify strings and such, and then after the modification was ran, a second copy would be saved that could not be easily edited later.
And now we have a two-step way of creating a 61 byte version of that program.
Nicely done, Sebastian!
Until next challenge…