| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
(Ab)use of dummy accesses
For the next release of my "No more Secrets" doc i am preparing a chapter related to the dummy access which happen when the CPU performs an internal operation. Once again i am looking for some examples on how to (ab)use it :) I guess everyone knows "inc $d019" - but i am sure there is more than this. And not only with RMW instructions. So if you have anything in your mind - just drop it here!
here are some related notes which i pasted together. feel free to proofread and point out mistakes :) |
|
... 55 posts hidden. Click here to view all posts.... |
| |
tlr
Registered: Sep 2003 Posts: 1790 |
Quote: nice trick, but 3fff can be set to any byte in a 8 pixel wide area with another trick.
I assume you are refering to exploiting the difference in pipeline delay between changing the videomode and changing the fetched graphics data to be fetched?
That is a neat trick, but it is dependant on the type of VIC-II (old/new) and it takes more cycles per instance.
The inc $ffff trick is only 6 cycles per instance. |
| |
Hoogo
Registered: Jun 2002 Posts: 105 |
Dec $dc0d after a Timer A IRQ occurred would acknowledge that IRQ and stop further ones. But I don't see a good reason to do that. |
| |
Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Hoogo, perhaps when you no longer need that timer interrupt, f.e. as an exit strategy to move on to a new demo part?
Oswald, are you referring to the vertical border scrollers in Krestage? But aren't these 7 pixels wide?
CyberBrain, great idea! |
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
reminds me of a subtle bug i created long ago which made me pull my hair out. somehow i thought its a good idea to ACK the timer irq by
lda $dc0d
sta $dc0d
aaaargs |
| |
Oswald
Registered: Apr 2002 Posts: 5094 |
Quote: Hoogo, perhaps when you no longer need that timer interrupt, f.e. as an exit strategy to move on to a new demo part?
Oswald, are you referring to the vertical border scrollers in Krestage? But aren't these 7 pixels wide?
CyberBrain, great idea!
maybe 7,dont know :)
interesting it doesnt work on old vic ? why did they change it? why is it needed? interesting details here :) |
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
"They" didnt change it - its a sideeffect of how the signal propagation delays in the chip, and so it changed when they moved from one process to another. |
| |
lft
Registered: Jul 2007 Posts: 369 |
It is possible to start a REU transfer by writing to address $ff00, which is useful when you want to transfer to or from memory in the $d000-$dfff range. But sometimes you don't want to trash the byte at $ff00, so you end up starting the transfer like this:
lda $ff00
sta $ff00
However, it turns out you can use any RMW instruction:
inc $ff00
The dummy write causes the REU to immediately take over the bus, so the second write-request from the CPU doesn't reach the memory chips. The incremented value never gets written into RAM. Three cycles saved. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
woa, thats... unexpected (to me at least). nice! |
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
That’s certainly unexpected. So what happens during the last cycle, bus conflict? |
| |
lft
Registered: Jul 2007 Posts: 369 |
The 6502 has two inputs, /RDY (Ready) and /AEC (Address Enable Control). RDY tells the CPU to pause execution, but it is only obeyed during read cycles. AEC immediately disconnects the CPU from the buses (address, data, and the read/write signal).
The VIC chip has two outputs, BA (Bus Available) and AEC (Address Enable Control). During normal operation, VIC asserts AEC (which is connected to AEC on the CPU) on every other half-cycle in order to read e.g. font bits. It has to work immediately, i.e. asynchronously, because it needs to be fast enough for half-cycle operations.
When VIC needs to halt the CPU, it first pulls BA low for three cycles, to ensure that the CPU is on a read cycle. Then it asserts AEC in order to access memory on both half-cycles.
The expansion port has an output, BA, and an input, /DMA. BA comes from the VIC. But /DMA is connected to both /RDY and /AEC. That is, it tells the CPU to pause, but it also immediately disconnects the CPU from the buses.
The REU monitors BA so it can pause an ongoing transfer during badlines and sprite fetches. But otherwise, it pulls /DMA and just assumes that the bus is free. The engineers must have assumed (wrongly) that the CPU will always trigger a transfer on the last cycle of an instruction, so that the next cycle is guaranteed to be a read (to fetch the next instruction).
Instead, due to the double-write of our RMW instruction, part of the CPU will attempt to place an address and data value on the buses, and set the read/write line to write. But the CPU is disconnected from the buses because /DMA is held low, and therefore /AEC. The bits never reach the actual bus lines; they dissipate into a small amount of heat. |
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 - Next |