13

The C64 kernel (or KERNAL as it’s known in the C64 community) routines work via a jump vector table stored in page $03xx. A common programming paradigm to create something like a "device driver" would be to hook the kernal routine by replacing the appropriate jump vector table entry with a pointer to your own custom code. So kernal calls just jump to your code instead of the routine in ROM.

What is the best approach and memory location(s) for stashing your custom "device driver" code, so that compatibility is as good as possible? Assume you want the BASIC interpreter to continue to work, normal DOS functionality to not be impacted, and minimize the chance of some other software over-writing your driver. Also, what needs to change to have the same functionality in C128 mode?

  • 2
    I see that the term "kernal" in my original question has been recast as "kernel". Most C64 programmers and publications used the spelling "kernal". See en.wikipedia.org/wiki/KERNAL – Brian H May 27 '17 at 19:55
  • If you want to get pedantic the C64's kernel name is KERNAL, based on a misspelling in the early 80s. The right name is "kernel" in terms of how it was referred to internally at Commodore. – Joe May 29 '17 at 13:30
  • 6
    There is a kernel of pedantry implicit in either correct spelling. – Brian H May 29 '17 at 15:24
  • Actually, "kernal" was used for the entire range of Commodore 8-bit machines. People referred to the PET's kernel as the Kernal". – JeremyP May 31 '17 at 9:42
17

There was, in my opinion, not much standardisation for things like that for the c64.

  • The simplest approach would be to put your code in the range $C000-$CFFF, and then modify the jump table at $03C0. The area $C000-$CFFF is not used by the system.
  • Another approach would be copying the content of one or both of the rom's in underlaying RAM. Modify the copied code in the RAM. Switch the memory map so that RAM is used instead of ROM.
  • A third approach (if you need much space) would be to write your routines in underlaying RAM. Modify the jump table at $03C0 to jump to the $C000 area (like in method 1). There you bank ROM out and RAM in and jump to your routine. Don't forget to bank back after finishing your routine.
  • This methods can be mixed. Use method 2 on the kernal ROM area, replace the routines by a simple bank and jump routine (that banks the basic ROM and jumps to your routine in the RAM under the basic ROM). This is very usefull if you don't want to use the $C000 area.
  • Another possibility is to lower the area used by the system for BASIC. So you will create space for your routines.

I can't help you with C128.

  • If I want my device driver to survive program loads, then is the RAM under the kernal ROM best? My assumption is that most programs will load into the normal RAM for BASIC, then the $C000 RAM if they need more space. So programs that actually use the kernal are unlikely to touch the RAM under the kernal, perhaps? – Brian H May 27 '17 at 19:45
  • It's really tricky to use the ram under the rom though in normal execution. You would have to not muck with the layout of the ROM or bank switch on the fly. There is no single "best@ way to avoid all conflicts; there are no fully safe places in the C64 memory map that everyone else avoids. c000 was safe from BASIC but lots of stuff went there. the tape buffer area was smaller but also well used. Then there's the 38k for BASIC programs and data. – Joe May 27 '17 at 21:50
  • It is hard to say which place will survive loads out of the BASIC program area. If another programmer followed the same way of thinking he will use the same places as you... – EL Dendo May 28 '17 at 12:00
4

The best approach is replacing the whole kernal. Discarding rarely used routines and putting new ones in their place.

Nowadays Easyflash and 1541 ultimate users have the chance to replace the kernal at will without opening the c64 case and doing any soldering.

So it's a viable method.

There are two main obstacles with a software only solution. 1. Preventing other software to not mess the hooks you setup is not trivial and it will only work for certain software. Compatibility would depend on ram needed by your custom software. 2. You need to load it on every boot before loading the actual software that will make use of the custom routines.

The other solution is to create a custom cartridge. Since this introduces extra memory (rom) to the computer it will be resident at least. You still need to cope with sharing ram with the actual software that will be running on the computer but this time it's not as hard as pure software solution since you will be hosting the code on the cartridge rom. You can use rarely used I/O areas or such to increase the compatibility.

  • Cartridge ROM is an interesting option. A standard 8K cartridge occupies $8000-9FFF. If the cartidge boot code relinquishes control back to BASIC, then is the cartridge ROM always banked in, and so it just steals the upper 8K of BASIC program space? Can it be "banked out" by ML programs that need that space? – Brian H May 30 '17 at 23:19
  • Yes, it's possible with a few ttl chips on the cartridge.Basically one need to build an address decoder and need a latch to store such setting. – Nejat76 May 31 '17 at 7:12
  • 1
    You can simple use an 74138 3 to 8 decoder chip. G1 = PHI2, /G2A=/IO1, /G1A=RW Since you will control just a single memory address you can use any of the 8 output pins you want supplying hardcoded (to GND or VCC) address lines or simply take an address range with supplying 3 bits of an I/O address. The output of decoder is used on the latch which is connected to databus. Of course one need to take care of the initial condition where either EXROM or GAME signal to be pulled low. Wiring reset to the CLR line on the latch would do the job I guess. – Nejat76 May 31 '17 at 7:27
  • @BrianH: Using some interesting timing trickery, it's possible to have a cartridge which replaces any or all of the ROM on a C64 by pretending to be a "Max Machine" cartridge during part of each CPU cycle, but which otherwise allows the system's memory map to behave normally. I don't think anyone knew of the trick back in the day, and from what I understand it does not work and is not adaptable to the Commodore 128 which only checks for Max Machine cartridges on startup rather than continuously. – supercat Nov 30 '17 at 19:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.