Tag Archives: 1541

Reading and Writing Sequential Data on the Commodore 1541

Commodore LogoSometimes it’s helpful to store large amounts of data on the disk rather than keep in it memory. Consider adventure games for example: you could add room descriptions to your listing and later read it into memory – but this would double the amount of memory you really need to keep the data. Since there’s only 64KB available on a C64 that’s not smart – given that you have another 170KB sitting there next to the breadbox.

The 1541 supported reading and writing “sequential data”. It means that rather than print text and other data onto the screen, you can divert it to the floppy drive. Likewise, we could read back that data – similar to how we communicated with the 1541 when issuing CBM DOS commands.

This time we’ll

  • open a data channel (OPEN 8,8,8,”filename,direction,type”)
  • use a command (i.e. PRINT# or INPUT# or GET#)
  • close the channel

We need to specify the Read or Write direction in the process with the file name, and we also need to specify the file type. There were four to choose from: PRG, SEQ, USR and REL – corresponding to the cryptic abbreviations in the directory listing next to the file name. It was more cosmetic really and didn’t make a difference to what was happening in the actual file. Think of it as today’s file extensions.

Here’s a quick listing to illustrate the process of reading and writing sequential data:

Here we create a new file called “SEQUENTIAL” with the type of SEQ and add three lines of text and an integer to it. Each time we write an entry a CR character is added to the file (carriage return) which makes it easy to read those variables back in later. If the file already exists we’ll overwrite it.

Next we’ll read all values back by opening another channel (in fact the same one). The INPUT# takes in 4 strings, even though in line 51 we’ve written an integer – however behind the scenes it gets quietly converted to a string and is saved as such. Hence, if you’d like to work with numbers you must convert them back using VAL(string).

GET# works just like its BASIC counterpart GET and will read a single character from disk. This can give you more flexibility and hunt for your own “separation characters” while reading data.

Commodore 1541 DOS Commands

Commodore Logo

The 1541 Floppy Drive was equipped with its own MOS 6502 chip and was therefore capable of understanding and executing its own commands (to format the disk, copy files, erase files, etc). The idea was that it could operate autonomously without the attached C64 to get involved – revolutionary at the time. They were called CBM DOS commands – indeed as in Disk Operating System, not to be confused with the later MS-DOS or DR-DOS.

Those DOS commands were not part of BASIC and had to be sent to the drive with a dedicated channel. In principle you needed to

  • open a channel (with OPEN 15,8,15)
  • issue the command (for example, PRINT#15,”command”)
  • and close the channel (CLOSE 15)

This worked in direct mode as well as from within programs too. Note that opening a channel followed by a BASIC disk operation involving the drive (such as LOADing or SAVEing a file) would automatically close the channel.

If you’re wondering about the significance of 15: it’s the 1541’s command channel. Channel 0 and 1 are for the operating system to transfer files, 2-14 can be used for your own operations, and 15 is good for what we’re doing now.

Here are some of the more useful commands. We’re assuming your drive number is 8 (change where appropriate):

Formatting a Floppy Disk

Nothing came pre-formatted in those days – everything was blank. The NEW command would be your best friend, taking about 10 minutes or so to give you a whopping 170KB of precious space per side. This was known as a “hard format”:

You can also abbreviate NEW with N. The presence of the 0: after the command was used to indicate which drive you were using in dual-drive setups, meaning 0 for the left and 1 for the right drive. The 1541 was a single drive and hence will only respond as 0.

This took a whole minute or two for the whole disk, and being the busy people we were turning into even back then, we were glad to know that there was a sort of “soft format” command available that would only erase the BAM and thereby clear out the directory. It did not write sectors on the disk, and instead simply marked them all as “available” again. It saved a lot of time and could be achieved by omitting the disk ID from the above command, like so:

Notice the way I’ve used the N instead of the NEW command here, and that there’s no comma or ID after the disk title. Since we do not specify an ID, it will remain as it was before the soft-format. We still use the same principle with modern hard drives today when we use the “quick format” option.

The Mysterious Initialize Command

Some CBM commands were a little puzzling and rarely used. The I or INITIALIZE command was one of those. It exists, and thanks to a comment by Dan, I finally understand what it actually does.

It takes no parameters and will read the current BAM/Directory into the disk drive’s memory. This is sometimes necessary as a way to check if the user has indeed changed a diskette after being prompted so by their software. Without such a check, software packages might receive data that does not exist on the disk.

Duplicating Files

You can duplicate THISFILE into THATFILE on the same floppy and generate your own safety copies.

Can be abbreviated with C. Note that you cannot use this command to copy from one drive to the other (like drive 8 to drive 9). You could even copy up to 4 files together, presumably concatenating them – but it never worked for me.

Renaming Files

Can be abbreviated with R.

Deleting Files

The SCRATCH command will do this. Can be abbreviated with S:

Validating your Floppy Disk

Before there was our new favourite “Device hasn’t been removed properly” message, things could still go wrong with floppies over time: write operations were started but never finished, channels were opened and prematurely closed, and so forth. If you’ve used a floppy over time for saving, renaming and deleting a lot of files, it may need a cleanup.

VALIDATE to the rescue. This command will go through existing files, defragment your sectors, update the BAM and speedup disk access to your precious 170KB of space. Can be abbreviated with V:

This will however ruin your data forever if you’ve been using your drive it with direct access (i.e. without LOAD or SAVE commands – we shall speak about this in another article).

Reading the Error Channel

One final thing that we did was to diagnose error messages that the 1541 was reporting – in the rarest of circumstances of course. Usually you knew what happened (i.e. no disk in drive, bad floppy, etc), but sometimes it wasn’t obvious – or you wanted to give users an explanation.

Much like we can issue a command with PRINT#, we can also read what the drive is telling us with INPUT# – much like we can read keyboard input from a user into a variable.

INPUT# does not work in direct mode, only in BASIC programs. Here’s how:

This little programme will remove the blinking red light from the drive and show you what’s wrong. Only the second variable is a string, but you can read the others in as strings too if you like.

Will report the CBM DOS version when the drive has just been switched on. Should the drive not be available (i.e. turned off) the programme will hang until you hit RUN STOP/RESTORE.

What’s that 0 after these commands?

Notice how I’ve used a 0 after each command, like NEW0. That’s the belt-and-braces approach to using disk commands. This is optional in most single drive units. Most of us never had the pleasure to use the old dual disk drives, but they did exist – and from what I understand, Commodore used very similar firmware in newer drives.

In these dual-disk machines (i.e. 4040, 8050, etc) you could specify which drive in the unit you were talking to. Drive 0 is the one on the left, drive 1 is the one on the right. The whole unit is then either unit 8, 9, 10 or whatever else. In single drive units, you can leave the 0 out and simply call the command (like NEW or N) without a number behind it.

Commodore 64 BASIC v2 Disk Drive Commands

Commodore LogoI must admit it’s been a while since I’ve loaded files from a C64 and the 1541 Floppy Drive – let alone save programs back to disk.

Here’s a quick reference how we did things 30 years ago:

Opening Files

The C64 BASIC v2 did not have built-in commands for talking to the drive. Instead, we used the standard LOAD command to bring things into memory, appending the disk drive number (which was 8 by default).

If you don’t specify the drive number the system assumes “1” which is the Datasette (tape drive) and will prompt you to “PRESS PLAY ON TAPE”.

Loading a BASIC programme from Floppy Disk is done like this:

Listing Directories

Another lightly annoying habit was that to look at the disk directory, you had to load its contents into the BASIC memory – overwriting any programme you were currently working on.

Here’s how to load the directory and LIST it:

The later BASIC versions 3.5, 4 and 7 all had the DIRECTORY command which would do this without killing your programme in memory.

Saving Files

To store your current programme on Floppy Disk you specify the name of the file and the drive number, like so:

Since you can’t show the directory on the C64, this may result in a red flashing light on the drive, telling you that the file already exists. The good news is that you can overwrite a file using

Note that this will write the file first, and then delete the original. On one hand it’s a great safety mechanism, on the other you may encounter a “full disk” error. Those were the days!

Verifying Files

The C64 also had a VERIFY command which would compare byte by byte that what’s on the floppy is indeed what is in memory.

The later BASIC versions 3.5, 4 and 7 implemented the DLOAD, DSAVE and DVERIFY commands which would let you do such things without specifying the drive number. Those would assume you’re using drive 8.

Saving arbitrary blocks of memory onto disk

The above commands are all great if you’re saving BASIC programs: in essence, everything from 2048 to the end of the current programme in memory will be saved to disk. BASIC uses a pointer which specifies where it’s stopped using memory. But if you’ve added some machine or binary code somewhere in memory you may want to save other parts of the memory too.

It’s not easy – but here’s how to do that from BASIC v2:

Modify the S and E to suit the Start and End of the memory you’d like to save. The routine then calculates and sets the high and low byte of your block, sets a file name, and finally calls a save subroutine. Here’s a mote compact copy-and-paste version:

Thanks to buzbard from the Lemon64 forum for this snippet!