For quite some time I haven’t been very motivated to make anything new. I guess that’s partly because of my busy job and partly because of the times we are living in.
However, having seen a few variations of Big Clive‘s “super computer” prop in his live streams, I decided to come up with my own design: a micro-controller based device, using components I have in stock and originally meant to be used to build Tiny C2N Monitor devices.
Having recently received the PCB from its manufacturer, this evening I assembled one of the devices.
Here’s what it looks like:
The one pictured on the right is one of two working modes, which resembles Russell’s mini supercomputer: it uses a single timer and its flashing “virtual LEDs” drift apart, despite of the fact they start from the same state, which is the characteristic of the original prop. The other working mode is slightly less visually appealing but quite neat from a programming perspective: I will publish an update to show it later on.
Worthy of note is that I finally designed a device that takes power from a micro-USB connection. In fact, I managed to acquire a few through-hole USB sockets. However, the drawback with this model is that its feet are not long enough to go through the whole depth of a standard 1.6 mm PCB. The socket feels stable after being soldered to the PCB, but I will probably also solder it further on the top side, to improve its resilience to mechanical stress.
Also worthy of note is the chunky old school ISP connector for the in-circuit re-programming the micro-controller. I have had this type of connector in my DC2N stock for years and my ISP programmer uses the 10-pin interface, so I thought: why not go for the retro looks? And I did 🙂
All in all, this is a project that was fun to design, build and program but has no real practical use other than being visually appealing.
A few days back Diestro left a comment for one of my blog posts and we had an email exchange afterwards. Among other interesting things, he made me notice that Ocean’s “Space Gun” cartridge is really just a 128 KiB one. In fact, the upper half of the binary data in all CRT files I was able to find on the Internet is just filled with zeros.
For testing purposes, I removed the upper 128 KiB from a BIN file extracted using VICE’s cartconv tool and re-created the CRT file from the shortened BIN file. Obviously the resulting CRT file works just fine, although I’d be looking at a more comprehensive way to test cartridges in general, extracting the snippets of code that deal with bank switching (specifically, write access to $DE00 in the case of Ocean cartridges).
This fact is now reflected in the dumping definitions for the C64 Cartridge Dumper that I publish in GitHub here.
Another curiosity Diestro pointed out is that the bank switching code in “Robocop 2” always sets the MSb of the bank selection value, before storing such value at $DE00. This fact is also mentioned in the CRT format documentation that’s part of the CCS64 emulator:
Bank switching is done by writing to $DE00. The lower six bits give the bank number (ranging from 0-63). Bit 8 in this selection word is always set.
However, according to the schematics, the MSb of the data bus is only connected to the data port of the external memory chip, so it’s in no way involved in any bank selection logic within the cartridge itself.
As soon as I get a chance to write a piece on the Commodore 64 PLA, I shall add a bonus section on cartridges to the book I am writing, so that readers will have a self-contained reference for the preservation of Commodore 64 cartridges along with those for tapes and disks.
I am sharing an initial experimental build for Mac OS X of one of my GTK+ applications, C64 Raster Effect Editor.
It comes as a DMG file but it appears that install_name_tool, which I use to bundle the application and its dependencies, corrupts one of the dependencies thus impairing the creation of GdkPixbuf from XPM data at execution time. In fact, before GTK+ libraries go through install_name_tool, everything is working as expected, including the creation of GdkPixbuf. Unfortunately this means that PETSCII artwork cannot be loaded into the application.
Today I finally managed to assemble one of the new C64 Cartridge Dumper devices I had re-designed a while back to use a Pro-Micro. I had the PCB manufactured weeks ago, but due to job-related commitments I never got around to building one of the new devices.
Well, the good news is that I tested the device with what I understand to be an Ultimax cartridge, Jupyter Lander, and it worked fine. In fact, I was nervous about the fact that the data bus wiring is a bit awkward:
Bit 0 is PD3
Bit 1 is PD2
Bit 2 is PD1
Bit 3 id PD0
Bit 4 is PD4
Bit 5 is PD7
Bit 6 is PB4
Bit 7 is PB5
As you can appreciate, an 8-bit value read from the data bus has to be read from two different ports (PORT D and Port B) and bit values have to be shifted into position. A similar wrangling has to occur when writing a value to the data bus, for bank switching purposes.
The reason I went with a more complicated firmware, compared to the breadboard prototype I had used to develop the firmware, is that the PCB routing is much simpler 🙂
The next thing I did was to check whether using a 5V MCU instead of a 3.3V one makes any difference when driving the bank switching circuitry for gmod2 cartridges. Luckily, Andy had lent me his copy of “It’s Magic II” a while back, so I have material to test.
I was indeed able to appreciate that bank switching appears to be behaving differently with the new hardware. Here’s a comparative image, with the left side showing a bank switching taking place correctly at dumping time with the new hardware, while the right side shows a previous attempt:
The bank switching logic doesn’t yet seem to be correctly driven though, as dump contents repeat at $4000.
I am starting to think that the bank switching hardware in gmod2 might require a signal edge on the Phi2 line to trigger, where I just pull it up with a resistor. I’ll try to hack my own circuit to e.g. route IO2 to the Phi2 line and cause an edge that way. If that works for gmod2, in general I would just need a NOR port to combine IO1 and IO2 on the inputs and use its output to simulate Phi2.
Of course, if anyone knows the bank switching details for gmod2, I’d be happy to read what they have to say 🙂
We know that when either 8KiB or 16KiB of external EPROM/EEPROM are provided by a Normal or Ultimax cartridge, the Commodore 64 can map each 8KiB segment to one of the memory ranges $8000-$9FFF, $A000-$BFFF, or $E000-$FFFF. Not just any combination is allowed, but what’s really important is that the Commodore 64 can only map one 8KiB segment of external memory to $8000, $A000, or $E000, and it can only map a 16KiB segment of external memory to base address $8000.
You might want to refer to this post on World of Jani for the values of /GAME and /EXROM used by Normal and Ultimax cartridges. The Commodore 64 Programmer’s Reference guide also provides a table with relevant information.
Here’s a summary:
/EXROM = 5V and /GAME = GND (Ultimax mode)
/ROML optionally enables the mapping of 8KiB to $8000 and /ROMH enables the mapping of 8KiB to $E000
/EXROM = GND and /GAME = 5V
/ROML enables the mapping of 8KiB to $8000
/EXROM = GND and /GAME = GND
/ROML enables the mapping of 8KiB to $8000 and /ROMH enables the mapping of 8KiB to $A000
Specifically, for a double-chip cartridge, /ROML is routed to the /CE and /OE pins of the first chip, and /ROMH to the /CE and /OE pins of the second chip. For a single-chip cartridge, /ROML and /ROMH are combined by an AND port (two diodes and a resistor) and routed to /CE and /OE, with /ROML also routed to A13.
A summary of the above mentioned table is also provided below:
LHGE LHGE LHGE LHGE LHGE
1111 1110 0100 1100 XX01
A000 ROMH ROMH -
8000 ROML ROML ROML
L = /LORAM
H = /HIRAM
G = /GAME
E = /EXROM
As for registers, bits 0 and 1 at location $1 on the Commodore 64 are mapped to the /LORAM and /HIRAM signal respectively and eventually affect the values of /ROML and /ROMH that are set by the PLA, based on the state of the address bus: I will cover this in more detail in a future post on the subject.
For an 8KiB block of memory, thirteen bits of addressing are required in order to select each byte in the block itself: this is the reason only address lines A0-A12 of the address bus are connected to the memory chip in a cartridge. In fact, we can’t connect the lines A14-A15 of the Commodore 64 address bus directly to the corresponding address lines of an external memory chip, because they would select addresses in the external memory chip that are not mapped to locations that the Commodore 64 can access, being these beyond the 16KiB limit. In reality even A13 is never connected because /ROML or /ROMH are used instead to drive the corresponding line of the external memory. So I hope it’s now clear why address lines A13-A15 are not used by cartridges.
The problem is: how do we allow a Commodore 64 to access external memory chips when these are larger than 16KiB? A good quality game with a lot of graphic elements and tunes would hardly fit in just 16KiB of memory. It’s more likely that a good quality multi-level game would require 200KiB or more. We could also be wanting to use two 128KiB memory chips, or one 256KiB chip, or even a 512KiB chip.
Fortunately, although we can only map one or two 8KiB sections of external memory chips at any given time, we do have options when it comes to driving lines A13 and above of the external chip (or chips) and selecting exactly the 8KiB block (or blocks) we want to map.
The fact that we have options means that different vendors came up with different schemes for exotic cartridges.
Let’s take Ocean, for example. Their strategy was simple: use the data bus to decide the state of the lines A13 and above for the memory chip (or chips) they mounted in their cartridges. Obviously the data bus is used for reading data out of the cartridge memory, so how can we use it to set the state of lines A13 and above? Well, as well as connecting data lines D0 and above to the memory chip for reading out its contents at a given location, the cartridge hardware also connected some of these lines to an 8-bit register (a.k.a. latch). Such register would sample and hold the value of data bus lines, presenting their state on its outputs directly connected to A13 and above, if and only if the Commodore 64 wanted to switch to a different memory bank. The Commodore 64, in the case of Ocean cartridges, uses D0 to set A13, D1 to set A14, and so on.
The next question to understand is then: how does a Commodore 64 communicate to an Ocean cartridge that it wants to perform a bank switching? Loading the data bus with the desired state of lines A13 and above is not enough; it would have to cause the latch to sample and hold. Well, looking at any Ocean cartridge circuitry, it’s pretty simple to establish that:
Phi2 has to be high, meaning that it’s the CPU that’s controlling the bus
/IO1 has to be low, meaning that the Commodore 64 is addressing a location in $DE00-$DEFF
So, in short, all the Commodore 64 has to do when it wants to switch bank is to set the value for A13 and above in bits 0 and above at e.g. $DE00; the hardware circuitry of the Commodore 64 will make sure that /IO1 is briefly pulled low at some point when Phi2 is also high. That’s exactly what the cartridge’s own circuitry is waiting for to sample and hold the value on the data bus and use it to set lines A13 and above.
This means that, as an example, for a single-chip 256KiB Ocean cartridge, we can map the bottom 8KiB to $8000 by setting $DE00 to 0. The 8KiB after these would be mapped by setting $DE00 to 1, and so on.
-- Ocean type B (single chip) dumping definition file
-- for the Commodore 64 Cartridge Dumper client
-- (C) 2019-2021 Luigi Di Fraia
-- Supported titles:
-- All Ocean titles excluding "Robocop 2" and "Shadow of the Beast"
-- Bank selection circuitry uses:
-- 128 KiB cartridges (all known titles): bits 0-3 at $DE00 and /ROML (single 128 KiB chip with A16 on pin 22, rather than the /OE signal)
-- 256 KiB cartridges (just "Chase H.Q. II"): bits 0-4 at $DE00 and /ROML (single 256 KiB chip)
-- 512 KiB cartridges (just "Terminator 2"): bits 0-5 at $DE00 and /ROML (single 512 KiB chip)
-- Calculate the number of 8 KiB banks to dump
local banks = size_kb / 8
local b = 0
-- Mapping is at $8000-$9FFF for all banks
while b < banks do
b = b + 1
I am still quite busy at work, but today I had a chance to finally commit my changes to TAPClean for supporting an Anirog loader clone found quite often in Polish tapes. The difference in encoding is that the clone uses a trailing sequence, where genuine Anirog doesn’t. From a loader code perspective, the two differ, but also have a few similarities:
exact same pulse threshold and use of timer,
similar handoff code to execute a BASIC program at the end of the load.
Back in November 2020, Adam approached me on SourceForge about a tape loader not recognized by TAPClean that was used by a Polish publisher in the 90s. Subsequently, he sent me a number of tapes from the same publisher and many others. For months I have put the task to add support in TAPClean aside, due to lack of free time, and asked Adam to keep reminding me on a regular basis, i.e. once a month.
Well, yesterday I finally decided to add support for what I refer to as “LK Avalon loader” to TAPClean.
I guess that if you have approached me with requests for TAPClean you already know this, but in case you haven’t, it might come handy: If I have no time to assist with a request, it’s best if you periodically approach me about it. As long as you are happy to wait, it might actually work out just fine 🙂
Having come back to proof-reading my book, after a few weeks since I last added content, I felt the need to clarify what “write splices” are for disk images, before referring to them in the chapter about Vorpal.
Therefore, I added a chapter on Disk image formats, track cycle detection, and the need of identifying write splices. This content is exclusive to the book, rather than being consolidated in the book from this blog, but I have been discussing those topics here in various posts.
I just published the first draft of my book on Leanpub. For those not familiar with Leanpub, one of the common book lifecycles involves frequent updates, all of which come at no further charge for those who buy the book.
What will you find in the first draft? Well, this is an initial attempt to get familiar with the publishing process on Leanpub. There is content found here on my blog, but also additional annotated code from Vorpal (later), specifically the code that is used to decode custom GCR bytes on-the-fly.
So, the publication is a starting point that gets me going and motivated. As a reader, please don’t feel like you are buying an unfinished work at full price: again, you will get all future updates for free, as and when they come.