9 ms·
This also misses loop unrolling, combined with an assembly language version of "Duff's device" to be able to do an arbitrary number of transfers even if your lo
by MarkusWandel 4y ago
This also misses loop unrolling, combined with an assembly language version of "Duff's device" to be able to do an arbitrary number of transfers even if your loop is unrolled to, say, 8 transfers.
This stuff used to matter! I had an NCR5380 chip on an Amiga, simple, memory mapped I/O, no DMA or interrupts. To get a tape drive to stream (remember that?) the byte transfer loop really had to be tweaked. But once fully tweaked, "whoooooooosh" instead of "chugga chugga chugga".
And truly heroic programming techniques had to be employed on the C64 to do X/Y smooth scrolling games. Often a static part of the screen, conveniently displaying scores etc, existed to make it work - there was just enough bandwidth to do 80% of the screen, say, so you find an excuse to keep the rest of it static.
I kinda miss those days, and I kinda don't. I guess it was good to have experienced them.
- amelius 4y agoWe're now doing sort of the same tricks, but with power management on mobile devices.
- le-mark 4y agoCrypto mining with fpga was in the weeds down this path, or 100 Gbps signal processing. Two examples where low level stuff is still relevant, just not commodity and widely available like the 8 bit micros were.
- aerique 4y agoI also read a high frequency trading blog that was posted here a few years ago. Same thing: hacking hardware and software so the first bytes of info could be grabbed from a stream and acted upon, instead of needing to wait for the whole package to have come in. Also when I was in the demo scene on the Atari ST one had to do specific timings in the assembly code to be able to draw outside the screen's borders (so the borders were on screen but couldn't be drawn on by code).
- Psyladine 4y ago>I kinda miss those days, and I kinda don't. I guess it was good to have experienced them. There's a certain reflective quality and even satisfaction from using a chainsaw after coming up using a tree saw by hand. It feels progressive, even if it is just optimizing for time at the expense of energy.
- vidarh 4y agoMost C64 games used character-based graphics (coupled with the smooth scrolling support in the VIC) which meant you'd at most move 2000 bytes to scroll the entire screen every 4 to 8 pixels scrolled. You can easily scroll the entire screen on a C64 if that's all you're doing. Some games did also scroll bitmaps. There the naive version requires moving 9000 bytes (40x25x8 for the bitmap data, 40x25 for the colour data) every time you need to scroll, and that indeed starts to bite. There are games which reduces the cost this using a trick called AGSP ("Any Given Screen Position"). But you're right static parts of the screen were often larger to reduce the dynamic part. That was rarely down to just scrolling the screen in isolation, though, but because the overall budget of cycles you had to work with was tiny. Often you might also have a lot of other stuff which consumed lots of cycles affected directly by the size of the playing field. E.g. if you did sprite multiplexing (moving a sprite after it had been partially or fully rendered to reuse the same hardware sprite), you might well be keeping the CPU busy throughout the full rendering of the playing field. There was also the consideration of how much effort you wanted to go to in order to avoid glitches, since unless you could do the scrolling entirely while the VIC was rendering the parts of the screen outside the playing field, you'd need to make sure the rendering and copying didn't overlap, and of course just restricting playing field size was an easy workaround for that problem.
- MarkusWandel 4y agoI didn't get that fancy. I got as far as a horizontal smooth scroller, but with the "move the screen memory during one 1/60 second redraw cycle" mentality - racing the redraw, and when it was just about caught up, whoa, time for the static bar at the bottom. Quite right, one could prepare the moved version in the background during the 7 steps where you're merely diddling the smooth scroll register, and then flip to it in an instant. But wait, was it possible to page flip the colour map? Also, always having the appropriate moved version ready even as the player is doing unpredictable things goes into the "heroic programming techniques" zone again. As for glitches, it's amazing what can be done if perfection is sacrificed and there were plenty of good games that did have them, e.g. sprite multiplexing. But I did mean "effortless looking perfect" smooth scrolling.
- 4y ago
- js2 4y ago> This also misses loop unrolling. It's mentioned at the bottom of the article in the "Thoughts" section: You could certainly use self modifying code and unroll this copy routine to get better performance at the price of flexibility and arguably understanding for the average casual 6502 assembly coder. Again, this was not a "how fast can we absolutely make it" but an everyday use examination.
- hinkley 4y agoDuff's device is a fixed size loop unrolling with an ugly hack to make it behave for arbitrary inputs. The assembly makes sense but the C code is rough. It's not quite as fast as self-modifying or custom compiled code, but it's pretty close.
- tialaramex 4y agoTom Duff's device was doing that because he's doing MMIO, you should not [I know you're not suggesting it, but just in case anybody reading thinks it's clever] do this today when you don't want MMIO, your compiler is very capable of just doing an actual copy quickly, so tell it that's what you want, don't write gymnastics like Duff's device. However, expressing these partially unrolled loops nicely is a nice performance-not-safety feature of WUFFS called "Iterate loops": https://github.com/google/wuffs/blob/main/doc/note/iterate-loops.md https://github.com/google/wuffs/blob/main/doc/note/iterate-l... Well, I say performance not safety, as always they want both, but you could safely just write the never unrolled case, while the existence of Iterate loops allows you to express a much faster special case but know the compiler will fix things up properly no matter what.
- vardump 4y agoWe're talking about C64 (and maybe Amiga). Compiler is not going to do absolutely anything for you on those retro platforms.
- tialaramex 4y agoAw, just needs a better compiler (with a 6502 target) :D Jason Turner's CppCon 2021 talk, "Your New Mental Model of constexpr" has half the presentation as a C64 program (though for practical reasons not actually running on a C64 but instead an emulator) because most of the heavy lifting is done by the C++ 20 compiler. https://youtu.be/MdrfPSUtMVM?t=1422 https://youtu.be/MdrfPSUtMVM?t=1422 Now, Jason's approach is not going to beat hand-crafted 6502 machine code in a fair fight but he often doesn't need to fight fair and that's the point of his talk.
- localhost 4y agoThe C64 VIC-II chip would grab the address bus from the CPU every 8 scan lines on the screen. Some of the early "fast load" cartridges like the Epyx FastLoad cartridge that would accelerate loading games from the floppy drive would blank the entire screen during load so that their async data transfer routines wouldn't get interrupted by the VIC-II chip grabbing the bus. I wrote a similar (better?) cartridge where I would need to use the register on the VIC-II chip that reported the scan line as a sync marker to transfer 3 bytes asynchronously from the 1541 down the clock and data lines of the serial bus. Good times.
- MarkusWandel 4y agoIn my recollection Epyx Fastload did not blank the screen, though some earlier fast loaders did. I also remember the software voice synthesizer "SAM" needing to blank the screen to render glitch-free sampled audio. Then along came, what was it "Impossible Mission" ("Another visitor! Stay a while...") doing pretty clean sampled audio with the screen on. Not that the C64 SID chip was even remotely intended to be able to play sampled audio in the first place! The Amiga was unimaginably powerful by comparison. Even a basic configuration had 8x the memory a C64 had, and it had all those fancy DMA toys to offload the CPU.
- jimsmart 4y ago> Not that the C64 SID chip was even remotely intended to be able to play sampled audio in the first place! I don't recall how SAM did it, but sample playing on the C64 SID chip was indeed a nice trick — it was actually done by modulating the main output volume, which made a slight click when changing. Eventually this got used by some of the C64 musicians / music player libs, so one could play a channel of samples as well as the three regular synth channels on the SID. IIRC, Outrun used this particularly well in its title screen and/or loading music, having some vocal samples "O-O-Outrun!" (and skidding sound effects) as well a sampled drums. Annoyingly, IIRC, some revisions of the SID chip behaved slightly differently, and had louder or softer sample playback when this hack was used. But still: clever stuff.
- 4y ago
- djmips 4y agoThose days still exist! If you want your mind blown watch the Epic Games Nanite talk from last year's SIGGRAPH where the core rendering of the dense vertex data is done directly in Compute , IE software rendered, instead of using the hardware rasterization hardware which has a minimum 4 pixel invocation overhead which gets expensive with very small triangles. This is but one example of this that's happening every day, there is much much more like hair rendering in EA FIFA soccer or automatic trading financial software running on GPUs. There's a whole world of applications where people are still concerned with every last cycle of performance just like in the C64 days.
- djmips 4y agoHere I'll save you the trouble of trying to find the video. https://www.youtube.com/watch?v=eviSykqSUUw&list=PLabw4gCouThkLIavA-dn4QDmJ_3tqH4LK https://www.youtube.com/watch?v=eviSykqSUUw&list=PLabw4gCouT...
- 6510 4y agoI eventually managed to do a scroll texts fast enough to do them while the pixels of the scroll text were printed to the screen. It was even fast enough to have char combinations in the scroll text that modified its speed and direction with speeds like "one time scroll 1 pixel the next 2". One of the tricks was to do "poor" timing with NOP's by requiring an empty row of bits between each scroll text. (The text becomes unreadable anyway if there is no space between the lines)
- djmips 4y agoKind of off topic for 6502 memory copy speeds but with regard to scrolling, there became a pretty cool software hack for the C64 (called VSP) where you could trick the poor VIC chip into starting scanning out the screen position later in memory. Move the start one character and the whole screen shifts left by 8 pixels. You only need to repaint a vertical column for this 'course' scroll instead of moving the entire screen of characters. This is something that should have been built into the hardware and was very useful on other systems that had that ability (like the NES for example) With it you can reduce the amount of memory you need to copy every 8 pixels (the 8 pixel part can be done with smooth scroll registers). There's a thread and example code on github here. https://www.lemon64.com/forum/viewtopic.php?t=70539 https://www.lemon64.com/forum/viewtopic.php?t=70539 Also note it's such a terrible hack on the DRAM that it doesn't work on all C64s and there's a technical discussion about that here. https://www.linusakesson.net/scene/safevsp/index.php https://www.linusakesson.net/scene/safevsp/index.php Hardware mod if VSP doesn't work on your C64 and more technical details. http://wiki.icomp.de/wiki/VSP-Fix http://wiki.icomp.de/wiki/VSP-Fix Also it makes mention of the C64-Reloaded which is a modern C64 product that includes the fix.