6

I was just writing some junk Speccy Basic programs, more to see how they take up space on the +3's disk layout than to do any actual programming.

But I noticed that after editing a program line to make a very long REM statement, that most of what I added disappeared after I hit enter and in the listing instead of what I was typing I see some corrupted text instead REM QTQ NEXT PRINT at the end. Most of the program is REM statements so that one could be from memory stomping with part of the next line. Or not, since the rest is garbage.

REMQTQ

Now I know that in the binary format of Spectrum BASIC there is a two byte field to hold the length in bytes for each line after tokenization.

But maybe some other part of the system has a much shorter limit, or maybe it's just a bug?

Is there a known limit, either by design or by accident?

4
  • It might be helpful to add a screen copy of the line(s). It's ea to mangle lines up using the advanced editing features of newer ROMs.
    – Raffzahn
    Commented May 18, 2020 at 1:49
  • 1
    @Raffzahn: Done. And please enjoy the silliness (-: Commented May 18, 2020 at 2:03
  • I think there is on the standard ZX Spectrum...something to do with the editor...probably not. Trying to remember the ROM listing from a long time since :-)
    – TonyM
    Commented May 18, 2020 at 8:21
  • @TonyM Back in the day I had an original 48K but now I'm using +3 emulators, if that could be relevant. Commented May 18, 2020 at 13:23

3 Answers 3

10

The correct answer to your question is YES, and NO.

YES, if you are editing a long line in the editor of 128K BASIC, you are limited to the size of line buffer, which can hold only 20 screen rows. You can confirm this by reading the ZX ROM Disassembly which can be found here (note that you will need to be reading disassembly for ROM 0). Let me quote a comment from there, given under the heading "128 BASIC Mode Limitations":

There is a practical limitation on the size of lines that can be entered. It is limited to 20 indented rows, which is the size of the editing buffers. Typed lines greater than 20 rows get inserted into the BASIC program, but only the first 20 rows are shown on screen. Editing such a line causes it to be truncated to 20 rows. There is no warning when the 20 row limit is exceeded.

Just to illustrate this point, I quickly did the following steps:

  1. I created a line that contains 21 rows: enter image description here enter image description here
  2. I tried to press the return key, to see what gets saved (and frankly it looks fine at this stage!): enter image description here
  3. I tried to edit the line again, and then it becomes clear that things are not all rosy: enter image description here
  4. To make things properly interesting, I tried adding a space after the fullstop, just before the first word TEST at the end and pressed the return key to obtain enter image description here

So, 128K BASIC editor is basically inadequate.

NO is also a correct answer, because the actual storage format of ZX BASIC allows lines with lengths up to almost 64K, which in any case cannot be inputted directly from BASIC. I believe that 48K BASIC is free from the described limitation and the line editor of 48K BASIC can only run into trouble saving your line if you run out of available RAM, which in 48K configuration can happen as your line length exceeds something like 20K of characters.

3
  • 1
    Thanks for the confirmation! I should've included in my question that I grew up on an original 48K but now I'm using +3 emulators and I'm aware there are changes to type a character at a time rather than a token at a time, so probably others as well. I also didn't mention basic programs with machine code hidden after a REM which I've seen in disk images I've downloaded. I guess they're OK because they're not intended to be edited of course, and would've been created programatically. Commented May 18, 2020 at 13:28
  • As for your YES answer, is this new in 128K BASIC? I remember that 48 BASIC lets you type in as much as you want, but emits a BEEP just to discourage you from going bananas. Commented Sep 25, 2023 at 10:00
  • 1
    @Lorraine, yes, this was one of the newly added "features" of the 128K BASIC.
    – introspec
    Commented Sep 26, 2023 at 19:05
7

ZX Basic stores the length of each line as two-byte quantity, so the length of any line is limited only by the amount of available RAM.

In fact, it is a common thing to put binary executable code inside REM statement, where the whole basic looks like this:

10 RANDOMIZE USR addr:REM <binary code follows>

with addr pointing to the byte after REM token. Such trick allows one, for example, to put there a packed(!) title screen for a long-loading game, without ugly and lengthier process of loading unpacked data directly into the screen memory. Another option is to have there a custom loader.

From my practice, basic lines up to many tens of kilobytes are perfectly possible (but my experience is only with the binary code in REMs).

5
  • At least on the ZX81 the listing stops at certain bytes, or combinations of bytes. You might like to add some detail about this, too, if there is a similar behavior on the Spectrum. It might answer why the line seems to be truncated. Commented May 18, 2020 at 7:12
  • Wasn't that common on the ZX81 and not on the ZX Spectrum? The Spectrum had LOAD CODE and CLEAR addr. The ZX81 didn't and had to resort to the REM trick.
    – TonyM
    Commented May 18, 2020 at 8:17
  • LOAD "" CODE leads to the pauses: between end of basic and header, then longer pilot tone of the header, then pause to binary data. To remove all but necessary pauses, it is wise to have at least a packed picture in the REM block. And as well -- to have everything else packed too.
    – lvd
    Commented May 18, 2020 at 12:02
  • 1
    @thebusybee Well, printing such a bigger REM string with lots of "forbidden" chars in there often fails, but that does not bother much in the use case as above.
    – lvd
    Commented May 18, 2020 at 12:04
  • Indeed I posted an answer about self-modifying code on Speccy Basic around the same I posted this question, which did in fact make me wonder how the one affects the other. But if it's just a bug/limitation in the 128K editor ROM it all makes sense. I'm actually writing a set of Ghidra Disassembler modules right now and hope to have it working for code hidden after REMs. Commented May 18, 2020 at 13:29
0

It should be noted that in ZX-Spectrum BASIC there are no standards for line length, as in modern IDEs, there are also no native restrictions of 80 characters, as it was in modem times (however, home attempts to connect modems and extended screen modes [translation] were later made, but both Speccy BASIC editors was developed before that).

Long lines were used primarily to protect programs, because regular BASIC editors did not cope well with these lines. The first defenses of the early 80s were often based on BASIC tricks, but later almost every bootloader used the REM operator to place machine code in it. Polish hackers (such as Bill Gilbert, SS Capitan, etc.) in the 80-90s, after removing the original protections, also added simpler protections on their loaders that made editing the BASIC program more difficult and placed the machine code in a REM comment.

Essentially, long strings, such as well as color code control characters, lines with number 0 and modified ASCII values of numbers are only the first step in complicating the perception of programs and, in particular, to understand the place where the machine code loader runs. Most of these tricks were understandable to more experienced 8-bit programmers of the time, but for ordinary users it could be difficult.

So if you want an extra long lines, or place your machine code, you need to use POKES or directly write BASIC operator codes in assembler then modify saved code block to BASIC. Actually if you put youre code after the RANDOMIZE USR <start_of_code_bloack> operator you don't need additional : REM, just put your code after 5 bits digits form of <start_of_code_bloack>. Here is an example:

        ORG #8000   # Address to place your code block after compilation.
        DISP #5CCB  # Address of your BASIC program
                    # (not Multiface or TR-DOS, just clean BASIC 48/128).
        DB 0,1      # First line number
        DB #FF,#FF  # Lenght of BASIC line
                    # (actually you don't need a correct length)
        DB #D9      # RANDOMIZE
        DB #C0      # USR
        DB "0"      # "0" in ASCII (you don't need to put real address in ASCII)
        DB #0E,0,0  # 5 bytes of calculator form of number 
        DW START    # where last two bytes is real address of code block

        # If you wish you can put : REM here anyway using the corresponding
        # bytes, but this is not required if your machine code program will
        # not return to BASIC.

START   # any code block here to run

ENDCOD  DISPLAY "lenght: ",ENDCOD-#8000  # to calculate a real size of the
                                         # code block
        DB #80,#AA,#01,0  # But you need to save this one as
                          # the end of BASIC programm.

Then save your code block from #8000 with length of calculated length plus 5 bytes. But take a note you need to set up length without these 5 bytes add. Made them as BASIC (In TR-DOS you can edit file descriptor on the 0th track, on tape you could use other tools).

Based on a structure and ZX-Spectrum charecter set you can do any number of any size of lines with code block(s) inside.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .