I have been wanting to put JiffyDOS on my Commodore 128. My 1541ii came with JiffyDOS, but none of my Commodore Computers did. I recently purchased JiffyDOS from RETRO Innovations, I am also doing a 4 way Switchless JiffyDOS setup on my Commodore 64.
The Commodore 128 Flat model shipped setup with 16k ROMs, it can be switched over to using 32k ROMs by setting some jumpers. If you switch it to 32k ROMs then there are only 2 ROMs required instead of 4. The ROMs that shipped in the Commodore 128 Flat model area also older than what is available. I wanted to update the Basic ROM, and the Kernal as well, so it is nice to only need two eproms instead of four.
In this case I am going to switch to the 32k ROMs, and also install a Switchless JiffyDOS ROM.
To change the Commodore 128 Flat from 16kB ROMs to 32kB ROMs we just have to install jumpers or bridge J3, J4, and J6. I am going to put in Jumpers to make it easy to switch back if needed. You will find instructions at various sources that tell you to do a mod that will connect the one jumper differently (J4) so that you can use the Commodore 128DCR ROM. I found that they did apparently make a Commodore 128 “Flat/D” 32k ROM, well I can’t tell where it came from, but it is listed like it has a Commodore Part Number. I decided to go with just putting in the jumpers for J3, J4 and J6 using the C128 “Flat/D” specific ROM. You can alternately make this slightly different ROM, it is about the order of the data on it.
To setup the JiffyDOS 32K ROM Set. We pull U33 (16k) and U34 (16k) and install the 32k U34 to replace them. That new ROM is the basic.390393-01.bin (32kB).
The second ROM we pull the 16K U32 and U35. Since I am doing the JiffyDOS Switchable ROM, I am making a 64K ROM to replace the original U32.
Switched C128/C128DCR KERNAL ROM (64kB):
basic.901226-01.bin (C64 Basic)
kernal.901227-03.bin (C64 Kernal)
kernal.318020-05.bin (C128 Kernal)
basic.901226-01.bin (C64 Basic)
JiffyDOS_C64_6.01.bin (C64 JiffyDOS Kernal)
JiffyDOS_C128DCR_6.01.bin (C128 JiffyDOS Kernal)
To do the Switched ROM we keep Pin1 (A15) bent out, and not inserted in the Socket. If I was going to do a Kernal “Switch”, then I would wire a 4.7k (recommended value I found) Resistor from Pin1 (A15) to Pin28 (VCC). Then put a switch between Pin1 and Ground. I am going to use an Arduino Pro Mini, it will not need the Pullup Resistor. I expect you could do Kernal Switcher that does more than two modes by making a 128K ROM, but for the Commodore 128 I don’t know of other Kernals that I care to use. That would also be a 32PIN Eprom so an adapter would also be required. If you did stick with the 16k ROMs, you could then alternately use 64k Eproms to setup a 4 way ROM Switcher.
I am basing the Arduino Pro Mini code on a modified version of Adrian Black’s C64 Kernal Switcher. It will be modified to only switch between two modes instead of four. I am starting with Mark Ormond’s modified version of the code as the basis. I only need to trigger switching A15 on one Eprom. It was setup to control 2 Eproms and rotate through more ROMs triggering several Address lines. With 16k ROMs on the Commodore 128 you do need to control 2 different ROMs. The board will be wired with a Current Limiting Resistor to the PowerLED to show the status changes. It will be triggering A15 on the 64k ROM triggering it to use either the upper or lower 32k portion. It will also be wired to the ResetLine, EXROMLine and RestoreKey, as well as Ground and 5V.


Above is the starting point. We have the four 16k ROMs installed. The first part of this modification is to remove them and install the jumpers to switch the system over to 32k ROM mode. That is just adding the 3 jumpers to the board.



There was a bit of an issue with that, the pins are not standard jumper pin spacing, I slightly bent the bottom part of the jumper to get it inserted. I do know there is a smaller size jumper I have seen on other equipment, but I don’t have the pins or jumpers to put on them. After bending the pins a bit they did fit well. I then got out some spare jumpers and installed them. By using the jumpers I can easily switch to 16k ROMs again if I want.
The next thing I had to do was put in the connections for the Switchless Kernal Switcher. It also handles doing a Hard Reset, well it is supposed to. I don’t know how it works with the Commodore 128 as I have only seen such mods on Commodore 64s. I wanted to make it removable, so I put in pins where I could, even to the point of putting pins on the side of two of the 74 logic ICs. That made it so I can detach the Pro Mini board and go back to normal ROMs, be it 32k or 16k ROMs. Also if the Pro Mini fails I can more easily switch it out. Be sure to get a 5V Pro Mini, not a 3.3V model.. The only wire directly soldered to the Pro Mini without a connector on the other end is for the Eprom, but it is socketed itself, so not a huge deal.



Right: Restore U16 Pin 9 (to Pro Mini Pin8)
The last pin is Pin 1 of the new U32. It needs to kept out of the socket and wired to the Pro Mini pin5.

Above you can see the new 64k Switched U32, and the 32k U34 in place. It may not be visible but Pin 1 on U32 is Not in the Socket, it is sticking out on the side and not making contact to the socket. The wire there goes over to Pin5 on the Pro Mini. Since I am using the Pro Mini, as I mentioned there is no Pullup Resistor from Pin 1 to Pin 28 on U32 like would be done with a “switch” based JiffyDOS setup.




I have modified Adrian/Mark’s code so that by default it will do a 4 way Kernal Switch for the Commodore 128. That can only be done with 16k ROMs though. Mark had it setup for 16k ROMs with a 4 way switch for only 1 of the ROMs and only doing 2 way for the second. That has a use, being you can use a smaller Eprom for the 2 way mode, but my version would have to be modified to do that. It now does a 4 way switch for both Commodore 128 16k ROMs by default. I added a “Max ROMs” entry that is set to 4 by default, but for my use I set that to 2 as I am using 32k ROMs and only have 2 sets of ROMs. Well I set it for 2 the second time around, I thought I messed up the code when it was trying to do a 4 way switch initially. I miswired the U32 Pin 1 to the wrong output of the Pro Micro, so I had to fix that too. Other than those two little issues it worked.




There is also the oddity that when it resets, the Commodore 128 goes into 64 Mode. Maybe it doesn’t like the Exrom Reset? It does properly remember the selected Kernal, and it does go into 128 mode when powered on based on the saved Kernal setting, the factory Reset button on the 128 also takes you to 128 Mode. You may catch that the RF Modulator was changed out on the pictures, you can also find the post other recent post about the RF Mod. The RF Modulator change was certainty worth it for the video quality improvement for 40 Column output. I did all of the changes at the same time.
I’m going to work on getting the code uploaded to Github as a branch to Mark’s release. I plan to add some instructions and pictures. Mark does have his pictures and a guide posted at another site, but he has the code at Github.
I am not certain the code below is correct for 16k 4 way switching for the C128 or not. I was getting U35 and U32 etc all mixed up when working on it. It is the code I compiled and used on my 2 way, except below it is set for 4 way switching with that one variable “NumROMs”.
#include <EEPROM.h>
// C64/C128 Kernel Switcher and Restore Key Reset/Selector
// Version 1.3 - 03-26-2023 Updates - By Travis Durf
// Based on C64 Kernel Switcher - 26-March-2019 - By Adrian Black
// Restore Key Mod: https://www.breadbox64.com/blog/c64-restore-mod/
// Initial C128 Changes - 06-22-2020 - By Mark Ormond aka dabone
/*
"The Simple" Pro-Mini
DTR TX RX VCC GND GND
+--------------------------------+
| [ ] [ ] [ ] [ ] [ ] [ ] |
| FTDI |
D1 | [ ]1/TX RAW[ ] |
D0 | [ ]0/RX GND[ ] |
| [ ]RST SCL/A5[ ] RST[ ] | C6
| [ ]GND SDA/A4[ ] VCC[ ] |
D2 | [ ]2/INT0 ___ A3[ ] | C3
D3 |~[X]3/INT1 / \ A2[ ] | C2
D4 | [X]4 /PRO \ A1[ ] | C1
D5 |~[X]5 \ MINI/ A0[ ] | C0
D6 |~[X]6 \___/ SCK/13[ ] | B5
D7 | [X]7 MISO/12[ ] | B4
B0 | [X]8 [RST-BTN] MOSI/11[ ]~| B3
B1 |~[X]9 GND[ ]A6[ ]A7[ ]SS/10[X]~| B2
+--------------------------------+
Based on: http://busyducks.com/ascii-art-arduinos
D3 to EXROMLine (C128 U11 (PLA) Pin12)
D4 to PowerLED to 220 Ohm resistor to Power LED
D5 to C64 A13, C128 U32 (A14) Pin27
D6 to C64 A14 27256(32kB), C128 U32 (A15) Pin1 With 27512(64kB) EEPROM 32kB ROMs
D7 to ResetLine (C128 U63 Pin2)
D8 to RestoreKey (C128 U16 Pin9)
D9 to C128 U35 (A14) Pin27
D10 to C128 U35 (A15) Pin1 With 27512(64kB) EEPROM 16kB ROMs
Set "NumROMs" to be the Maximum Number of ROMs. 2-4 Default is "4"
For Commodore 64:
To do 4 ROM Sets you can use a 27256(32kB) EEPROM with A13 and A14
You can use a 27128(16kB) EEPROM and do 2 ROM Sets with A13.
For Commodore 128:
To do 4 ROM Sets on a stock C128 Flat that uses 16k ROMs you can use 27512(64kB) EEPROMs with A14 and A15
You can use 27256(32kB) EEPROMs and do 2 ROM Sets with A14.
For C128 Flat/D set to 32kB ROMs, or DCR (Both use 32kB ROMs), you can use 27512(64kB) EEPROMs to do 2 ROM sets with A15.
When doing 32kB C128 ROMs you only use U32 and only use A15 as A14 is kept in the Socket and controlled by the C128.
U35 is removed in the 32kB ROM configuration and is now included in the 32kB based U32 now. The drawback here is you can only
do two ROM Sets with the 27512 EEPROMs.
The C128 Basic ROMs must be replaced with a new 32kB Basic ROM (basic.390393-01.bin) in U34, also removing U33.
*/
const int EXROMLine = 3; // Output the /EXROM line
const int PowerLED = 4; // Output Power LED
const int PowerLEDAlt = 13; // Output Power LED (onboard LED)
const int RomAOne = 5; // Output EPROM C64 A13 (C128 16kB Mode U32 Pin27 A14, 32kB Mode U32 Pin1 A15)
const int RomATwo = 6; // Output EPROM C64 A14 (C128 16kB Mode U32 Pin1 A15 27512 EEPROM)
const int ResetLine = 7; // Output to /RESET line
const int RestoreKey = 8; // Input Restore key
const int RomBOne = 9; // Output EEPROM C128 16kB U35 Pin27 A14
const int RomBTwo = 10; // Output EEPROM C128 16kB U35 Pin1 A15 27512 EEPROM
int RestoreDelay = 2000; // 2000ms delay for restore key
const int FlashSpeed = 75; // LED Flash delay
const unsigned long repeatdelay = 500; // used for debouncing
const int NumROMs = 4; // Maximum Number of ROMs
int CurrentROM; // which rom is select (0-3)
int debouncecounter = 0; // how many times we have seen new value (for debounce)
int debouncereading;
int debounce_count;
int RestoreHeld;
unsigned long TimeHeld; // amount of time Restore is held down
int buttonDuration = 0; // for keeping track of how long restore is held down
boolean buttonHeld = 0; // for keeping track when you are holding down
boolean Released = 0; // Keeping track when the restore key is released
boolean holdingRestore = 0; // Keeping track if you are holding restore
boolean resetSystem = 0; // keep track whether to reset
int buttonInput; // used to return if restore is held
unsigned long time; //used to keep track of millis output
unsigned long htime; //used to keep track of millis output
unsigned long btime; //used to keep track of bounce millis output
void setup() {
pinMode(PowerLED, OUTPUT);
pinMode(PowerLEDAlt, OUTPUT);
pinMode(RomAOne, OUTPUT);
pinMode(RomATwo, OUTPUT);
pinMode(RomBOne, OUTPUT);
pinMode(RomBTwo, OUTPUT);
pinMode(ResetLine, INPUT);
pinMode(EXROMLine, INPUT);
pinMode(RestoreKey, INPUT);
digitalWrite(PowerLED, HIGH); // turn on the power LED
digitalWrite(ResetLine, LOW); // keep the system reset
pinMode(ResetLine, OUTPUT); // switch reset line to OUTPUT so it can hold it low
digitalWrite(ResetLine, LOW); // keep the system reset
CurrentROM = EEPROM.read(1);
SetSlot(CurrentROM);
delay(200);
pinMode(ResetLine, INPUT); // set the reset pin back to high impedance which releases the INPUT line
delay(1000); // wait 1000ms
FlashLED(CurrentROM); // flash the power LED to show the current state
// all set!
}
void loop() {
buttonInput = readButton(); delay(500);
time = millis(); // load the number of milliseconds the arduino has been running into variable time
if (buttonInput == 1) {
if (!buttonHeld) {
htime = time; TimeHeld = 0; buttonHeld = 1; } //restore button is pushed
else {
TimeHeld = time - htime; } // button is being held down, keep track of total time held.
}
if (buttonInput == 0) {
if (buttonHeld) {
Released = 1; buttonHeld = 0; htime = millis(); TimeHeld = 0; //restore button not being held anymore
}
}
if (TimeHeld > RestoreDelay && !Released) { // do this when the time the button is held is longer than the delay and the button is released
htime = millis();
if (holdingRestore == 0) { FlashLED(CurrentROM); holdingRestore = 1; resetSystem = 1; } // first time this is run, so flash the LED with current slot and reset time held. Set the holding restore variable.
else {
if (CurrentROM < NumROMs - 1) { CurrentROM++; SaveSlot(CurrentROM); } // or you've already been holding restore, so increment the current ROM slot otherwise reset it to 0
else { CurrentROM = 0; SaveSlot(CurrentROM); }
if (TimeHeld > RestoreDelay) { TimeHeld = 0;} // reset the time held
FlashLED(CurrentROM); //flash the LED
}
}
if (Released) {
//if time held greater than restore delay, reset the system, set the current rom slot, reselt the time held and holding restore
if (resetSystem) { // on do this if the reset system has been set above
htime = millis();
resetSystem = 0;
holdingRestore = 0;
Released = 0;
digitalWrite(ResetLine, LOW); // keep the system reset
digitalWrite(EXROMLine, LOW); // keep the EXROM line low
pinMode(ResetLine, OUTPUT);
pinMode(EXROMLine, OUTPUT);
digitalWrite(ResetLine, LOW); // keep the system reset
digitalWrite(EXROMLine, LOW); // keep the EXROM line low
delay(50); // wait 50ms
SetSlot(CurrentROM); // select the appropriate kernal ROM
delay(200); // wait 200ms before releasing RESET line
pinMode(ResetLine, INPUT); // set the reset pin back to high impedance so computer boots
delay(300); // wait 300ms before releasing EXROM line
pinMode(EXROMLine, INPUT); // set the reset pin back to high impedance so computer boots
} else { //otherwise do nothing
htime = millis(); Released = 0; resetSystem = 0; holdingRestore = 0;
}
}
// finished with loop
}
int readButton() {
if (!digitalRead(RestoreKey) && (millis() - btime >= repeatdelay)) {
for(int i = 0; i < 10; i++)
{
debouncereading = !digitalRead(RestoreKey);
if(!debouncereading && debouncecounter > 0)
{
debouncecounter--;
}
if(debouncereading)
{
debouncecounter++;
}
// If the Input has shown the same value for long enough let's switch it
if(debouncecounter >= debounce_count)
{
btime = millis();
debouncecounter = 0;
RestoreHeld = 1;
}
delay (10); // wait 10ms
}
} else {
RestoreHeld = 0;
}
return RestoreHeld;
}
void SaveSlot(int CurrentRomSlot) {
// Save Current ROM selection (0-3) into EPROM
EEPROM.write(1,CurrentRomSlot);
}
void FlashLED(int flashcount) {
// Flash the LED to represent which ROM slot is selected
switch (flashcount) {
case 0:
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
break;
case 1:
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
delay(FlashSpeed);
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
break;
case 2:
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
delay(FlashSpeed);
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
delay(FlashSpeed);
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
break;
case 3:
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
delay(FlashSpeed);
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
delay(FlashSpeed);
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
delay(FlashSpeed);
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
break;
default:
digitalWrite(PowerLED, LOW);
digitalWrite(PowerLEDAlt, LOW);
delay(FlashSpeed);
digitalWrite(PowerLED, HIGH);
digitalWrite(PowerLEDAlt, HIGH);
break;
}
}
void SetSlot(int DesiredRomSlot) {
// Select the actual ROM slot being used
switch (DesiredRomSlot) {
//Stock-Kernal0
case 0:
digitalWrite(RomAOne, LOW);
digitalWrite(RomATwo, LOW);
digitalWrite(RomBOne, LOW);
digitalWrite(RomBTwo, LOW);
break;
//Kernal1
case 1:
digitalWrite(RomAOne, HIGH);
digitalWrite(RomATwo, LOW);
digitalWrite(RomBOne, HIGH);
digitalWrite(RomBTwo, LOW);
break;
//Kernal2
case 2:
digitalWrite(RomAOne, LOW);
digitalWrite(RomATwo, HIGH);
digitalWrite(RomBOne, LOW);
digitalWrite(RomBTwo, HIGH);
break;
//Kernal3
case 3:
digitalWrite(RomAOne, HIGH);
digitalWrite(RomATwo, HIGH);
digitalWrite(RomBOne, HIGH);
digitalWrite(RomBTwo, HIGH);
break;
default:
digitalWrite(RomAOne, LOW);
digitalWrite(RomATwo, LOW);
digitalWrite(RomBOne, LOW);
digitalWrite(RomBTwo, LOW);
break;
}
}
While I was working on the Commodore 128, I had been having issues with the Cartridge Port reading correctly. So while I had the board out I reflowed all the pins on the cartridge port. Upon getting the Kernal Switcher (and RF Modulator change) done I put in two different cartridges and both worked properly the first time. I’m hoping this means my Commodore 128 is in good working order now. It is annoying not being able to use cartridges reliably. I do have JiffyDOS now. I need to try it out with my 1541ii that has a Vintage JiffyDOS rom in it. I also purchased JiffyDOS for the 1541, and will be putting it on my pi1541 and trying that out. But not tonight, it is way to early in the morning to start that, I am going to go get some sleep. I was nice getting a number of these projects wrapped up today/ in the last 24hours.

I realized I forgot to show a JiffyDOS 128 80 Column RGB Video screen shot. You see it adds the JiffyDOS line to the startup screen there.