T64 to CRT

This is a LONG read. You can skip to the interesting parts by simply scrolling. And you can get the bits right here: T64Loader.zip

History

Back in 1984 my "career" started with the publication of "Hypra Load" in the magazine "64'er". This was one of the first software-only "fast loaders" for the C64/1541 duo. The main floppy code was done by Karsten Schramm, I worked on Kernal integration and the actual "listing", a printable code for the magazine that readers could type in. We had no internet or BBS.

40 years later I have seen the surge in creating "pure" software collections for the good old C64 that want to be as close as possible to the original games, but without the wait to load. There is a certain kind of "hacker ethic" and "cracker vanity" where most games floating around on the internet have large cracker intros, extra features like typed in docs and trainers, built-in fast loaders and more. Those quality-of-life features are good and well on original hardware and recreate the experience that a lot of us actually had of those games (when pirated copies outnumbered sold originals by a hundred to one) but, well, I would like the actual game and not a cracker intro. There are many in the scene that think differently, and this is just a personal opinion.

A guy named "Statmat" in the UK started "OneLoad64", a fantastic collection of C64 games stripped down to well, the game. In early 2024 Pugsy created the CRTLINKER (New Release: Magic Desk CRT Linker (make your own CRTs) - Commodore 64 - Lemon64 - Commodore 64) to create your own versions of single loaders. With these modern tools it is easy to take original masters of games, basically "freeze" them at the exact moment loading is done and the game begins and then wrap these into instant loading files and cartridges. This gives many games a console-like experience: Plug and Play. To keep the good old Loading Screens and Loading Music these tools can preserve these too. But - they are for single load games only.

Also, a lot of people (to name a few and say thank you: Stephan Scheuer, hellboy73 and Solo1870) have created awesome versions of multi-load taped-based and disk-based games that load (and save) to this specific cartridge instead. The Easyflash systems are powerful beasts, as the C64 can actually write to them, so they can be used for game saving and highscore keeping. But they are also complicated as they require a lot of specific code to achieve these marvels because they also bank out the BASIC rom space ($A000).

There is a middle-ground, the Magic Desk Cartridge, originally only for 64K ROMs but now extended to a full Megabyte, with a primitive but easy to handle bank switching system, covering "only" $8000-$9FFF and no write functionality. Write a bank number from $00 to $7F to $DE00 and there you are in the specific 8K bank. Set bit 7 and the bank is invisible. Super easy and therefore ideal for compact software.

So, I asked myself: Could I contribute to the Multi-Load-scene with an easy tool to use the Magic Desk format? Over a course of three weeks, I brushed up on my 6510 coding skills (unused for nearly 40 years) and Kernal vectors. With the help of the awesome C64Studio and VICE debugging it was a delight to go back into self-modifying code, indirect Zero-Page addressing and finding the shortest possible algorithm to calculate from a double word to a bank switched offset address.

First, I wanted to create my own file format for the package, then I thought "T64 is out there and there are tools for it so I don't need to python my own packager", then I got sidetracked because the otherwise awesome DirMaster has major faults in T64 editing and by the time I had this all fixed I could have written my own file format. But I like the idea of using something already out there.

This is the rationale for T64 to CRT. It is a useful tool to convert games that do not require write access into cartridges (or tape/disk). It looks "cleaner" than Disk2Easyflash, which still is an awesome tool, but has longer boot times.

I hope T64 to CRT it is a useful addition to the C64 community.

The features

T642CRT is many things in one package. On the easiest level it is a 768-byte front end for any T64 image. Copy the loader and the T64 file together, convert into Magic Desk format, presto, you have an instant loading "tape" of up to 1 MB size.

If you use tools to put Snapshots into PRGs or CRTs, you can simply put all subsequent parts of a game into a T64 image and install one call into the cartridge in the snapshot. It will install the loader and as long as the game uses the standard Kernal vectors, all LOAD access to the tape or disk is rerouted.

And if you have a game that needs extra special care, you can rebuild the loader to load at any other address below $8000 (or in the $C000 space) and create a special version.

Other features:

  • The loader can be compiled for any bank of the Magic Desk cartridge. Of course, it autoboots only in Bank 0. You need to compile the code for any other bank, because reading the current bank from $DE00 is unreliable (it worked sometimes and then stopped for me). This makes it possible to use the loader with other tools that create Magic Desk bins.
  • The loader uses provided load addresses (not the one from the first two bytes of the file itself) if the secondary address is 0 (used by some games to trick crackers, originally in the Kernal to load stuff at $0801, no matter what the PRG says).
  • LOAD "$" will provide a short listing of the first seven files on the tape (not complete) - sorry, this had to fit into the 768-byte limit. On the other hand, it does NOT destroy any memory, it just writes to the screen!
  • LOAD "*" and LOAD "" are loading the first file in the T64 image.
  • The loader refuses to write below $0400 for safety reasons, that can be shut off in the source code (but please move the tape code somewhere else).
  • The loader will autoload the first file of the tape if the filename starts with a "!" and converts the next 4 PETSCII characters (e.g. 0820) into a JMP address executed right after the load.
  • The loader captures ALL devices, so the same code works for ,1 (tape) or ,8 (disk) or others. In theory, the loader can also be used to convert IDE64 based games if they only use the standard LOAD vector and no specific IDE64 code.

Shortcomings:

  • Magic Desk Cartridges larger than 128KBytes are not supported by VICE 2.4 and below or some other emulators. This means larger cartridges do not work on an unmodified C64Mini or TheC64. Libretro-VICE, which is used in most emulation setups these days, is based on VICE 3.X and works fine!
  • To avoid crashing, all SAVE calls are just acknowledged without saving anything. If you want to save your game progress, you need to use the snapshot function of your emulator. If you want cartridge games that save progress, there is no way around of doing a (more complicated) EasyFlash conversion. Remember though that on emulation you then have to save the cartridge image itself! I prefer the Snapshot solution on emulation. For a real C64 of course the Easyflash route would be preferred.
  • The loader currently installs in the tape buffer. If your game uses the tape buffer, you need to find another place and recompile. The loader needs <160 bytes somewhere in RAM and you can crunch this a bit by taking out safety features, but these need to stay untouched. Fortunately, this is LESS than most tape fast loaders, so multi-load tapes should be convertible.
  • There is a simple logic for games that load into color RAM. If start and endaddress of a load are in the color RAM space, the code assumes that color RAM is needed. If you find an odd case where there is a load into these addresses that should go into standard RAM, you can switch off that feature in the code.
  • The Zeropage is left untouched, only the bytes set by the Kernal Load routine are used!

Simple Usage

The package you are looking for is here: T64Loader. It contains the source code as well as a prebuilt standard binary for bank 0 and then 8, A and B. Ignore the binaries for the other banks and stay with the standard.

If you have a .T64 file, conversion into a cartridge is very easy. You need the cartconv tool from a recent (!) version of VICE (not before 3.X) and run just two commands:

copy /b t64loader.bin + FILENAME.t64 FILENAME.BIN
cartconv -i FILENAME.BIN -o FILENAME.CRT -t md -p

The first one glues the files together into a binary (that could be burned into ROMs), the next one converts into a file format for emulators.

That's it. If you start your C64 with that cartridge, you will see this:

You can now show a "directory" of the cart - the code for this cheats a lot to stay small and not do any page traversal, so it can only show a certain number of files. It is mainly a control for you as well as capturing the "$" and now go into an error.

We can now load the first program and run it. Or the second (if you want to do a compilation, but there are better tools for that).

Autostart

To create a cartridge that automatically starts the first program, you need to find the jump in address. In my case (Koronis Rift, more on that later), after loading we need a JMP $0820. Rename the first file in your T64 (that would be the "0KORONIS" in my example) to "!0820" and voila, it is automatically loaded and started at boot time!

Creating T64 images

To my best knowledge as of today, Februrary 2024, there is only ONE tool that creates correct T64 images: Compyx/t64fix: Tool to fix T64 tape image files (github.com)

Every other tool makes mistakes. End addresses are wrong, PRG headers are wrong and the otherwise totally awesome DirMaster from Style mangles T64 files during editing beyond recognition.

To create the T64 you just have a directory of the files that need to go in there and then:

t64fix -c FILENAME.t64 DIRNAME\*.

To get the files into this directory is a bit more complicated. You can take any tool that reads C64 images and exports into your filesystem but must follow these rules:

  • You need to delete the ".prg" extension.
  • You need to convert to all lower case characters.
  • Any file that needs to be up front needs to start with a 0.

t64fix uses Windows sorting for putting the files into the container. That also is the reason for using the "!" as the autostart character - Windows sorts this before most other characters.

The actual order of the files inside the system is irrelevant. The loader searches the directory and then loads the file. The search code is not totally foolproof, but I have not seen any instance where it would fail with real programs.

Getting the files off original tapes

The best tool to get to the files off a tape image (we don't deal with physical tapes here, that is out of scope) is TAPClean download | SourceForge.net

While TapEx is a sometimes more powerful tool, unfortunately it does not preserve filenames and renames every file it exports to its load address and a logical number. With tapclean you can do:

tapclean -t FILENAME.tap -doprg

A subdirectory named "prg" will be created with the files. Most of the turboloaders are decoded - if the specific game you are looking at is not, you need to look for other tools on your favourite search machine. Fungus from Triad has released many tools running on the C64 itself that can get files of specific loader tapes.

Remember that you have to rename the files. 019 (0820-CFFF) [KR].prg needs to be just kr. (no extension!). Use your favourite rename tool to automate that for you.

Building Koronis Rift

To build a simple autobooting fast cartridge off the tape version of Koronis Rift you simply have to:

  • Find the original .tap on the Internet.
  • Extract the files with tapclean.
  • Rename the files.
  • Check the address the main game (largest file) starts with ($0820).
  • Rename kr. to !0820.
  • Build the t64 with t64fix.
  • Combine loader.bin and .t64 with MS-DOS copy command.
  • Cartconv into Magic Desk.
  • Profit.

No code adaption is needed. The T64 cart loader lives in the same space usually Novaload would be in, so the game does not touch it. For loading it uses the standard Kernal vectors, so each load is automatically captured and rerouted to our cartridge.

I have also built a nicer (loads faster and has a title screen) version of Koronis Rift and if you are interested in the extra steps, the detailed instructions are here: A better version of Koronis Rift. This will show you advanced techniques to combine the loader with tools like CRT Linker.

Pitfalls

  • Some tape loaders have no filenames. They just blindly load the next file. For these you need to refactor the code. Loading sequentially is (not yet) supported. I'm thinking about this though.
  • Some tapes have multiple files with the same name. Most often they are identical. In order to save you from forwarding and rewinding the tape all the time, some parts are just saved several times. If you see identical filenames, do a checksum and see if they are identical. You just need one copy - there is only a tiny time difference for directory search and after that all loads have the same speed.
  • Pro Tip (learned from Koronis Rift): There were several files that had the same name but were not identical. These were color RAM saves. As the upper 4 bits of reading the color RAM are random, the files do not look identical, but any of them would do. Color RAM saves are files in the $D8+ range.
  • Some tapes or disks use illegal Windows characters like "<" in their filenames and tapclean won't write them. You can either try to patch the game (hard) or cheat and, after creating the T64, use a hex editor and change the directory there to get the correct character in PETSCII.
  • Some games check if you pressed Play or Rewind. You need to manually patch these out. Other games ask you to flip the tape over. Again, manual patch I'm afraid.
  • Some games (most of them disk based) really open files and get the bytes character by character themselves. An extended version that also captures these calls is already in my head.

Other sources for games

You can have a try with any game you find that only uses standard Kernal load vectors and prg files. In theory, most of the "Disk2Easyflash" games should work with this. A couple of IDE64 "fixes" will work as well as some versions created for .d81 disks.

The problem most often is the overachievement of the cracker using a "levelcrunch" or "IFFL" to save sacred diskspace. While the LOAD itself uses Kernal vectors to be compatible with IDE64 or JIFFYDOS or other devices, the tape buffer is used for an unpack routine so that diskspace is saved. Unfortunately, we are now competing for the same memory space. Ideally you need to find a different version of the game that is NOT using decrunch or remove the decrunch yourself - or put the loader somewhere else in memory. Just find a free place below $8000 and recompile.

For the future I am looking into SEQ files as well. REL files are out of scope for this tool - if I have a LOT of time in 2024, I might tackle a REL to CRT conversion to finally get good versions of Portal and Alter Ego (or an IDE64 bin to CRT conversion because there are good IDE64 versions of both games out there).

Code Review

Yes, I hacked my way through this. Did I mention that I am 57 and I did not program on a C64 for about 40 years? There are several things in the code that I think are pretty cool, others that can certainly improved. I am open to suggestions! I wanted to cram it into 512 bytes, but even when turning off all the "extras" I was two bytes short. You can still turn off some features when you assemble this even though you won't gain a lot.

The copy loop itself is not that efficient. (Partially) unrolled loops and indirect addressing might make it faster. But by using a simple self-modifying routine I can handle bank traversal better than with indirect addressing which fails when the next byte to copy would be in $A000 - so in $8000 in the next bank. The major optimization here would be if all files would align on $0X00 borders (which I was planning for in my own format), unfortunately you can NOT hack T64 into this because, well, the format is bonkers. Files NEED to live cosily byte to byte, otherwise the format is broken the second any tool wants to modify it. I wanted a general solution so T64 it is.

Also, I wanted bank detection to be totally automatic, but unfortunately reading $DE00 sometimes is not reliable. It was working most of the time and so I chased a white rabbit for a while. In the end I decided that the starting bank is not autodetected, but we have a binary for each starting bank (it's just those 4 that I can think off right now).

The source code has no hardcoded addresses so you can make it longer or shorter (it knows the $0x00 border the t64 image starts on) and you can move the loader part anywhere below $8000 (or the $C-$D range). If you turn off the color ram protection, it will save you a few bytes too. Feel free to optimize and squeeze out every single byte.

When you really don't remember how SBC works, writing short code that will take the 3-Byte-address inside the T64 and convert that into a 2-byte address aligned with $80-$9F and the correct bank is a real pain. Now that I understand it all again, I'm looking for any future application of that reborn knowledge.

License

Do whatever you want. Even commercially. It would be awfully nice if you let me know what you have done with this: boris@dreisechzig.net 

Resources and thank yous

Standing on the shoulders of giants, here are most of the resources (including source code) that helped me to get this going. Let me know if I forgot you. I have a light flu while I am writing this...

First and above all: Statmat (Youtube link) and his OneLoad collection that I made small contributions to over the past years and who was so kind to let me test his toolchain. Check out his new project that combines NFC cards with OneLoad on a C64!

C64 PRG to CRT converter (frank-buss.de)

Memory Map | Ultimate C64 Reference (pagetable.com) Michael Steil and me never met but I admire his work - even on cracking the original Xbox open.

Bergatrollet's Tech Blog – Welcome to the cave of knowledge Some excellent hints and tips and reviews related to hacking C64 programs.

Multiload64 - Commodore 64 - Lemon64 - Commodore 64 (Solo1870 kindly giving me hints and tips)

Multi load conversions for use with Magic Desk cartridge - Commodore 64 - Lemon64 - Commodore 64 (Hellboy73 kindly giving me hints and tips)

New Release: Magic Desk CRT Linker (make your own CRTs) - Commodore 64 - Lemon64 - Commodore 64 (Pugsy kindly modifying his tool chain with every dumb request I had)

[CSDb] - TapEx V2.0 by SLC (2023) (great tool to understand the structure of tapes, unfortunately current version will not retrieve the filenames...)

Compyx/t64fix: Tool to fix T64 tape image files (github.com) (Without this tool I would have trashed the whole effort)

msolajic/c64-uni-cart: Hardware design of Magic Desk and Ocean compatible cartridge for the Commodore 64 (github.com)

DDI Magic Cart (sys64738.net) (Lots of nice single load compilations for a Magic Card and lots of technical info).

Georg Rottensteiner - GR Games (georg-rottensteiner.de) Georgs C64Studio made me a programmer again! Thank you for this awesome IDE, even if I used less than 5% of it.

Das letzte Update dieses Artikels war am 26.2.2024