Code Golfing in Commodore BASIC(imrannazar.com) |
Code Golfing in Commodore BASIC(imrannazar.com) |
"Deulignes" programs could target any platform, but must only take 2 lines of BASIC (most implementations allow only a limited line length, often 255 characters).
Some programs were really impressive; I remember one complete breakout implementation in MSX-BASIC for instance. People actually made whole (small) games in 2 lines of BASIC!
Here's an example page : https://archive.org/details/hebdogiciel-french-098/page/n15/...
Slow and inefficient for sure, but most of the magic is happening directly at the hardware level (sprites, memory-mapped IO, etc.), so there's a surprisingly large amount of stuff you can do with very acceptable performance.
1 SPRITEON:IFK=2THENR=-2:B=2*SGN(X-Z-4):RETURNELSEIFK=0THENCOLOR4,0,0:SCREEN2,1:DEFINTA-Z:J=186:X=140:Y=80:VPOKE14336,128:VPOKE14344,248:LINE(80,40)-(183,61),7,BF:LINE(78,7)-(184,J),2,B:LINE(Y,8)-(183,10),1,BF:R=2:B=2:Z=X:ONSPRITEGOSUB1ELSEIFL>5THENRUN
2 K=2:S=STICK(0):Z=Z+2*(S=3)*(Z<174)-2*(S=7)*(Z>80):PUTSPRITE1,(Z,161):Y=Y+R:X=X+B:PUTSPRITE0,(X,Y),11:P=POINT(X,Y):IFP=0THEN2ELSEIFP=7THENR=-R:A=(X\4)*4:LINE(A,Y)-(A+3,Y+1),0,B:GOTO2ELSEIFP=1THENR=2:GOTO2ELSEIFY>180THENL=L+1:Y=80:K=1:GOTO1ELSEB=-B:GOTO2
Direct link to the source code [4][1] http://www.hebdogiciel.free.fr/
[2] http://www.hebdogiciel.free.fr/2lignes_15.htm
[3] https://archive.org/details/hebdogiciel-french-104/page/n11/...
[4] http://www.hebdogiciel.free.fr/hd-roms/2lignes/2lignes_MSX_n...
https://archive.org/details/hebdogiciel-french
I'm pretty sure it's really difficult to convert MSX-BASIC to 6502 assembly though... But there are lots and lots of great C64 deulignes too :)
Et les dessins de Carali...
(If you're in Vienna, Austria, you can go to the Retro Gaming Museum and see the winning entries on a real computer, in person..)
https://www.c64-wiki.com/wiki/BASIC_keyword_abbreviation
That would shave off some more precious bytes!
10SAVE"4",8:PRINT4
0801 0F 08 link to next line at $080F
0803 0A 00 line number (16-bit binary): 10
0805 94 token SAVE
0806 22 34 22 2C 38 3A ascii «"4",8:»
080C 99 token PRINT
080D 34 ascii «4»
080E 00 -EOL-
080F 00 00 -EOP- (link = null)
As we may see, "SAVE" has been compressed already to a single byte (0x94), as is "PRINT" (0x99). Moreover, the line number is a 16-bit binary integer, meaning, the number of decimal digits in the listing has no effect on the in-memory format.BTW, abbreviations of BASIC keywords work, because of how upper-case/shifted letters are encoded in the PETSCII character set: they have their sign-bit set. (So normal letters are all smaller than 0x80, and shifted characters are >= 0x80. We may also note that codes > 0x80 are used exclusively for tokens in the stored BASIC text, discriminating them from any other text.) Now, the tokenizing routine uses a table, which also uses a set sign-bit: as a marker on the last character on each of the keywords, which are stored in a table. It will compute the difference of each letter in an input word to the entries in that table, and, if the difference is exactly 0x80 (the sign-bit), this means, (a) we arrived at the end of the word stored in the table, and (b) all the letters up until here did match (otherwise, we would have already exited the loop, in order to test the next keyword). We have a match! The routine then adds 0x80 to the table index of that keyword, and voila, there is your BASIC token.
Notably, if we're dealing with single-byte values, for a difference of 0x80 it doesn't matter, which of the two bytes, this is the difference of, holds the bigger value. It's effectively unsigned and agnostic of which was the larger byte. For our tokenizing routine, this means it will only "know" that one character has the sign-bit set, while the other has not (but is otherwise the same), but it will not "know" which of the two this is. Therefore, adding the sign-bit to an input character will fool the routine into assuming, it already went over the entire keyword and hit the sign-bit set in the last character of the table entry. And we achieve this by shifting the character in the input text. And, voila, there is your abbreviated BASIC keyword.
(We can also see how the length of the input keyword doesn't contribute to the storage format, as it will be compressed to a token, which is 0x80 + the table index of the keyword, anyways. We may also see why "iN" matches "input#" but not "input", because the longer version has to come first in the table, in order to match at all, and it will be also the first to be recognized by the erroneous match.)
There were some workarounds posted on of Robin's recent video.
It didn't seem like any of your links was to a playable version, so I had a Goog' and a paste and came up with [1]. Pretty impressive game for that amount of code, I'd say.
I've never written a line of code on an actual MSX machine (even though I was around in the 80s), it's kind of amazing the amount of emulation Magic Power we casually throw around, these days. Massive thanks to all the emulation authors and (of course) retro computer archivists.
Edit: typo, more compliments.
Also there is a line limit in C64 BASIC that would overflow if certain shorthand would be expanded and for beginners to see their fully written keywords being transformed to shorthand after loading would be even more confusing.
10 for i = 1 to 10
20 : (arbitrary number of spaces) print "hello"
30 next
The short hand issue is real, too:
1?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?:?
expands into six lines of "1 print:print:....:print" that you can't simply edit because the limit is 80 characters (two lines)
And the tokenization didn't prevent you from style differences anyway - as the article points out it e.g. keeps spaces etc. It only tokenized a few things, like keywords and line numbers.
(EDIT: in the late 90's I worked on a project written in Word BASIC.... It was also tokenized and that was used as an opportunity to translate the keywords in the localised versions of Word. But someone had managed to write a bunch of code in the Danish version and somehow exported it as text and imported it into the Norwegian version - the languages are similar enough that it was really hard to tell (no syntax highlighting, and they'd edited a bunch before realising and I had the fun job of untangling it... Yay...)
This had the side-effect that you could still display and (presumably with a bit more mental effort, read) the program listing fine, but re-entering a line as shown in that listing would fail because the computer depended on the spaces to do the parsing, even if they were redundant after the tokenisation happened.
I was always surprised that it did all that, but wasn't any faster than Commodore BASIC.