To be clear, I'm talking about the actual memory cells at addresses $0000 and $0001 in the DRAM chips. Devices can of course initiate read or write requests to these address on the address/data buses to which they're connected, but that doesn't necessarily mean that this will result in an actual read from or write to the RAM device.

According to §4 of Christian Bauer's excellent VIC-II article, the CPU's data bus is tri-stated during a write access to the registers of the 6510's on-board PIO at addresses $0000 and $0001. (This is not mentioned in the 6510 data sheet.)

He says, however, that these memory locations can be written anyway though a mechanism that I don't really understand¹, involving the VIC-II actually doing the write.

He also says that, at least on some C64s, those locations in RAM can be read by the processor via reads in the $DE00 "I/O 1" area (presumably so long as a cartridge or whatever hasn't mapped some I/O devices in there) or via "sprite collisions."

So how exactly does this work? What devices (the 6510, the VIC-II, external devices you add yourself on the expansion bus, etc.) can read from and/or write to locations $0000 and $0001 in the RAM devices, and how exactly do they do it?

¹ It seems to be something to do with what goes on during φ1—the "VIC-II's phase" of RAM access—where the VIC-II has enabled RAM for its own purposes and R/W̅ is low, causing a write to happen anyway. But I don't see at all where the data come from, or why there would not be a re-write of random data to that location during φ2, when presumably nothing is driving the data bus. And I guess for this to work the VIC-II needs to be programmed to be using the first 16K block of memory? This is probably all wrong; I include this speculation just to give you an idea of where I am in my confusion.


1 Answer 1


Data lines hold their previous state if nothing drives them

Each trace on the motherboard has some tiny capacitance, depending on its length, routing, and distance from the ground plane. Each time there is some traffic on the data lines, the data lines D0-D7 are charged to high or depleted to low level, depending on the data put on them.

The VIC reads some data from memory on every φ1 half-cycle, no matter whether it needs to or not (when displaying the border). If nothing is driving the data bus during the φ2 half-cycle, this data remains on the data bus.

Writing to $00/$01

As you have noted, when the CPU executes an instruction to write to $00 or $01, the external data lines are not driven, so they hold their value (charge) from the previous VIC access. Although the CPU doesn't drive the data lines, it sets the address and control lines, going through all the motions to write some data without putting anything on the data bus. So the data that just happen to sit on the data bus from the previous access by the VIC gets written to memory.

If you can figure out which memory address would be accessed by the VIC just before the write by the CPU, and store some value there, that value gets copied to $00 or $01.

Reading from $00/$01 through the unmapped area

In a somewhat similar fashion, executing a read from anywhere between $DE00 and $DFFF would return whatever the VIC has read just before. I'm not sure that it can be arranged that the load instruction is executed exactly when the VIC reads from $0000, because it should happen on a bad line, when the CPU is stopped, but if there is a clever VIC timing trick to do it, then the CPU read would return the byte at $0000. However it's certainly possible to read $0001 this way.

Reading from $00/$01 through sprite collision

The bits in the VIC sprite collision register are set whenever there is a non-transparent pixel of the respective sprite at the same position as a non-background pixel of the main graphics plane.

Set the VIC to graphics mode, bitmap starting at $0000. Now the contents of $0000 and $0001 are displayed at the beginning of line 0 and 1, respectively. You can actually see the contents on the screen.

Let all sprites have an empty ($00) bitmap except byte 0. Set byte 0 of sprite 0 to $01, byte 0 of sprite 1 to $02, byte 0 of sprite 2 to $04, etc, i.e. sprite x has bit x of the first byte set. Display all of them at (0,0) and wait for the collision register to get updated. Bit x would be set, if the single pixel of sprite x collided with a pixel on the bitmap screen, effectively giving back the contents of $0000. Move the sprites down one pixel to get the value at $0001.

  • 1
    I think memory-expansion cartridges that use DMA could also access addresses 0 and 1 of RAM.
    – supercat
    Commented Sep 21, 2019 at 18:34
  • 4
    So, in principle, you could create a Spectre-like attack against the C64? That's fascinating.
    – Kevin
    Commented Sep 21, 2019 at 19:05
  • How about setting the screen to start at address $0000 and font memory to start at address $0800, and then storing the values i=0 to 255 to address $0801+i*8? The first shape data fetch for the second displayed scan line should yield the value that was fetched from address 0 on the bad line.
    – supercat
    Commented Nov 4, 2020 at 17:36
  • @Kevin: What's more interesting is the fact that the Apple II+ doesn't provide any way of determining the location of the raster, but some programs manage to synchronize with the beam anyhow by watching idle bus data. If while text mode is active, code does an idle bus read and stores the results every 8 cycles for a scan line (nine times total), then modifies the data at e.g. $478-$47F, and then, starting 130 cycles after the first set of stores, does idle bus reads, comparisons (using patched immediate-mode operands), and branches on inequality, the branch can only hit if...
    – supercat
    Commented Nov 4, 2020 at 17:40
  • ...the raster just advanced past a multiple-of-eight scan line, or those addresses were fetched but not displayed [they're never displayed] for the current text line. If repeating the procedure results in another "hit", that would imply that the change must have occurred as a result of modifying $478-$47F. If a different value was stored at each such address, one could determine a cycle-accurate raster-beam location.
    – supercat
    Commented Nov 4, 2020 at 17:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .