8

Considering the ZX Spectrum, part of the memory is accessible to both the ULA and the CPU, and the CPU is slowed down when it is using that area, so that the framebuffer can be read out. As I understand, some Amigas also have a region of memory which slows the CPU down when the CPU reads/writes to it, because it is connected not only to the CPU, but also to the video/sound/etc.

But it's occurred to me, that the vast majority of interaction with the framebuffer on these systems will be to write something. Only rarely will it be necessary to read from the framebuffer. So it seems to me, that whenever the ZX Spectrum wrote a byte to the 8 KB containing the display file, instead of slowing the CPU down to allow that to happen, the value and the address could have been latched, and the write to the memory could happen later on -- say, when the Z80 is fetching the next instruction. It should be possible so long as the video memory is on a separate bus from the rest of memory. (Of course, it would require a little extra circuitry, and would possibly preclude being able to execute code from this region, but it's probably worth doing, right?).

So what's with this design decision? The ZX Spectrum, the Amiga, the Commodore 64, all slow the CPU down so that the video can be read! Did any retrocomputing system buffer the write so as to let the CPU run at full speed whenever it's not reading from the framebuffer (which is practically always)?

9
  • I'm curious about a variant of this - interleaved/banked DRAM and two busses, so the slowdown is only necessary when the video readout and the CPU access the same bank. Shouldn't need that much extra logic. Of course programs with cycle-exact timing on this would have been a PITA. And DRAM refresh still needs to be taken into account. Maybe I should make that a question, but I don't think that model was ever used...
    – dirkt
    Sep 20, 2018 at 12:39
  • @dirkt AFAIK that's already the case with a 48KiB Spectrum due its two banks, and only the first (16 KiB) is also used by video. IIRC, there wasalready a question about the way the Spectrum does video access, highlighting the mechanics.
    – Raffzahn
    Sep 20, 2018 at 13:42
  • @Raffzahn do you mean this one? retrocomputing.stackexchange.com/questions/7133/… Sep 20, 2018 at 13:44
  • @Wilson Nope, there was another one, more specific about the sharing scheme. I remember having looked at the schematics for that. Somehow I fail to come up with the right keywords for searching - and there are already way too many questions (and answers) on RC to just browse. We should stop adding more.
    – Raffzahn
    Sep 20, 2018 at 13:55
  • 1
    The very first assumption of 'usually VRAM is only written to' is actually wrong: ZX Spectrum, Commodore 64, Amiga 500 (to name a few) all massively execute code from VRAM (i.e. from the RAM also used for video display fetches). Otherwise you are right, if we gonna only write to VRAM by CPU (meaning relatively infrequently in comparison with video fetches), those writes could be done waitless for the CPU most of time.
    – lvd
    Sep 20, 2018 at 15:55

7 Answers 7

16

So what's with this design decision?

Not as helpful as it looks on first sight.

For one, it does need at least three chips for latching the data (8 Bit Data and 11 to 16 bit address) plus a considerable number to handle the access whenever there is time, plus a some muxes to switch the busses, as the CPU still needs the ability for read data from screen memory. Quite a lot of pins to solder (and pay for).

Second, the gain is rather meager. It's only a single (write) access that gets buffered. As soon as there is a second (before the screen memory can be accessed again), the CPU gets halted … as without. Equally important, the CPU gets also still put on hold for a read access.

Timing

A Line

To validate this it helps to take a look at (average) screen timing. Lets assume a system where the video part needs the whole RAM bandwidth during display (or at least so much that there can't be any CPU access in between). During a picture this is only true while a scan line is displayed. Lets stay with 1980s TV sized picture. Here a line is defined as 64 (63,6 for NTSC) µs. Thereof 12 (10.9) µs are used for synchronisation purpose and 52 (52,7) µs are for a potentially visible signal. Let's just assume the VDC uses all of that.

52 µs is quite some time in a CPU life – and especially more than enough to attempt to write more than one byte to screen memory. On a 1 MHz 6502 that equals up to 6–8 sequential writes in a tight copy loop. A 4 MHz Z80 can as well do up to 9 writes during that time (Let's for simplicity assume it tales 10µs per single meaningful write). That's about the maximum. And it'll of course overrun the single transaction buffer. To really use it some FIFO for address and data is needed. Increasing cost again.

Of course even a FIFO would only postpone the access into the gap between lines. Then again, a memory good enough for either of these CPUs will be able to squeeze a good 20 write access into the line retrace. So yes, such a FIFO could resolve it and give the CPU seemingly unhindered access. As noted, that's only true as there is no intermediate read access, which would halt the CPU again. So no bitblit please. Not to mention that there needs to be some priority logic to maybe let a waiting read slip in at the beginning of a line gap before the buffered writes are done, so the CPU only needs to wait for a minimum … err … no, bad idea, as it would possibly deliver old, already changed data, which has just not been committed by now. Drats.

The Whole Picture

A picture isn't just lines, but also frame structure. There are 286 (243) visible lines for a total of 18.3 (15.5) ms within a 20 (16.6) ms frame (50/60 Hz). With our model CPUs that allows for a maximum of ~170 (110) bytes written outside the visible part. In addition two writes per line can be done (*1), adding it up to 456 (353) accesses per frame or 22.8 (21.2) KiB/s (*2).

Adding a single access buffer to this would increase this by ~62 (68) percent to 37.1 (35.7) KiB/s. Sounds not bad. A 10 entry FIFO will even get it up to close to full speed (something like 100 KiB/s). Even better, isn't it? Except, this will break down quite hard if the job is not just a tight copy loop, but maybe some bitblitting with decisions and transformations in between.

So, What to do Instead?

Full Interleave

As long as the timing requirement isn't too tight (as in 'already using the fastest RAM affordable'), it's better to avoid a collision at all by using RAM with a bandwidth of double what's needed for screen refresh (or CPU, whatever is higher), so the CPU can access it with no (or little) speed penalty. Something very common on 6502 systems, where RAM anyway has to be twice as fast as the CPU. Now there are no additional cost for perfect access.

On the backside, this requires RAMs always being double the speed, even when not needed (during retrace).

Only Partial Take Over

The C64s VIC shows an in between solution, by mostly acting when the CPU isn't accessing the RAM and only stoping it when it needs additional bandwidth.

Just Live With It

As seen in the whole picture calculation, while we are talking about a 60+ percent speed up in tight loops, it is in absolute numbers still a meager transfer rate. A lot of Hardware to gain a little.

Better Improve the Rest

Instead of spending a handful of TTLs on a little and often not reached gain, using the same amount of gates for a more capable VDC could be way more rewarding. Building a (very simple) DMA copy circuit can move like a 5 to 10-fold amount per time than the CPU can do (*3). Adding a full DMA controller to the system might cost even less. Then again, with a specific circuit additional benefits are possible – like bitblitting and so on.

Did any retrocomputing system buffer the write so as to let the CPU run at full speed whenever it's not reading from the framebuffer (which is practically always)?

Leaving the interleave/partial blocking systems apart, there are all machines using a 9918. It does buffer one transaction and a 3.5 MHz Z80 could access it (virtually) without being stopped (*4). Similar systems that used a second CPU for I/O had that advantage. Though, not many where made.


*1 – Thats one lovely part – and crucial to memorize: Any access done during a line will stop the CPU (in basic configuration), and release it one memory cycle after the end of the line. Giving the lock the whole 12 (10.9) µs for another interaction, which can be done in a tight loop, making the next write happen instantly and then putting the CPU on hold again. So as soon as the horizontal retrace is longer than one loop iteration plus one memory cycle, always two will fit – already creating parallel action for up to 2/6th of a line.

*2 – Here also lies one major reason why early computers had to use tile graphics and sprites (besides not enough RAM): not enough bandwidth. A CPU of that kind can not move even in a tight loop more than about ~2 KiB per frame – without being halted that is. Not enough to brute force an acceptable frame rate. Using tiles and sprites reduced the amount to (maybe) less than an 1/8th, making it possible again to sustain a good frame rate (still needing a good tile design :))

*3 – No, using a Z80 LDIR is not the same as DMA. It takes 21 cycles to move a byte. With two cycles per memory access, DMA can do the same in merely 4 cycles.

*4 – Calculation is a bit complex here, as for one the 9918 has a basic access time of 2 µs plus 0–6 µs wait, depending on internal action (frame or line) and within a line on what graphics mode is used. With a Z80 and LDIR as (a fast) use case, this comes down to a maximum effective CPU clock of 2–10 MHz depending on when the access happens. For all practical matters a 3.5 MHz Z80 can write to a 9918s screen memory virtually without being slowed down.

9
  • 4
    there was also another solution ... using Dual port RAM chips ... but IIRC those come up much latter and where expensive
    – Spektre
    Sep 20, 2018 at 11:54
  • 2
    @Spektre That would be (more generalized) any kind of dual port RAM. But they always have been - and still are - expensive. In fact, for this video aplication a perfect RAM 'only' needs one write and two read ports. As Video does not write. This woudl help a lot with synchronisation. Maybe only adding a wait state when writing exactly the location that is accessed at the same time. In an FPGA implementation that would be the way to go. For single chips way too expensive.
    – Raffzahn
    Sep 20, 2018 at 11:58
  • 1
    I agree double speed RAM will be much cheaper and more available than DPRAM ... and the needed change would not be as big especially if modern ULA is an FPGA ... I just wanted to point that out there exist DPRAM which are used in nowadays gfx cards and are perfect for this apart the cost ...
    – Spektre
    Sep 20, 2018 at 12:00
  • A simple approach for handling reads would simply be to have a portion of the CPU's memory shadow the same address space as the video buffer, so that a write will be sent immediately to the CPU memory and also to the FIFO, while a read will be served from the CPU memory. A 16x4 FIFO is a standard chip, so using six of those to handle up to 64KB of screen storage (four for address; two for data) wouldn't seem too horrible.
    – supercat
    Sep 22, 2018 at 23:39
  • 1
    @Raffzahn: Was that the price for the TTL 16x4 ones? I never used the TI's Extended BASIC, but it's built-in BASIC was a dog.
    – supercat
    Apr 9, 2019 at 17:46
9

Re: did any computer use this scheme, which I think is still unanswered; yes: several.

The TMS9818[/a] was used by the TI99/4[/a], MSX, ColecoVision, and many more. It doesn't share RAM with the CPU, it has its own. The CPU isn't synchronised to the TMS's memory windows when it wants to read or write, it writes to (or reads from) a latch that is written to (/read from) video memory whenever there is next a spare slot to do so.

The problem is that the access slots are far enough apart that you can't write to the latch at full speed or you'll start overwriting values that haven't been written yet. If you speed up the RAM so that slots were always available, you might as well eliminate the latch.

That being said, the chip has a diverse family tree, at least some of which block on write only if the latch is full; that's an effective strategy but starting to get a little electronically complicated for a machine of the Spectrum and C64 vintage.

8
  • The TMS9918 runs at 5.4MHz, and guarantees CPU access at least once per 32 cycles (or once per 6 cycles if in text mode). For a 4MHz Z80, you don't have to do much between memory accesses for that not to be a problem. It's also somewhat better than the Spectrum manages. :)
    – Jules
    Sep 20, 2018 at 12:37
  • @Jules Keep in mind, the access is only about Video. Even with an LDIR, video access would be only once per 21 cycles on a Z80. which would make it perfect for a 3.5 MHz Z80 without adding any wait cycle. ((5.4 MHz / 32 cycles worst case) * 21 cycles per LDIR) = 3,5475 MHz Looks like a nice number for such a system, doesn't it :))
    – Raffzahn
    Sep 20, 2018 at 13:18
  • @Raffzahn - Interestingly, this page calculates 21.3 cycles for a 3.58MHz MSX, but then suggests there are somewhere between 5 and 9 "CPU-access wait cycles" that must also be allowed for between accesses. It's unclear whether this is an MSX-specific delay, or where it comes from exactly.
    – Jules
    Sep 21, 2018 at 9:16
  • 1
    .. Ah, I've found it. It's in section 2.1.5 of the TMS9918 datasheet, which on skimming I'd assumed only applied to reads, but it seems also applies to writes ... there's a 2us delay before a write command can be accepted, which translates to 7.2 CPU cycles. I think the 5-9 range from the linked document is based on the assumption that 2us is rounded to 1sf, but as other figures in the same section have 2sf I assume it is actually 2.0us. This correlates with advice I see elsewhere suggesting 29 cycles being correct for an MSX.
    – Jules
    Sep 21, 2018 at 11:48
  • 1
    @Tommy Ah. ok, thanks, that abrevation is new to me. Now I'm able to write even more cryptic posts :)) (Serious, I couldn't figure it out. Pointing this out is helpful to me).
    – Raffzahn
    Sep 24, 2018 at 15:48
7

Ultimately these computers were designed with price as a primary design goal, rather than squeezing the absolute maximum performance possible.

First you'd have to separate the video memory. The screen is 7k, not 8k, and the Spectrum uses a 16+32 configuration of RAM chips. So you'd have to go to 8+8+32. That alone would probably make this idea a non-starter as you're adding 8 more chips and their routing to the board area. And it "wastes" about a kilobyte.

Then you'd have to do the write buffering somewhere. Maybe within the ULA, but if not you're adding yet more chips to the board.

(The Amiga does make this distinction for addon memory between "chip" and "fast": What is the benefit of increasing Amiga chip memory? )

6

Did any retrocomputing system buffer the write so as to let the CPU run at full speed whenever it's not reading from the framebuffer (which is practically always)?

Yes, the Inves Spectrum +. A clone made by Investronica, which departs from the classical arrangement of two memory banks, one contended, one not. In the Inves, there is a single memory bank (64KBytes, although the hardware didn't allow accessing the portion of RAM that shares space with ROM).

The Inves uses a gate array from Texas Instruments, a TAHC10, but not all the functions that were in the oriignal Ferranti ULA were taken to the TAHC. Keyboard and EAR reading, for example, were perfomed off chip by discrete TTLs.

Having only one bank of RAM, Inves designers had to come to a solution to maximize software compatibility, by having non contended memory. The solution was very similar to what you have described.

I had the chance to deep analyze one of these clones, and this is the block diagram I made of it:

enter image description here

RAM is directly connected to the gate array. Between RAM and CPU there is a latch and a buffer. The buffer allows transparently passing data from the Z80 to the RAM during writes. The latch stores a byte read on behalf of the CPU so it can access it a bit later.

The sharing mechanism is kinda interleaving access. The TAHC is always making read cycles with a tRC of 281ns (one CPU cycle). In other words, RAM is being read at 3.546 MHz.

When the TAHC wants to read from video RAM, the read cycle uses the multiplexed address supplied directly by the TAHC (VA). If the CPU is not demanding memory access, the TAHC performs two identical read cycles with the same address so the same data is present in the data bus (VD).

But if the CPU needs to read or write to memory, one of these access (may the first or the second) is lent to it: the TAHC disconnects itself from the VA bus and enables the MUX so the CPU address from A is multiplexed and outputted to VA. If the operation is a read one, the byte read is latched into LATCH. If the operation is a write one, the TAHC doesn't wait for the WR signal from the CPU to go active, but it generates its own /WE signal to the RAM while the BUFFER is opened so the data to write comes from D to VD. Write and read operations last one CPU cycle (from the point of view of the RAM). As read operations actually take longer for the CPU, the latch ensures the CPU to get its required data at the end of its memory read cycle.

The actual schematic of the bus management described above is this: enter image description here

Note that the WR signal from the CPU is not used at all. The TAHC infers a memory write operation if it detects /MREQ active, but /RD not active, and the last cycle is not a /M1 memory cycle. This way, it doesn't have to wait until /WR goes active, which is way much later, almost at the end of the write cycle. This behaviour, unfortunately, was not adecuately implemented for an INTA cycle, in which there is a M1 cycle, but not with /MREQ but with /IORQ. This causes the RFSH cycle following it to be misinterpreted as a memory write operation, causing corruption in RAM memory space if I register is set to a value greater than 63 (see https://www.youtube.com/watch?v=HiNAs0sQbI4 )

A much more deeper description is available at http://www.zxprojects.com/inves/ That is the complete article I wrote about the internals of the Inves Spectrum some time ago. It's in spanish, but I think Google Translate can do a decent job.

2

In addition to pjc50's answer (i.e. that performance simply wasn't a high priority design goal for these systems), there are more things to consider, at least for the Spectrum:

  • A cheaper way of increasing performance would have simply to have used the full performance of the CPU: the Spectrum ran at 3.5MHz but its processor is rated for 4MHz. The modifications to allow this would have increased complexity, but would have done so less than the modification outlined in pjc50's answer to allow for separate framebuffer access. This would have made a much larger improvement for lower cost.

  • Another simpler improvement would have been to use slightly faster memory and a small readahead buffer. The Spectrum used 200ns memory, but if it had used 150ns memory it would have been able to squeeze all of its screen access operations into the gaps between Z80 memory accesses, allowing the CPU to run unimpeded. It wouldn't be able to guarantee getting framebuffer data at exactly the right time, though, so it would have had to buffer a handful of bytes ahead in an internal buffer. This would have had a minimal cost increase to the memory and only a small complexity increase in the ULA (I don't know how much of the available capacity of the ULA was used, so that may or may not have resulted in a cost increase for producing them).

  • And, at the end of the day, the 48K spectrum had 2/3 of its memory that didn't have the penalty on access anyway, so performance critical applications could simply use that memory and avoid it (and perform display updates during the retrace interval). The 16K model only existed as a concession to the budget end of the market, and its performance was therefore a lot less critical.

3
  • All of those things would again have increased cost though. They tended to use B-grade parts in order to get them for the rock bottom wholesale price (it may only be legend, but apparently the 16K chips were all "half broken" 32Ks wired to only use the working half), so underclocking everything was somewhat necessary to ensure reliability. Also, like most old computers, the pixel clock was tied to the rest of the system; increasing that would mean changing the whole screen structure, and probably increasing resolution to lessen the "windowbox" effect. It'd have likely counterbalanced...
    – tahrey
    Oct 27, 2019 at 22:39
  • IE once the need for the extra screen memory and per-line bandwidth is considered, as well as rejecting more marginal parts, it'd have been a zero sum outcome for performance, or at least performance per pound, and Sinclair's aim was the absolute cheapest computer meeting certain goals; in the case of the Spectrum, being a ZX81 (also running at 3.5MHz, with 32x24 text), but with lowercase, colour, sound, and more internal memory. Similarly the RAM speed was neither here nor there. 200ns is more than enough for 5MHz, let alone 3.5; they were just the cheapest chips. 150ns is Amiga/ST grade.
    – tahrey
    Oct 27, 2019 at 22:41
  • In fact, even the IBM PC used 200 (250?) ns parts. Sinclair could have used much slower memory (300ns or more) and pushed against the specs somewhat, which was a common tactic used by a lot of manufacturers... likely, the 200ns "half broken" chips were the cheapest, and offered sufficient overhead "just in case" whatever fault knocked out the unused half also affected the speed of the "working" half. Using faster stuff and prebuffering it may have worked, but it'd be way too complex for a machine of its type. Anyway, like you say, they already had performance stratification - the 16K vs 48K.
    – tahrey
    Oct 27, 2019 at 22:44
0

You seem to assume a single latch could suffice buffering video memory writes from the CPU while the RAM is busy shifting out bits to the DAC.

That would assume that a single CPU instruction is only capable of pushing out a single byte to video RAM - but this is not the case: 16-bit accesses (which you could buffer with two latches) or even more complex instructions like LDIR (that would need way more buffers) on a Z80 transfer lots more bytes in a single instruction fetch. In order to catch these, you would need more buffers, actually a second video RAM - This ends up in an actual component, dual-ported memory, that you can actually buy, albeit at much higher prices than "normal" RAM. Dual-ported memory has been used as video memory on contemporary (expensive) computers and is even used today.

Dual-ported memory is actually the thing that you are describing, just extended to cover any real application.

1
  • "LDIR (that would need way more buffers)" Not realy, since an LDIR can be put on hold like any other access when the one transaction buffer is filled. "[LDIR] on a Z80 transfer lots more bytes in a single instruction fetch." Again, not realy, as the LDIR gets fetched for each and every byte transfered. Over and Over again. And no, he isn't decribing a dual port memory, but a write back buffer.
    – Raffzahn
    Sep 20, 2018 at 12:06
-1

It's not just the systems you mentioned; in almost everything from the era, other than the IBM PC (with its discrete - and not particularly high performance, merely higher performance than hanging something directly off the 8088 bus - graphics cards) and the MSX/Console type machines using a TMS VRAM graphics system, or an Amiga equipped with FastRAM, the CPU had to contend with the video system for access to RAM.

There's various reasons for this. One major driver was that of sheer cost. If you run two buses in your machine, one with main memory accessible by the CPU alone, another with video memory that's looked after by a discrete chip, you greatly increase the complexity, and thus the design and building cost of your machine. It also increases the potential points of failure, which is an undue risk if you're making a simple and cheap home starter system. One bus with everything hanging off it, and a somewhat simpler Glue ULA / PLC / etc gating the access on a timeshare basis, especially if the "video chip" is little more than a shift register that has video data serially DMA'd into it, is far more streamlined and straightfoward, and can be banged out for minimal cost without suffering too much in the way of reliability issues.

Another is, well... need. Video bandwidth in the early days really wasn't that much. The sheer amount of available memory (the PC's 16KB CGA was positively massive for its launch era, especially considering the machine's base RAM wasn't any larger, and the MDA only had 4KB; by the time of the Mac, ST and Amiga some years later, the screenbuffer size had only increased, respectively, to 1.33, 2.0, or 2.5x (default; max of 10x for the rather less frequently used, slow, memory squashing, flickery hi-rez interlace), with the competing EGA coming with 64KB by default) limited the practical resolution and colour depth you could deliver, and that reduced how much data you had to stream from memory to screen per second*. The best you tended to get with any 8-bit or other early 80s machine was in the realm of 256 or 320 pixels on a line and 2 bits per pixel (direct, or equivalent via block attributes). 512 or 640 bits, a little under 16,000 times per second, isn't that much... it's in the realm of 8 to 10MBit, or 1.0 to 1.25MByte/s (actually a little higher because of blanking, but let's not split hairs for the sake of a demo; we can consider it doesn't go above 2MB/s, and probably settles around 1.5).

OK, when you've got a 6502 system running at all of 1 or 2MHz, or even a Z80 at 4MHz (both limited as much by the memory speed as anything else - in fact, a decrease in the cost of high-frequency DRAM is literally what made it possible to run the BBC Micro at 2MHz and have it deliver an 80-column display with graphics capability, when the original design only produced half of those specs), this still sounds like quite a lot. But, there's more; you have to consider the CPU demand as well. And early processors just weren't very efficient when it came to memory access. Modern chips can easily completely saturate the memory bus with continual access, and indeed often end up momentarily paused waiting for the next RAM cycle if they get multiple cache misses in a row. Not so the earlier generation of chips. You'd be lucky to get 4 clocks per cycle a lot of the time (excepting some oddities of efficiency like the 6502's zero-page mode), and ignoring the other specifics it was typical for the bus to sit idle a good 50% of the time; this was even true of the 8086 (the 8088 hammered the bus a bit more as it was trying to fit a 16-bit architecture into 8 bits), and persisted into at least the 68000/68010 era, maybe the 80286 as well. Anything sitting idle in a computer, generally, is just a waste of silicon and electricity. What's to be done with it?

Well, er... we could fit the video access into it. If things are arranged with sufficient grace, the impact on processing could be anything from "nothing" or "so minor that you wouldn't notice outside of detailed benchmarks", to "moderate, but still not worth adding an extra bus and chipset to overcome", depending on machine and, indeed, the video mode. We can even trace the decisions regarding default video modes to these arrangements, somewhat.

Later examples which are the ones I'm most familiar with are the aforementioned trio of Mac, ST and Amiga. All use the 68000 CPU at 7 to 8MHz, and pixel clocks in the 7 to 32MHz range depending on mode (higher clock/resolution meaning lower bit depth, so roughly the same bandwidth - including the Amiga's interlace mode, which essentially halves the framerate). The 68000 has a 4-clock memory cycle, which is, nominally, continually active when filling the prefetch queue or running through strings of short instructions... but in reality it's only active on the bus for two out of every four cycles, maximum, and it's designed for memory rated at only half the CPU's clock speed. If your computer's Glue logic is in any way competent, and you have full-speed memory (which by the time these machines came around was fairly affordable), it can fool the processor into thinking it's got exclusive use of the bus, when in fact the graphics system (and/or other DMAs) have free reign of it at an effective 3.5MHz or more. Meaning you can run a 7 to 8MB/sec graphics mode using shared memory with almost no performance penalty whatsoever - the only times the processor is made to wait is if it's just finished processing one of the relatively rare longer instructions that runs for a total number of cycles not divisible by four... in which case that longer instruction is extended by one, two or three clocks. But even in the worst case scenario (say, adding 3 clocks onto a 5-clock instruction), it's not quite a 50% slowdown, and the greater majority of instructions are either 4-clock aligned, or take so long to process that the extra latency after each one causes only a very fractional increase to processing time. That bandwidth is what gets you the common 320x200p (or x256p, 400i, 512i) 16-colour or 640x200p (etc) 4-colour ST or default Amiga modes, 640x400p (72Hz) mono ST mode, and is in fact rather in excess of the Mac's relatively lowly 512x342p (60Hz) mono which, in concert with somewhat reduced blanking, needs half as much bandwidth again (possibly down to it being derived from the lower frequency Lisa, where 720x364p 60Hz used the full available bandwidth, and maybe intended to run at 4MHz or less vs the Lisa's 5MHz). We also see evidence of it in the Amiga's higher quality modes, which demand an extra 25% (lo-rez 32-colour), 50% (lo-rez 64-colour/hi-rez 8-colour) or even 100% (hi-rez 16-colour) bandwidth, and sap the processor speed accordingly (in the latter mode, it can ONLY run during the border/blanking periods of the screen scan, being completely HALTed during the active parts of the video, audio and disc DMA cycle). In those modes, the ability for the custom chipset to compensate for the hobbled CPU, or even for the CPU to run on a separate bus with its own "Fast" RAM (one of the many reasons it was a comparitively expensive machine), become absolutely essential.

Backtracking to the 8-bits, we can still see similar, though there's often more of a tradeoff in terms of speed vs cost. The Spectrum needs about 14Mbit/s video bandwidth (=1.75MByte), with 7MHz pixels at 2bpp equivalent. The system clock spins at 3.5MHz, transferring 8 bits every other clock assuming ~2MHz memory and the usual 2-clock DRAM R/W cycle. So that's just enough to support the normal graphics mode (or the double rez, colourless option in its Timex sibling), with the processor halted during the active video period. This may be why the machine's video appears in a relatively small window with thick borders; you can still deliver reasonably good resolution this way, with high-ish clocks and a PAL signal, without entirely crippling the processor. There's exactly 224 clock ticks per line, of which 128 are taken up by video access, so you lose a little over half the potential memory accesses in this scheme... but, also, only 192 of the 312 scanlines are active. Overall, only 35% of the actual scanned frame is active video. If your programmer is sufficiently wizard-grade with their use of machine code and cycle counting, and can arrange so that the processor is fed a long-running instruction just before the start of the active video period (then writes out the result as soon as it's allowed, and spins through some shorter ones in the blanking period), you may only really lose a third of the available bandwidth... less still, if they can do it on every line. This, I expect, would have been considered entirely acceptable in the pursuit of a lowest-possible-cost Colour Computer that still gave acceptable (rather than "blazing") performance, especially as it was using what would otherwise have been considered a pretty speedy processor only a few years earlier when even pretty expensive CP/M based micros were using things like 2.5MHz i8080s. Compared to those, it had performance to burn. And if you were really bothered more by processing than visuals, there was likely still the option of turning the display off (except for syncs) altogether, such as what happened with the ZX81's "Fast" mode, or whenever you pressed a key on the ZX80. Or you could just buy a machine that cost more than £149 fully assembled...

(In fact, sanity checking my memory via Wikipedia to make sure it didn't run the bus at 7MHz instead with 4MHz memory... turns out the Spectrum improved on the ZX81 in more ways than just adding colour, sound, and a larger internal RAM/ROM. It actually WAS a split-bus design... maybe not fully a true two-bus system, but there was an at least notionally Amiga-like separation of "memory accessible by the video/Glue system AND the CPU", being the lower 16KB (or only 16KB, in the base model, where the above dissection would still hold true), and "memory accessible only by the CPU", being the upper 32KB (or 112KB) in the larger-memory models. In which case, if you were writing 16KB code, you'd have to be exquisitely careful about your timing in order to squeeze out the best performance, but it's not like you were going to write anything THAT complicated in the approx 9KB of usable program RAM available to you anyway so optimisation was rather a given; if you were writing 48K or 128K code, you just had to make sure anything timing-critical lived above that 16K boundary, and save the spare 9-and-a-bit K of lower memory for less important stuff such as infrequently referenced data that could be specifically called upon during vsync, maybe a double-buffer for the screen or a larger scrollable area, music replay routines, etc... this would be analogous to using a higher Amiga video mode - EHB low rez in deep overscan, or 16-colour hi-rez with a reduced viewport - on a system with only 512K or even the very base 256K of the launch model, but 2x or more that amount hanging off the FastRAM bus, with the same considerations about what goes where, including whether the AV system could directly access it or not)

C64 I'm fairly sure I read as actually having GREATER memory bandwidth... like, the processor might have only run at about 1MHz, but the bus / RAM was clocked somewhat higher, and a typical video mode tended to share access on about a 2:1 basis (video:CPU) during the active periods. Atari 8-bits similar. These systems of course, particularly the Ataris, had the additional advantage of offering multiple screen modes, with contention varying - much like in the Amiga - according to the combination of text vs graphics, resolution and colour depth, as well as having hardware sprites that meant you could produce the illusion of a visually richer display (through use of a limited number of small, but higher resolution and higher colour depth elements, on top of an otherwise more rudimentary playfield; again, this helped the Amiga no end, especially in its later years when VGA-equipped PCs, later Macs, and 16-bit consoles became its main competitor, rather than the ST, 8-bit consoles and mono Macs) without having to significantly increase actual video bandwidth.

(OK, I haven't done as well sanity-checking THAT, but what wiki knowledge I have dredged up says that the commie's VIC-II "shares the RAM with the CPU, each accessing it on alternate half-cycles, other than so-called BadLines where the VIC blocks the CPU". Which, all in all, sounds rather like how the 68000 vs Video works in the later machines; as the VIC has a dedicated 4-bit mini-bus connection to the half-kilobyte "colour RAM" chip (presumably accessed at a higher frequency derived from the master 14MHz colourburst crystal?), which lies outside of the normal 64KB memory map, and that is responsible entirely for holding information about the attributes of the background character/tilemap, one assumes that in normal use the VIC alternates reading actual character information from RAM with attribute information from the ColourRAM (during phases where the CPU has memory access), and BadLines are... IDK... where the ColourRAM has to be updated from normal RAM, via the VIC, as it can't be directly written by the CPU? Perhaps it's refreshed on one out of every eight scanlines, always copying the data afresh with each new frame as that's a lot simpler than trying to determine when and what to copy, and as the characters are blocks of 8x8 (or 4x8) pixels the colours read from the first line are good for the other seven; in this way, the processor runs at full speed almost all of the time, only being halted for the active width of one scanline out of eight through the active height of the display... or in other words, about 80 out of 114 ticks, on 25 out of 262 or 312 lines per frame = 5.6 to 6.7 percent of the time, which again could be ameliorated slightly by clever time-sensitive machine language programming. Having to run just four short additional traces to one very small, simple, cheap additional chip on the board, to enable the CPU to run at about 93 to 95% of its theoretical maximum potential, with an otherwise maximally simplified design, seems like a reasonable compromise, vs either massively slowing it without that small additional buffer (losing more like 45 to 54% of its speed), or having to provide a wholly separate memory bank just for the video system in order to recover that last 6% or so.)

(Indeed, though it was not a conscious bit of copying, a thought-exercise design I came up with for a more comprehensively enhanced STe vs what Atari actually delivered incorporated something vaguely similar in order to allow more Amiga-like graphics modes without a second bus or increased clock frequencies; essentially, a small SRAM buffer which could be DMA'd into in the usual video-readout fashion, starting immediately after the end of an actual display period, but not stopping - and, in the real life machine, essentially idling/wasting cycles, not even recovering them (as the Amiga does) for Blitter or Disk transfers - during the border/blank area. The only slightly modified (to add extra modes) main video chip then reading out of that buffer during the usual display period, starting just as it becomes completely full up, and FIFOing for the remainder of the display time (reading out at a greater rate than it's being written into, but discontinuously), until it's emptied at the end of the active frame. In this way, a fairly cheap and simple 16KB SRAM, a mildly upgraded "shifter", and a minimal tweak - not addition - to the existing Glue logic would allow a 50% increase of either resolution or colour depth (enough to finally produce a 16-colour 80-column display, albeit with only a 6x8 font, or with 4 colours/greys in the 400-line mode, or a true 640x200 display with 8 colours, or 320x200 with 64... or, say, 20% to one and 25% to the other... or a reduction of one with a greater than otherwise expected increase to the other) over what could be provided by the usual 32KB screenbuffer, and without causing any additional processor slowdown (UNLIKE the Amiga case), simply by taking advantage of the unused and "wasted" areas of the video scan. It's not quite the same idea as the C64 colour RAM / Badlines, but there's a good bit of overlap between them)

(Atari... IDK what their approach was in that regard, but everything was a bit more modular and separate anyway, so there may have been full separation. But the wide proliferation of video modes, including some pretty weird ones with e.g. "1.5 bit" colour depth, means that it was probably all shared, and left up to the programmer to decide on an appropriate division of system bandwidth between AV and CPU)

Later on is where this model started to fall apart, with systems like the A1200, Mac LC, Atari Falcon (somewhat; its architecture was largely designed to extend and make the most of a shared-memory model with a focus on improved graphics, but still suffered in the higher modes) and even the PCjr / Tandy series, not to mention a good bunch of peri-millennial PC systems which used AGP to share system memory with graphics, all showing increasing levels of system hamstringing with use of high quality graphics modes, particularly anything beyond the level of Generic VGA (ie, 320x200 256-colour thru 640x480 16-colour... in some cases the latter having to be interlaced to retain speed, unless the former was scandoubled anyway). But the fact that their makers thought that it was still a viable idea - and essentially provided for programmers and users to, as before, decide on the best mix of graphical quality and processor speed on a case-by-case basis (and, in the LC and A1200 at least, still provided for multiple memory areas so a well-behaved operating system or bootloaded program could keep time-critical code away from the AV memory) - shows that they had got well-used to it being an entirely workable concept with their earlier machines.

Oh, and another couple of considerations, which are certainly relevant to both the PC, and the TMS based machines: Code complexity, cross compatibility, and speed of video updating. Having to send data through a different chip, possibly at the end of a whole additional bus, makes for less efficient code than simply dropping it into a certain place in main memory, or moving it from one memory address to another. You have to write more lines in your programs to carry out the same task, you may have to duplicate data to a greater extent (having some things both in your main RAM and in the video RAM, for speed of access or just displaying it at all, and paging things in and out as needed), and it takes longer. You can't just MOV a bunch of bytes using the same mechanisms as any other transfer, but instead have to shuttle them through another chip, with particular instructions, acknowledgements, maybe a slower bus in-between, and that other chip isn't guaranteed to be particularly efficient or work as fast as the rest of your system. Plus in most of these early examples the available maximum VRAM is pretty limited (typically 16KB) and it doesn't always make the best use of it... EG often the only settable modes use the entire memory as a single display page... and even if they don't, the half-page capabilities are so poor that you wouldn't realistically employ them for anything but the most simplistic purposes. So you have to suffer a much slower full-screen update, by streaming the entire new screen across whatever bus is between your main memory and the video controller, and avoid doing that instead of rewriting small portions (or, where the facility even exists, moving sprites around on top of a static background), whereas on a lot, if not all of the shared-memory systems mentioned above, the screenbuffer is quite a bit smaller than the total memory space (and crucially, a good bit smaller than the range accessible by the AV system), so you can have multiple video pages (a la Hercules, EGA, VGA and later, more memory-dense PC video cards, or the graphics memory of later and more advanced consoles) within the shared memory area and flit between them with a simple single register write - that is, changing the start address of the active video area. Boom, double buffering and all its advantages, such as moderately smooth scrolling and/or sprite movements without "tearing", zipper-effects, orphaned-pixel trails/smears, or "snow", are yours for the taking, if you even need to use them anyway because of the increased write speed to the video memory and much improved ease of blitting sprites in from nearby offscreen areas, or shifting the entire image around by a few pixels (or chunky-scrolling by whole character spaces in the hybrid text/graphics models), if indeed the video chip itself doesn't allow hardware sprites and scrolling (for which a larger-than-the-screen memory page is absolutely essential) in the first place, obviating some of those procedures entirely. This in part is why a lot of early PC games are single-screeners; the background is fixed and everything that moves does so against that static background, with any change of scene being a flip-screen affair. EG, Alley Cat, Round 42, or any number of first-gen arcade conversions (early arcade boards themselves being pretty simplistic and having very little memory). Also why almost anything that uses the TMS system or a derivative - including both the NES and SMS, as well as the first generation of MSX machines - operates on a tilemap (ie, background is essentially harware-scrollable textmode, but with a customised graphical character set) and sprite basis, rather than using bitmaps, because that's the only way to produce a dynamic, scrolling display with the available memory and update bandwidth (and usually they cheat somewhat by using the cartridge as a character ROM, instead of relying on having one in the machine, or using internal RAM to hold that data, so the notional memory space is a bit larger)... otherwise they'd be stuck with single/flipscreen action as well.

*(ironically, textmode could often be what made the highest demand, and was one reason CGA had to be a discrete card; 8 graphics pixels in monochrome use no more bandwidth than an 8-bit text character of the same width, and in 2-bit/4-colour mode they use as much as a character plus simple attributes... and on top of that the character/attribute data has to be converted into actual pixels by feeding through a font ROM and colour gating system... the only saving is memory amount because that same character is read out from the same RAM address several times to build the image one scanline at a time. An integrated system probably could have dealt with CGA's graphics mode, and 40-col attributed or 80-col unattributed text, but the 80x25 full colour textmode that formed the basis for all standard PC text displays for the next 30+ years would have been unsustainable... hence the original problem of having to choose between slow / flickery screen-blanking Vsynced updates when scrolling, or putting up with "snow" as data transfer interferred with read-out to the screen)

PS. The Spectrum's method of producing separate memory areas is likely rather simpler, and less costly than it would be in the Amiga... it is after all already a very pared-down architecture with the minimum of chips. Having a bank of 16KB and another of 32KB means you only need 14 (or maybe 7, if they're time-multiplexed) address lines going one way, and 15 (or 8) the other. Or if the lower bank shares space with the ROM (backwards to how you'd usually expect it - often, ROM is freely accessible by the CPU, but Sinclair was often found going against the grain, and in any case you're gonna need access to the character glyphs), each of them only needs 15 lines, instead of the 16 for the whole system. It's a small saving, but it's still a saving. In the 68000 system you'd have a minimum of 18 on the shared side (assuming 512KB and word rather than byte width access; more likely 20) and potentially 22~24 for the CPU-only side. Of course, the data lines would only count 8 on both legs, rather than 16, and I wouldn't be entirely surprised to find that they're actually shared and time-multiplexed somehow (like the chips are strobed one clock tick apart and the data coming off them gated, buffered inside the ULA, and delivered in just-in-time fashion to their respective destinations - which is somewhat like how the Atari ST Glue logic works when arbitrating CPU vs Video memory access; the access request from one chip is woven around the response to the other, and the actual addressing AND data is buffered through the chipset). And, in any case, the lines are WAY shorter; the Amiga motherboard version may find itself routed through 16 (1x256K, so each data line has a different length and path, alongside the address lines) internal chips for the video part, and off to an arbitrarily-placed external connector on the FastRAM side. The Spectrum one? A single 8x16K chip on one side, and two on the other, each getting all of the data lines and most of the address lines, making the routing short and uncomplicated... And of course the C64 one is simpler still. Just four (eight?) extremely short traces between the VIC and the CRAM. Comparing either of those (or, say, the Falcon's Videl) to the Amiga, or the entirely separate video and VRAM subsystem in a TMS design, let alone the complete multi-slot expansion bus in a PC, is like apples to oranges.

PPS FWIW the BBC used 4MHz memory. It clocked the memory bus at twice what the processor and video sections ran at, allowing zero-contention access by both to the same memory areas. It just so happened to exist at a time when that speed of memory had become affordable, but the processor speeds hadn't yet increased to match. Thus CGA-like graphics (but with greater height, slightly better choice over palette, and a higher-colour/lower-resolution option, with no "snow" or other silliness, at the expense of its most colourful textmode being limited to a "mere" 40x25 in 8 colours) and a fairly nippy 6502 (probably acquitting itself quite well against the PC's 5MHz 8088 in a straight fight), all on a cost-efficient shared system architecture, leaving overhead in the budget for all the additional nice-to-haves like the coprocessor bus, sideways ROMs, disk operations, decent BASIC, surprisingly good soundchip (at the time, only really beaten by the SID), relatively professional keyboard, monitor output, more ports than you can shake a stick at, EcoNet capabilities, surprising memory expansion capability, etc. Showing that, at least with an extra year or two of development and serendipity, you need not make something along the same lines as, or costing as much as, the IBM in order to enjoy similar performance.

1
  • 3
    Would whoever pretty much instantly downvoted this care to comment as to why? Simply too long for you, or something else?
    – tahrey
    Oct 27, 2019 at 22:45

You must log in to answer this question.

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