11

When running TR-DOS commands from within BASIC, it's necessary to prefix the command with RANDOMIZE USR 15619: REM: first. I understand the former command, but not the latter.

For example, to load a program called "foo", this is done:

RANDOMIZE USR 15619: REM: LOAD "foo"

Instead of this:

RANDOMIZE USR 15619: LOAD "foo"

Why is this? Why is a REM statement necessary if it's essentially a no-op? Is it used to add padding to align the memory for some reason? Is it used to waste a few t-states for timing reasons?

forest
  • 2,029
  • 12
  • 36
  • Probably to prevent it from being executed as a BASIC statement, since the : separates statements in BASIC. It might also prevent the TR-DOS command from being tokenized but I don't know if that it's true. –  May 17 '19 at 04:24
  • @RossRidge I'm not sure why that would prevent it from being tokenized (that is done automatically before anything is executed), and the RANDOMIZE USR 15619 is what prevents it from being executed as BASIC, unless there's some odd side-effect that makes it insufficient on its own. – forest May 17 '19 at 05:04
  • 2
    The RANDOMIZE USR 15619 wouldn't prevent the second statement on the line from being executed. Both the RANDOMIZE and REM statements will get executed unless the TR-DOS code at address 15619 modifies the BASIC interpreter's internal state to skip over it, and apparently it doesn't do this. It appears ZX Spectrum BASIC doesn't actually tokenize its input, relying on the user into enter the tokens directly: https://retrocomputing.stackexchange.com/questions/5578/zx-spectrum-tokenisation –  May 17 '19 at 05:41
  • 1
    @RossRidge For 128 BASIC at least, it would tokenize each line when you finished it. – forest May 17 '19 at 05:44
  • 1
    So (non-Sinclair user here) it seems RANDOMIZE USR xyz allows an arbitrary call into non-BASIC code. But why overload RANDOMIZE? They just needed to hide the hook somewhere? Why not a new statement token? – dave May 17 '19 at 11:41
  • 1
    It's called a "hack". Obviously they didn't/couldn't/shouldn't modify the actual BASIC runtime to support these calls, rather they simply hacked them in using side effects of the interpreter state within the machine language subroutine that's being called. I assume USR 15619 is a function call, and used as the value for the RANDOMIZE seed, and is ideally harmless (since it probably just returns the current seed for RANDOMIZE as its value -- more inherent state and hackage). – Will Hartung May 17 '19 at 17:18
  • 3
    @another-dave - You could also use PRINT USR xyz if you wanted to see the return value, which was the contents of the BC register. However, if you weren't bothered about that value then you would generally use RANDOMIZE. – Greenonline May 18 '19 at 07:42
  • @another-dave If the BASIC interpreter is in ROM (and not designed for it) it is not that easy to change it (especially not in a memory constrained system). So, use the hooks you have. – Thorbjørn Ravn Andersen May 25 '19 at 10:32

1 Answers1

18

The disk handling routine at 15619 will look ahead in the currently-executing BASIC line to see what command needs to be performed. As Ross Ridge observes, it evidently doesn't modify the BASIC interpreter's internal state when doing this, and so when the RANDOMIZE USR 15619 call returns, the interpreter will continue at the next statement. If the REM wasn't there, the interpreter would proceed to handle the subsequent LOAD "foo" as a standard BASIC statement, and attempt to load from tape. (Sinclair BASIC treats everything after a REM until the end of the line as part of the comment - including anything following a colon - so the LOAD "foo" is considered part of the REM comment and skipped.)

Additionally, not all TR-DOS commands correspond to valid Sinclair BASIC syntax - CAT # is an example of a command which doesn't. Since the BASIC interpreter performs a syntax check at the point of entering the line, the REM is necessary to prevent the syntax checker from rejecting the line.

gasman
  • 1,341
  • 8
  • 8