Jump to content
IGNORED

Console BASIC CALL KEY and the 'X' return value for Key Unit 1


pixelpedant

Recommended Posts

Likely some of you folks are already well familiar with this issue.  But it appears to me that there's a bug which affects CALL KEY in 99/4A console BASIC.  Previously, I just casually worked around this, as probably others have in the past.  But I recently decided that in certain optimisation contexts where Key Unit 1 is greatly preferable to Key Unit 0, it was too annoying not to investigate (and too odd not to understand). 

 

Specifically, when CALL KEY returns a value for the key 'X' on the 99/4A keyboard via Key Unit 1 as called in the following form...

 

10 CALL KEY(1,K,S)

 

K will be set to a value which displays as zero if PRINTed.  For example, like this:

 

10 CALL KEY(1,K,S)
50 PRINT "K="&STR$(K)
60 IF S=0 THEN 10

 

But it is not in fact a normal zero. 

 

So while STR$(K)="0" will be true, K=0 will not be. 

 

As well, many normal operations on this "zero" K value will crash console BASIC.  For example, this will crash TI BASIC, if X is pressed:

 

10 CALL KEY(1,K,S)
50 PRINT "K="&STR$(K)
60 IF S=0 THEN 10
70 K=K/2

 

Now, looking at the Symbol Table, what I'm seeing for K in this circumstance appears to be

 

>40 >00 >00 >00 >00 >00 >00 >00

 

Which it should not be, as I understand it.  A zero should be

 

>00 [seven irrelevant bytes]

 

Or at least, that is how the interpreter handles its Radix 100 representation for all other purposes. 

 

And interestingly, 99/4 Console BASIC does not seem to have this problem.  Running this same CALL KEY on the 99/4 returns the expected, usable value.  And Classic99 shows the value in the Symbol Table set to 

 

>00 >00 >00 >00 >00 >00 >00 >00

 

As a consequence, all normal arithmetic operations on the value are possible. 

 

This problem is also not manifest in Extended BASIC, incidentally. 

 

It seems to be specific to Console BASIC on the 4A. 

 

I've known this was an issue for a while.  But I'd never dug into what was actually going on in memory.  Until now. 

 

 

  • Like 5
  • Thanks 1
Link to comment
Share on other sites

All this toil and trouble, incidentally, ultimately stems from the fact that the program I'm working on extensively abuses the fact that TI BASIC will tolerate fractional numbers in pretty much every context where only integer values would make any sense. 

 

This is useful in various contexts, but one of those is where non-sequential numbers need to be "converted" to a sequential series by the fastest available means for the purpose of selecting array values or doing an ON GOTO.  And the fastest available means is always going to be simple arithmetic. 

 

For example, for possible X values OF 0, 2, 3, 5, the following will succeed in handling them as 1,2,3,4 for the purpose of an ON GOTO:

 

10 ON X/1.5+1 GOTO 20,30,40,50

20 PRINT "YOU PICKED 0"

25 END

30 PRINT "YOU PICKED 2"

35 END

40 PRINT "YOU PICKED 3"

45 END

50 PRINT "YOU PICKED 5"

55 END

 

Two of the potential values of X/1.5+1 fed to the ON GOTO end up being fractional.  But of course that doesn't matter. It only matters that the nearest integers are 1,2,3, and 4, respectively. 

 

Anyway, that's how I ran into the division of this aberrant zero crashing BASIC.

 

Selecting array values and handling control flow with approximate values is tortured and mad.  But if TI BASIC weren't as tortured and mad as it is, I probably wouldn't be so enamoured of it.

  • Like 3
Link to comment
Share on other sites

3 hours ago, pixelpedant said:

So while STR$(K)="0" will be true, K=0 will not be. 

I read about this in one of our user group newsletters way way back, though without the benefit of symbol table analysis you provided.  As a result, I started comparing the K return with POS(KEYS$,CHR$(K),1), where KEYS$ is a string of expected character values, which can include CHR$(0).  Has never let me down.

 

1 hour ago, pixelpedant said:

Two of the potential values of X/1.5+1 fed to the ON GOTO end up being fractional.  But of course that doesn't matter. It only matters that the nearest integers are 1,2,3, and 4, respectively. 

This is another wonderful facility of TI BASIC.

  • Like 1
Link to comment
Share on other sites

1 minute ago, senior_falcon said:

This is an odd one. Interestingly, if you add 1 to K then arithmetic operations go as expected.



10 CALL KEY(1,K,S)
15 PRINT K+1
20 IF K+1=1 THEN 100
30 GOTO 10
100 PRINT "X WAS PRESSED"
110 GOTO 10

 

 

Indeed! That was my solution, in the end. 

 

And this would appear to make some sense, I suppose. 

 

Since in the case, our aberrant 0 is.

 

>40 >00 >00 >00 >00 >00 >00 >00

 

And adding one to it just makes it.

 

>40 >01 >00 >00 >00 >00 >00 >00

 

i.e., makes it a value for which >40 happens to be the correct exponent value, instead of an errant one. 

 

But indeed, division operations applied immediately to K crash BASIC, while multiplication operations result in invalid values.  So those need to (initially) be avoided. 

 

Under nearly all circumstances, this is an only minor inconvenience, though. 

  • Like 2
Link to comment
Share on other sites

2 hours ago, senior_falcon said:

This is an odd one. Interestingly, if you add 1 to K then arithmetic operations go as expected.



10 CALL KEY(1,K,S)
15 PRINT K+1
20 IF K+1=1 THEN 100
30 GOTO 10
100 PRINT "X WAS PRESSED"
110 GOTO 10

 

This is the workaround I used to use. :)

  • Like 1
Link to comment
Share on other sites

1 hour ago, apersson850 said:

What about ABS(K)? Does it work correctly? Is there even ABS in TI BASIC? Haven't used that since... eh... a long time.

 

ABS(K) does not change the floating point value (>4000 0000 0000 0000) returned for 'X' in CALL KEY (1,K,S).

 

...lee

  • Like 1
Link to comment
Share on other sites

Not that this isn't already known but I believe one of the addendums that came with the 99/4A (at least the beige ones) mentioned this.  The workaround was the one you found (IF K+1=1)

 

http://ftp.whtech.com/datasheets and manuals/Official TI addenda and data sheets/994a Users Reference Guide Addendum.pdf

 

The same issue applies to key unit 2 and the M key.

  • Like 4
Link to comment
Share on other sites

5 hours ago, apersson850 said:

OK, I get what you mean, even if you wrote 'X' when you meant 'K'. It was just an idea. SQR doesn't do anything either? Perhaps a little more likely it actually does. What if you add zero, to compute K+0?

 

Not always the case, but I said what I meant: K holds the value returned for tapping ‘X’.

 

SQR returns a non-zero, nonsense value and computing K+0 returns the original, erroneous value.

 

The reason that computing K+1 works is that the exponents for the erroneous zero and 1 are the same, so there is no change in exponent before addition of the mantissas. Had the erroneous zero had a higher exponent, the answer would have been weird—still 1, but not properly represented, i.e., it would not have been normalized to having a non-zero first radix-100 digit before the radix point. The following is an example showing the hex representations:

>4200 >0000 >0000 >0000     <---improper 0
>4001 >0000 >0000 >0000     <---proper 1
+++++++++++++++++++++++     <---floating point addition
>4200 >0001 >0000 >0000     <---improper 1

On the other hand, had the improper zero an exponent less than 0 (excess-64 value lower than >40), adding 1 would always result in a proper 1.

 

...lee

Edited by Lee Stewart
correction
  • Like 4
Link to comment
Share on other sites

From where does BASIC get that erroneous zero?  Is it stored in a table somewhere or is it computed?  I have literally always wondered about this.

 

I just ran a quick test, K*1 returns 6400.  Neat!  And, useless in the context of scanning keys, but K*0 does equal 0.

Link to comment
Share on other sites

2 hours ago, OLD CS1 said:

From where does BASIC get that erroneous zero?  Is it stored in a table somewhere or is it computed?  I have literally always wondered about this.

The GPL code for CALL KEY takes a shortcut converting the scanned key byte to a decimal number:

3724: DST @>834A, >4001   Initialize the number representation.
...
373D: ST  @>834B, @>8375  Copy the scanned key into the second byte.

It normalizes values larger than 100 in the code between, but not the 0-value.

  • Like 1
Link to comment
Share on other sites

1 hour ago, Eric Lafortune said:

The GPL code for CALL KEY takes a shortcut converting the scanned key byte to a decimal number:


3724: DST @>834A, >4001   Initialize the number representation.
...
373D: ST  @>834B, @>8375  Copy the scanned key into the second byte.

It normalizes values larger than 100 in the code between, but not the 0-value.

Ooooo naughty!

Link to comment
Share on other sites

  • 2 weeks later...
On 6/21/2022 at 7:41 AM, Casey said:

Not that this isn't already known but I believe one of the addendums that came with the 99/4A (at least the beige ones) mentioned this.  The workaround was the one you found (IF K+1=1)

 

http://ftp.whtech.com/datasheets and manuals/Official TI addenda and data sheets/994a Users Reference Guide Addendum.pdf

 

The same issue applies to key unit 2 and the M key.

I remember seeing that extra page in my manual material when I started using the computer and scratching my head, but kind of shrugging because at around that same time, TI exited the home computer business so it was like, “Our oops, but bye, we’re done.”

 

Of course, I missed the Alpha Lock warning until after I had already returned joysticks I thought were defective to the store…

  • Like 2
  • Haha 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...