Odd LIST bug/behaviour
Posted: Tue Sep 17, 2019 5:43 am
So I've recently begun doing some work on a custom implementation for displaying listings of ZX81 programs (a macOS Quick Look plugin, for the curious), and wanted to figure out what the behaviour would be for REM statements that contained some of the control characters (118/newline and 126/number flag). The results I discovered were rather interesting...
(Note: the listings were produced by issuing a 'LIST'; simply typing newline can produce an endless loop)
Given the following program:
If a POKE 16517,118 is issued, the following occurs: This is where the listing code thinks the end of line has been reached (the early 118), and treats the rest of the line as though it's the next line to print (up to the end of the original line)
If instead, a POKE 16517,126 is issued, the following happens: Code 126 is the flag for 'a number', which makes it skip the next 5 bytes (in this case, the rest of the REM, just before the terminating 118).
Now if we do a POKE 16520,126: Since skipping the next 5 bytes goes past the original line, the next line becomes part of the first in the listing. Line 20 is still editable however.
Things really get wacky if we do a POKE 16535,118: In this case, the listing goes past the program, and starts reading into the display file.
Now I don't find it surprising that the LIST code didn't take into account that a REM statement would contain control characters that wouldn't be part of a normal BASIC line, as that would have taken up precious space in the ROM to try to avoid this behaviour. But I was a bit surprised that it doesn't use the length of the line to properly detect when to stop evaluating the line, given that the length of each line is encoded within the BASIC program - making sure not to go past the end of the line shouldn't have been too many more bytes of code, and if the length is not used otherwise then it seems like a waste of memory (though I think the length is used to determine where to put the editing cursor, which would explain why line 20 is still editable).
I guess this was likely considered a fringe case, which is also easily avoided by using a double 118 sequence to hide the entire REM contents.
(Note: the listings were produced by issuing a 'LIST'; simply typing newline can produce an endless loop)
Given the following program:
If a POKE 16517,118 is issued, the following occurs: This is where the listing code thinks the end of line has been reached (the early 118), and treats the rest of the line as though it's the next line to print (up to the end of the original line)
If instead, a POKE 16517,126 is issued, the following happens: Code 126 is the flag for 'a number', which makes it skip the next 5 bytes (in this case, the rest of the REM, just before the terminating 118).
Now if we do a POKE 16520,126: Since skipping the next 5 bytes goes past the original line, the next line becomes part of the first in the listing. Line 20 is still editable however.
Things really get wacky if we do a POKE 16535,118: In this case, the listing goes past the program, and starts reading into the display file.
Now I don't find it surprising that the LIST code didn't take into account that a REM statement would contain control characters that wouldn't be part of a normal BASIC line, as that would have taken up precious space in the ROM to try to avoid this behaviour. But I was a bit surprised that it doesn't use the length of the line to properly detect when to stop evaluating the line, given that the length of each line is encoded within the BASIC program - making sure not to go past the end of the line shouldn't have been too many more bytes of code, and if the length is not used otherwise then it seems like a waste of memory (though I think the length is used to determine where to put the editing cursor, which would explain why line 20 is still editable).
I guess this was likely considered a fringe case, which is also easily avoided by using a double 118 sequence to hide the entire REM contents.