Wednesday, July 20, 2011

ANT is insane

So I'm learning how to use ANT. Or, rather, I'm learning the insane limitations of ANT tasks.

Here's how it works. Every ANT task has its own API, its own behavior, and a very limited way of operating.

Example: foreach. I cannot pass in a list of module names, referenced from an XML Property file, into foreach for processing. Can't be done. Why? Because the coder didn't code that in.

But why did the coder have to specify the types of data a foreach statement could take? Why is a generic iterator required to go beyond iteration? And yet foreach does; apparently it must, presumably because ANT has insufficient expression power.

If that's a fundamental limitation of the ANT core system, then why didn't the original writer write ANT in a more generic fashion? This blows me away. It's insane.

If we're going to create a de facto script language out of XML, let's do it right, folks.

(1) Accept a LIST, and nothing more. If this means ANT needs a foundational LIST type, then so be it. If this means foreach needs to be rewritten to accept a LIST and only a LIST, then so be it. To do anything else is INSANE.

(2) Define tasks to be performed inside the foreach. After all, this is control flow. Don't make me perform an assembly-language-like JUMP. Do It Right.

<foreach list="${my.modules}" param="item">
<compile sourcePath="${item.sourcePath}"
destPath="${item.destPath}"/>
</foreach>

Friday, July 15, 2011

i64 Diskette Image header

A "D64 file" is an image file of a real Commodore 1541 diskette. D64s, and related formats, have been around since the 90s. In a previous post, I explained that it might be nice to see a more flexible, parametric approach to Commodore disk images.

I'm currently calling this format "i64", although I haven't fully settled on it.

An old draft of the format is here.

In short, it's simply an optional header block, with parametric data explaining the structure of the image and important offsets.

It's present in any disk image which is of a non-standard size.  For example, if a .d81 file is not the correct size for a d81 image, then look at the first block for the i64 custom header. If it's present, it's located in the first 256 bytes of the disk image -- where a header ought to be located. Otherwise, drive on as usual.

This fancy new header tells us very explicit things about the image.

Structure is 8 bytes, and lays out the four zones of every Commodore disk: the number of tracks per zone, and the number of sectors per track within that zone. Also whether the disk is double-sided (thereby duplicating the zone data for side 2).

Error data can either be prepended to the actual tracks, or appended.

The locations of the disk header block, directory and BAM are required. Offsets to the header and BAM data are required, and how the BAM is stored in the case of dual-sided disks, or indeed if the BAM exists at all.

An autoboot BAM offset, if any. A boot track, if any.

Interleaves.

The disk's default format type and DOS type.

Whether the REL field is used for the LSU.
Whether the file's timestamp is stored in the directory entry.
Whether the Directory is allowed to freely grow and range, like any other file.
Whether the image is allowed to grow dynamically, or is pre-allocated on creation.

The future of the D64 format

The Commodore 64 is an ancient 8-bit system, enjoying a niche fanbase of aging gen-Xers and the youngest Boomers. Emulators are sophisticated and sufficient. You can run games off of a Commodore disk drive attached to your Mac or PC or Linux box. You can run games off of a Commodore computer attached to your home computer acting like a disk drive. You can buy SD-card-reading hardware that replaces a Commodore disk drive. You can buy a joystick that has an embedded C64 burned into its chips. Commodore diskette and hard drive images are insignificantly tiny, compared to today's storage capacities.

What is there to improve on, and why bother?

The second question is the easiest to answer: because the problem space is interesting and well-scoped.

The first question requires creativity. However, I do have some ideas.

Networked "UDP1541"

Current systems bundle all software into one application. Your C64 emulator includes disk and tape support at some level. Some are very sophisticated.

IEC emulation requires effort. It's painful. So I say, if someone has gone to the effort, make it shareable: split the disk drive into a separate application, and communicate via a primitive IEC-friendly protocol over UDP. Not only would this be a fun project, it would also allow emulators to use these "devices" even if they were programmed on a completely different platform. The FC64 AIR app could use the VICE UDP1541.

If you really must, then write it as TCP1541, i.e. using TCP/IP instead of UDP. In this way the C64 emulators may access Commodore drives located on any server anywhere on the internet.

3rd Generation Image Support

The venerable D64 works for 99% of all emulator needs. The G64 works for the remaining 1%. So why is another format needed?

Think of it the other 'way 'round. Emulated drives are common. The D64 format is somewhat irrelevant; it's the emulation support that's more important. An opportunity arises to support the 1541's quirks while not being constrained by it.

So rather than a new format, I suggest that disk drive emulators should be highly parameterized, and tweaked to read those parameters from disk images when present.

I see three areas of compatability: (1) small programs, (2) large programs, and (3) experimentation.

First, MY Solution

My solution is an image header block: the first block, if identified by an identification label and image configuration parameters, would not only tell any reader exactly where all data is located, but also the structure of the data itself -- for example, the number of tracks in each of the four zones, how the BAM is stored in special cases, if error bytes are prepended or appended, if the image is allocated fully or is permitted to grow, and so on. This information and more sits easily within one block of data, and essentially paramaterizes a disk image reader.

I think the best-case scenario would be for disk drive emulators to look for this block on any mounted image that's not the correct size for a typical image file.


1. Small Programs

Where you have small programs, and yet want to remain compatible with a disk-image milieu, it would be nice to have smaller disk images. This argues for a flexible file format at least. One way to do this is to reorganize the disk tracks, so that the header+directory track comes first, and the remaining tracks are added only as needed, in write-order, based on an explicit mapping.

Of course, if you have the flexible image format, all you have to do is define the format, and you're done.

2. Large Programs

The other potential gain is in large, multi-disk programs. In this case, it would be nice to be able to store more than 174k in one image. You could define a larger disk image in some cases.

However, I think a better solution in many (but not all) cases is for emulators to understand the TAR format, and use archiving to group related disks together.

3. Experimentation

This to me is the funnest part. If a disk reader is highly parameterized, there are lots of custom images you can make, and you'd be free to explore the space without worrying about support.

I have custom image formats that I've played with, and found that a little bit of parametric data goes a long way. While not immediately practical, there is potential for interesting formats. Perhaps this is the best way to archive programs, too: let the file size dictate how many zones, how many tracks, how many sectors to have.