10

It is widely known that, while the Commodore 64 did indeed provide 64K of RAM for machine code programs, only 38K was usable from BASIC; this was because bank switching was needed to get at the rest, but if a BASIC program switched out the interpreter ROM, or anything providing essential support thereto, it would of course promptly crash.

But the Commodore Plus/4 apparently provided 60K to BASIC programs. By the above reasoning, this should be impossible.

How did it work?

1 Answer 1

11

[...] Commodore 64 did indeed provide 64K of RAM [...] only 38K was usable from BASIC; [...] bank switching was needed to get at the rest,

And that's exactly the way the TED computers did use.

but if a BASIC program switched out the [...] ROM, [...] it would of course promptly crash.

Well, BASIC 3.5 was aware of that and did provide functions for various RAM und ROM access (*1).

But the Commodore Plus/4 apparently provided 60K to BASIC programs. By the above reasoning, this should be impossible.

How did it work?

Well, what about because it did exactly do so and switched out the ROMs?

It's a feature of BASIC 3.5 and all TED computers using it (C16, 116, Plus/4). For read access (*2) to all RAM (*3) the ROMs need to be switched out, and back again afterwards. To do so an access stub was established in RAM (see below), itself unaffected by the switch. When called it switched out the ROM, accessed RAM, switched the ROMs in again and returned.

After all, that same scheme was intended for the C64 as well, but by Tramiel's decision it was produced the way the prototypes where hacked together, not waiting for BASIC 3.5 to finish.

Another advantage of the TED line was to have the I/O area moved to the top 4 KiB at $FC00, thus resulting in a continous RAM Block of 60 KiB when ROM was switched off (*4).


Detailed workings of the access stubs:

BASIC 3.5 was build in a very versatil and comfortable fashion. To do so the whole first two KiB, not just page zero, was used for variables and pointers (*5). Among others, page 4 contained separate stubs for all BASIC related pointers to fetch from. For example a stub called INDTXT at $04A5 to fetch BASIC program text.

INDTXT:
    SEI               * no interrupt
    STA   RAM_ON      * disable ROM ($FF3F)
    LDA   (TXTPTR),Y  * fetch byte  (<patch>)
    STA   ROM_ON      * enable ROM  ($FF3E)
    CLI               * free IRQ
    RTS               * return the byte

All the stubs are copied from the same ROM code and patched at <patch> with the address of the corresponding pointer.

Similar the CHRGET/CHRGOT combo, central for Commodore BASIC and others get moved there - all including the ROM on/off switching.


*1 - In addition to the Kernal banking services like the 'Long Fetch' routine located at $FC7F (via Kernal entry point $FCF7) to access any of the 4 32 KiB ROM Banks.

*2 - No need to go thru such a stub for writing, as writes always end up in RAM.

*3 - Strictly this would apply only to addresses above $8000. No switching needed below that, as there is always RAM. Thus a simple (BIT) test for negative of the high byte (even free when loading(moving that pointer) can detect the need for using the stub. Something that always fails on a 16 KiB C16. Except, it hasn't been done as the savings are rather marginal - 8 clocks per fetch. There may be other areas to improve instead.

*4 - The C64 had a it/s 4 KiB I/O area at $D000, somewhat in the middle, cutting off the to 8 KiB, even if ROMs were disabled.

*5 - The November 1984 issue of the US magazine Commodore Computers contains a rather expressive address list.

4
  • 1
    Out of curiosity, did BASIC 3.5 do anything to improve the performance of calculations involving small whole numbers? Floating-point calculations are a major bottleneck in 2.0, and treating a value whose exponent byte is zero would as a integer whose sign is in the second byte and whose value follows in the next two bytes, would allow additions, subtractions, and multiplications to be performed much more efficiently on such values while keeping most of the floating-point infrastructure exactly as it is.
    – supercat
    Commented Jan 27, 2019 at 18:41
  • 3
    Evidence of the performance pottleneck posed by integer computations can be found using a television receiver and an electrically-noisy C64. Turn up the volume on the TV and listen to the whine produced while performing a N=32000:FOR I=1 TO N:NEXT loop. Each time I passes another power of two, the whine will drop in pitch as a consequence of the increasing numbers of shifts required to align floating-point operands before calculations and normalize them afterward.
    – supercat
    Commented Jan 27, 2019 at 18:44
  • 1
    Not sure if this fits here, as it's not only a different computer, but also a different issue. Then again, the bottleneck is for sure smaler on the C16, as it runs at 0,9/1,8 MHz resulting in an effetive speed of roughly 1.2 MHz - So not only better graphics (sans sprites) on the C16, but also faster than a C64 :)) And for your question: the FP parts of BASIC 3.5 are unchanged - but easy to replace at least. So get one and improve it :))
    – Raffzahn
    Commented Jan 27, 2019 at 18:54
  • 2
    There is a BASIC cartridge for the C64 by RadarSoft that banks out the BASIC ROM to give 51,197 bytes free in BASIC. It also adds a few commands.
    – Tim Locke
    Commented Jan 27, 2019 at 23:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .