4

I would like to store some binary data in a BASIC program on the Commodore 64 as DATA statements. To save space, I'd prefer to store as a string, rather than as a sequence of numbers.

Is it possible to store any character, from CHR$(0) through CHR$(255), in a DATA statement, or are certain characters impossible to represent this way? What is the complete list of characters that cannot be represented in a DATA statement (if any)?

I'm particularly wondering about CHR$(0), double quote ("), newline and carriage return. If these can be represented, how?

Laurence Gonsalves
  • 137,896
  • 35
  • 246
  • 299
  • It is possible, but you would need to write a HEX editor, and in your string change the 2-character values to their HEX value, such as a space is 20 in hex, and so on. That will create your string. I would have to find a HEX editor on my iPad to create such a string and then put a comma after each pair of numbers. With some testing I could get you your answer, or someone out there may be able to create your string DATA statement quicker. Then a READ A$ and a A=CHR$(VAL(A$)) might do it. I typed in the following: READY. PRINT CHR$(VAL("80")), and it printed a P. – George McGinn Mar 10 '17 at 20:45
  • @GeorgeMcGinn Are you suggesting to store the data as hex instead, using two characters for each byte instead of one? I know I can do that, but it doubles the amount of space needed. – Laurence Gonsalves Mar 14 '17 at 17:06
  • Not really. Each character is made up of two hex bits (instead of bytes). If you look at the hex value of a SPACE it is x20. Check my answer below, for when I even put in x169 it prints ©, a single character. My data statement below shows what happens when you use hex in a DATA statement. C64 BASIC only goes to 255 values. So the last two on my DATA statement are past 4000. Yet they still gave you one byte. Otherwise, if you do not store the data in hex (which converts it to the symbol it represents), you are better off storing a string of numbers, as there is no other way to do this. – George McGinn Mar 15 '17 at 07:34

3 Answers3

1

Short answer: No. And you said why: the double-quote character inside a string generates an error: there are no quote-escape characters. For every Other value, you might be able to poke stuff into your DATA statement strings and then just never touch those lines again with the C64 BASIC editor, but the double quotes would kill you.

The best and fastest solution I've yet to think up is poor mans hex. It works like this:

  1. Take each binary byte. Separate it into its two hex digits (/16 and keep the remainder for the second digit).
  2. For each hex digit, take the binary value and add 48.
  3. Now you have two characters in the set (0,1,2,3,4,5,6,7,8,9,:,;,<,=,>,?) that represent one byte.
  4. Those two characters go into your data statement string.

Reverse the process to read them and poke them out.

Bo Zimmerman
  • 132
  • 6
  • The zero byte is also a problem because it has a special meaning in a tokenized BASIC line, or rather at the end: it marks the end of the line. – BlackJack Oct 26 '17 at 20:15
0

There is a way to do this, you can POKE bytes directly into RAM. It's a bit of a long way around though, and you need to know where you're POKEing the bytes to. You could negate the need for lots of zeros in your DATA statement though, like this:

    0 FOR I=0 TO 7
    1 READ A(I)
    2 NEXT I
    3 PRINT A(0), A(4)
63998 PRINT "FIN"
63999 DATA ,,,,4,,7,8

We know that 2048 is the start of the BASIC area (unless you've moved the pointers), so at a guess, one could do this:

    0 DATA" "," "," "," "," "

Then POKE around 2050 or 2051 with a character that you'd recognise and then list it. If you see the character added in between the double quotes then you win. Of course, then you need to calculate each position between the quotes thereafter. When you're done, renumber your line number and carry on programming. I'm not sure how you'd POKE a double quote in between a double quote as there is no notion of escaping a string in Commodore BASIC as far as I know.

I'd personally just use numbers though.

Shaun Bebbers
  • 179
  • 2
  • 12
-1

I have stored the following data statement, each element as a string, in a C64 program. I chose CHR$(172) - CHR$(190), and two above CHR$(4000).

100 data "©","ª","«","¬"," ","®","¯","¶","¼","½","¾","™","ח","⦁"

And I ran the following code:

10 FOR X=1 TO 14
20 READ A$
30 PRINT ASC(A$)
40 NEXT X
100 data "©","ª","«","¬"," ","®","¯","¶","¼","½","¾","™","ח","⦁"

The results were mixed. I knew it would not recognize anything above 255. But the CHR$(173) printed as a 32 instead:

RUN
 169 
 170 
 171 
 172 
 32 
 174 
 175 
 182 
 188 
 189 
 190 

?SYNTAX  ERROR IN 100
READY.

I resisted the program, and my DATA statement now looks like this:

100 DATA "©","ª","«","¬"," ","®","¯","¶","¼","½","¾",""","",""

Using another BASIC dialect, one more modern and written in the past few years, this was my output of the CHR$ for 172 to 190:

The ASCII value of A is:  65 
The ASCII value of A should be 65, like it is on a PC.
If it is not 65, then a conversion table must be loaded
and the results converted to match the PC so code

CHR$ VALUES
—————————————————

CHR$(169)=©  CHR$(170)=ª  CHR$(171)=«  CHR$(172)=¬  CHR$(173)=­        
CHR$(174)=®  CHR$(175)=¯  CHR$(176)=°  CHR$(177)=±  CHR$(178)=²  
CHR$(179)=³  CHR$(180)=´  CHR$(181)=µ  CHR$(182)=¶  CHR$(183)=·  
CHR$(184)=¸  CHR$(185)=¹  CHR$(186)=º  CHR$(187)=»  CHR$(188)=¼  
CHR$(189)=½  CHR$(190)=¾  

For C64 BASIC, you either must use the string of numbers, or you will have to use the HEX values and store the actual characters as I have done in my original C64 DATA statement.

I don't know exactly how much space you think you are going to save, but it will be minimal at best, as C64 can't go past CHR$(255).

However, the other dialect I used, SmartBASIC, I went out past CHR$(20480).

I hope this helps.