Sunday 16 January 2022

UPLOAD.COM for Z80 CP/M - writing the utility

Below is a pkg file. It's easy to see what's going on. Your source file is in hex and padded to the 128-byte boundary. There's a count and checksum at the end. The first line is the instruction to use '' to put the file into the current directory as the name specified.

I wrote this utility for my Mac some time ago, it allows me to convert any file, paste the result into the Terminal app I'm using to communicate with my RC2014 and have the file copied onto one of the drives.

What has been missing is a way to do the opposite. To grab a file from the RC2014 as the original binary file. I've written about that problem here. The very neat solution would be to have a Z80 program which does this same conversion on the RC2014 and displays a file that you can copy and paste - and either convert back into a binary or store for re-downloading at some later point.

Conveniently, there's an example program in the CP/M Operating System Manual called A Sample File Dump Utility (5.4). This very nearly does what we want. It takes a filename as an argument and dumps that file as hex to the console (formatted neatly with numbering and spaces, which were easy to take out).

It was also easy to add the necessary count and checksum, output A:UPLOAD at the start along with the filename. 

I decided to look up the actual user number, rather than just printing "U0". This is the start of my deep dive into BDOS - a series of operating system calls, documented and available for you to use in your programs. They tend to involve setting up parameters in Z80 registers, setting the C register to the number of the call that you want to make, and then CALLing the base of the BDOS.

I've dabbled in this before, it provides convenient ways to receive keys and output characters to and from the console.

Getting the user number is simple. 

But then we came to parsing the passed argument for wildcards and finding matching files. The example program doesn't do this. It simply OPENs the file that's specified by the user, and if that happens to contain wildcards, the first matching file is opened. 

UPLOAD.COM would be a whole lot more useful if it does pattern matching and spews out all of the matching files. It now does and I've demonstrated this in my guide.

The CP/M documentation isn't bad. It allowed me to discover that you can pass a filename to a 'first' and 'next' functions (17 and 18) which give you the first and subsequent matches for your filename which contains ? or *.

I learned that the system has a 128-character buffer at a known location, which is used for passing results for certain functions. For filenames It's divided into 4 32-byte buffers and you get a number 0-3 in A which you shift-multiply by 32 and add to the base address of the buffer for the result you need.

After calling the 'first match' function, you have to call the 'next match' immediately, and then again, as long as you receive a valid result. (You can use this same process without checking whether your filename contains wildcard characters. If it doesn't, then 'first match' just returns your file, and 'next' will return 255 meaning 'no more results').

It would seem sensible to use the 'first' and 'next' system at the start and make an array of matching filenames. Instead I chose to do something less efficient, but that I thought was simpler to write, which is a 'get_nth_match' function, which passes the original filename to 'first' and then calls 'next' the appropriate number of times.

UPLOAD.COM is available here and included alongside with the CF cards that you can buy for your RC2014.

No comments:

Post a Comment