Commodore 64: breaking the 38K RAM barrier from BASIC. Creating an additional 4K BASIC variables storage area.

Although the Commodore 64 comes with 64K RAM of memory, not all of this amount of memory is available right after the machine has been turned on. 38911 bytes are “only” available to BASIC – that’s just what the start up message is telling you.

This was indeed a big amount of memory for the time, as earlier Commodore PET/CBM machines usually offered roughly 32K RAM memory for BASIC. CBM 2 machines offered much more memory available to BASIC instead, but those computers enjoyed a quite limited success.

Still, you may wonder why the Commodore 64 out of 64K of RAM memory only offers 38K RAM for BASIC programming. But, you may also wonder whether or not it is possible to go past this limit with BASIC.

The Commodore 64 CPU is only capable of addressing 65536 bytes (locations from 0 to 65535 decimal, $0000 to $FFFF hex). That’s because the address bus is only 16 bit wide. But, the Commodore 64 has 64K RAM memory plus 20K ROM. It also has a special 4K I/O area where Interface Adapters (VIC-II, SID, CIAs) are mapped. That sums up to 88K. How is it possible for the Commodore 64 to address all of that memory? As we all know, the 6510 CPU has a special I/O port that allows to select the memory configuration of the Commodore 64. This way, BASIC and/or KERNAL ROMs can be swapped out and replaced with RAM for instance, freeing up 16K of RAM.

The point is, while using BASIC, you are usually told that no more than 38911 bytes are available. Still, there is an additional 4K RAM area starting from $C000 (49152 decimal), but this is commonly thought as an off limits area for BASIC. This is mostly used to add utilities and/or to poke data.

Anyway, if you want to use this 4K RAM area for BASIC, it is possible. You just have to set BASIC pointers properly. This area can be used to store either variables or a short program.

Let’s have a quick review of Commodore 64 BASIC pointers:

  • Start of BASIC (locations 43 – 44 decimal): this is the pointer to the location where BASIC programs start from.
  • Start of variables (locations 45 – 46 decimal): this is where variables start from.
  • Start of arrays (locations 47 – 48 decimal): this is where numeric arrays and string arrays descriptors start from.
  • End of arrays (location 49 – 50 decimal).
  • String pointer (locations 51 – 52 decimal): that’s the location strings will be stored from – it grows backwards as soon as strings are being created.
  • End of BASIC (locations 55-56): that’s the last location used by BASIC, defaults to $A000 or 40960 decimal.

These pointers can be dramatically useful. For instance, we can set up things so that variables can be either stored in the standard BASIC memory area or in the 4K RAM area starting from 49152 decimal. This approach gives us different advantages. First of all, we can have an additional 4K memory space for BASIC variables. Furthermore, we can take advantage of two different sets of variables. In a way, we can have “local” variables. And, those local variables can have the same name as the “global” variables if we want to.

The following program shows off this simple technique.

 

DOWNLOAD: using $C000 area for additional BASIC variables

 

The program creates two different arrays having the same name – A$. One array is on the conventional variable storage area, the other one is on the 4K area starting from $C000.

Subroutine from line 130 sets BASIC pointers so that BASIC will look for variables on the $C000 area. Subroutine from line 60 sets BASIC pointers so that BASIC will look for variables in the conventional variable storage area. So, we can do things like in the following screenshot:

 

 

As a further example, we can create some variables in both areas and print them, from direct mode.

 

 

As you can see, a different set of variables has been created on each variable storage area. As a proof, L$ holds no string if you try to print it when the variables area on which it was created is not active. After the command gosub 60 is issued instead, if you try to print L$ the word “C64” will be shown again.

The code is quite simple and subroutines do not use variables. This way, you are free to use any variable you wish. That’s why routines are unrolled. Of course, these subroutines can be rewritten in assembly language. That way, they’ll be fast.

Now, what about the RAM under the ROM? There are 16K RAM potentially available (the remaining 4K are used for mapping the custom chips). This is just the RAM under the BASIC ROM and the KERNAL ROM. This memory cannot be read by BASIC – that would require swapping out the BASIC ROM while using the BASIC interpreter – clearly impossible. But, BASIC can write to this memory. And despite the fact that the 6510 CPU cannot access that memory for reading with the BASIC interpreter active, the VIC-II chip can read it anyway. That means, this amount of memory can be used by BASIC for graphics. The RAM under the KERNAL is all available for the VIC-II to show pictures. The RAM under the BASIC ROM is not all available – 4K are used as the shadow of the characters ROM – but, the other 4K can be used for graphics as well. So, we have a total of 12K that BASIC can easily use to show graphics, although it cannot read it. Possible uses are, for example, loading a picture from disk and showing it, or loading one or more charsets and use them (but without the ability of modifying them with BASIC).

So, adding 4K for BASIC variables like explained earlier and using the RAM under the ROM to show graphics loaded from media storage adds to BASIC another custom use 16K RAM to the 38911 BASIC bytes free.

4 Replies to “Commodore 64: breaking the 38K RAM barrier from BASIC. Creating an additional 4K BASIC variables storage area.”

  1. C’e’ modo di riempire da 49152 a 49152+NumCaratteriRidefiniti*8 con i caratteri ridefiniti e puntare a questa locazione?

    1. Ciao Stefano, si è possibile e uno dei metodi utilizzabili è questo. Bisogna selezionare il banco 3 per il VIC-II e spostare la memoria dei caratteri e la memoria dello schermo nei 4K RAM a partire da $C000 (49152 decimale). Bisogna inoltre dire al KERNAL dove è la nuova memoria dello schermo, modificando la locazione 648 decimale.

      Ecco un esempio interamente in BASIC che copia i caratteri maiuscole/grafica dalla ROM alla RAM. Il programma è lento e andrebbe convertito in linguaggio macchina, ma riesce comunque a dimostrare il metodo. Per riportare il computer alle condizioni normali (cioè per visualizzare di nuovo i caratteri dalla ROM e riavere l’usuale memoria dello schermo da 1024 decimale), digitare GOTO 100, non usare RUN/STOP+RESTORE.

      Nell’esempio, il font dei caratteri (di soli 2K) parte da 49152. La memoria dello schermo parte da 52224.

      Ciao e grazie per la visita.

  2. Ciao! Riesumo questo “vecchio” post perché, oltre ad averlo scoperto ora, ho una domanda.
    La routine è molto interessante ed anche tutta la spiegazione acclusa. Credevo fosse ottima per un adventure che sto scrivendo ma richiamando la prima volta le variabili, siano esse numeriche che stringa, caricate da $C000 in avanti, dopo il primo GOSUB 130 le stampa regolarmente ma dopo essere tornati nell’area normale dove i puntatori cercano le variabili con GOSUB 60, al successivo GOSUB 130 se provo a stampare una variabile qualsisi, il C64 non fa nulla, il cursore sparisce, fermare l’esecuzione non è possibile e l’unica cosa che rimane da fare è utilizzare RUN/STOP + RESTORE.
    Come mai? Qualsiasi aiuto è gradito! THX!!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Insert math as
Block
Inline
Additional settings
Formula color
Text color
#333333
Type math using LaTeX
Preview
\({}\)
Nothing to preview
Insert