Very basic BASIC: formatting numbers and updating information on screen

While writing a simple C64 BASIC “game”, I came across some little issues dealing with formatting numbers and updating information on the screen. As info must be kept updated  with no screen flickering and with no potential garbage collection issues, some simple special techniques were needed.

Commodore 64 BASIC V2 doesn’t provide any means of formatting numbers. For instance, there is no function that allows you to force an integer number to be four digits (using leading zeros for numbers with less than four digits, and omitting surplus digits for numbers with more than four digits).

So, C64 built-in BASIC prints numbers with no special formatting. But, a space is always put at the beginning of any number. And when converting an integer or real number to string, that space is kept.

Suppose we must print score (or time) using a fixed length of four digits.

If we are happy with leading zeroes, we can accept a thing such as:

 

0005

 

Then, we could code like this:

 

10 input "value (integer)";a
20 a$=right$(str$(a),len(str$(a))-1)
25 nz=5-len(str$(a)):ifnz<=0thenz$="":goto35
30 fort=1tonz:z$=z$+"0":next
35 a$=z$+a$
40 print "formatted number: ";right$(a$,4)

 

Although functional, the above code is quite inefficient. Of course, we could make some improvements (for instance, evaluating the STR$ function only once, using a variable), but  the point is, the above code is not quite straightforward.

But, we can use a trick. If we want the score to be four digits at max, we can just set initial score to 10000 instead of zero. If we only print four digits from the right, the initial score will be just zero. And as long as we add points, everything will work just nicely. For instance, we will print the value 100, but in memory we will have the value 10100. If the number printed on screen exceeds 9999, it will wrap around to zero on the screen, but in memory it will be 20000. Here is how we may code it:

 

10 input "value (integer)";a
20 a=a+10000
30 a$=right$(str$(a),4)
40 print "formatted number:";a$

 

 

The above code works fine, but we still have a problem. The use of the function STR$ may cause garbage collection issues. For instance, if we are printing the value of a timer, it will be updated quite often, and that increases the risk of slow garbage collection troubles. Even if no slow garbage collection happens, many garbage strings will be created on memory.

As far as I can see, we should use another approach. Suppose we are not interested on leading zeros. We just want the number to be printed starting from the same position. Taking advantage of Commodore BASIC control characters seems a better solution in this case.

Let’s imagine our score keeps growing. Then, the following code will print score always starting from the same character position on the screen:

 

20 printchr$(147)" score:";sc
25 sc=sc+500:if sc>10000 then end
30 printchr$(19)chr$(29)chr$(29)chr$(29)chr$(29)chr$(29)chr$(29)chr$(29);sc
40 fort=1to200:next
50 goto 25

 

Things work fine because the number is always increasing. So, new digits are always guaranteed to overwrite old numbers. As a result, numbers being printed are always correct and there is no visible flickering as well.

Things will not work, however, if we are printing a timer going towards zero:

 

10 printchr$(147):sc=100
20 printchr$(19)" time";sc
25 sc=sc-1:if sc<0 then end
30 printchr$(19)chr$(29)chr$(29)chr$(29)chr$(29)chr$(29)chr$(29);sc
40 fort=1to100:next
50 goto 25

 

Some old digits are not updated, so printed numbers at the end are bigger than the actual values.  To fix the problem, we can use spaces:

 

 

Download

 

Now, printed numbers are correct, but we see some flickering. This is due to the fact that numbers are deleted with spaces, then printed again.

But, we know from my BASIC chessboard scrollers and other routines presented here, that we can use the instruction WAIT to update information while the rasterbeam is out of the viewable area, avoiding flickers. The following code will do:

 

Download

 

As the program is short, a little pause between WAIT and PRINT statements is required. Otherwise, flickering will happen. However, bigger BASIC programs will run slower, so that pause may be not needed on them.

Missing the leading zeros? It may be the case, as they are used on most games for scores and time. If we still want to avoid using string functions, the fix is not straight, but it can be done. We just have to change the starting character position according to the size of the number. And, as we don’t want any potential slow garbage collection issue, we will create a little array for control characters, then update an index, thus avoiding string variables assignments.

 

 

Download

 

The above code is quite complex. Instead, I like the simplicity of the solution truncating a number which is bigger than needed (the second program presented on this article). But, I don’t like the fact that it creates garbage strings. Still, we can play around with the string pointer and avoid producing garbage strings. The following program  will actually format a big amount of numbers without producing garbage strings:

 

10 fork=1to9999
20 a=k+10000
25 p1=peek(51):p2=peek(52)
30 a$=right$(str$(a),4)
40 print "formatted number:";a$
45 poke51,p1:poke52,p2
50 next

 

You can directly paste the program in VICE. After you run the program, you will see that the string pointer will have the original value. So, there is no memory waste and there are no potentially slow garbage collection issues either. Of course, the content of variable A$ will NOT be preserved. As long as other strings will be created, its content will get corrupted. But, since we are regarding it as a temporary string (we just need to print it once), it just doesn’t matter.

So, the following version offers simple code with no garbage collection concerns:

 

10 input "value (integer)";a
20 a=a+10000
25 p1=peek(51):p2=peek(52)
30 a$=right$(str$(a),4)
35 poke51,p1:poke52,p2
40 print "formatted number:";a$

 

Previous Entries Taking the square of a 16 bit number, a simple technique using 6502 assembly Next Entries Plotting a 3D function with Simons' BASIC and BASIC 2.0 (C64)

2 thoughts on “Very basic BASIC: formatting numbers and updating information on screen

  1. Crispin on said:

    Great article.
    Now,
    It is not strictly related to, but this “Draw a clock” example from Rosetta Code (link below) matches title:
    “Very basic BASIC: formatting numbers and updating information on screen”.

    Rosetta Code has different goal (Chrestomathy), but this code example is quite interesting.
    Could you “fix” it for real use (e.g. no flickering, faster/simpler code etc)?
    Or just use a different (better) approach?
    It is “Draw a clock” example, but it could be used e.g. for timer.
    http://rosettacode.org/wiki/Draw_a_clock#Commodore_BASIC
    Other CBM BASIC examples:
    http://rosettacode.org/wiki/Category:Commodore_BASIC

    • retro64 on said:

      Hello Crispin,

      thank you! I have had a look at the clock program and I think it can be improved. I’ll have a try at it. Thanks for the interesting links!

Leave a Reply

*