https://retrocomputing.stackexchange.com/questions/2361/why-does-the-commodore-c128-perform-poorly-when-running-cp-m Stack Exchange Network Stack Exchange network consists of 181 Q&A communities including Stack Overflow, the largest, most trusted online community for developers to learn, share their knowledge, and build their careers. Visit Stack Exchange [ ] Loading... 1. + Tour Start here for a quick overview of the site + Help Center Detailed answers to any questions you might have + Meta Discuss the workings and policies of this site + About Us Learn more about Stack Overflow the company + Business Learn more about our products 2. 3. current community + Retrocomputing help chat + Retrocomputing Meta your communities Sign up or log in to customize your list. more stack exchange communities company blog 4. 5. Log in 6. Sign up Retrocomputing Stack Exchange is a question and answer site for vintage-computer hobbyists interested in restoring, preserving, and using the classic computer and gaming systems of yesteryear. It only takes a minute to sign up. Sign up to join this community [ano] Anybody can ask a question [ano] Anybody can answer [an] The best answers are voted up and rise to the top Retrocomputing 1. Home 2. 1. Public 2. Questions 3. Tags 4. Users 5. Companies 6. Unanswered 3. 1. Teams Stack Overflow for Teams - Start collaborating and sharing organizational knowledge. [teams-illo-free-si] Create a free Team Why Teams? 2. Teams 3. Create free Team Teams Q&A for work Connect and share knowledge within a single location that is structured and easy to search. Learn more about Teams Why does the Commodore C128 perform poorly when running CP/M? Ask Question Asked 5 years, 9 months ago Modified 2 years, 7 months ago Viewed 10k times 46 I have seen several claims of poor performance of the C128 when running CP/M, and would like to better understand these claims, especially in comparison to other CP/M machines of the early to mid-1980s. The C128 has a Z80A microprocessor clocked at 4MHz for running CP/M. This is the same processor and clock speed found in, for example, the TRS-80 Model 4. Both those machines were CP/M compatible, but I have seen claims that the 4MHz clock speed was not fully utilized by the Z80A in the C128. Specifically, I have seen it stated that the C128 Z80A only runs at 4MHz half the time. Is this statement true, and why should this be the case? Also, are there any benchmark results published to substantiate poor C128 CP/M performance when compared to similar Z80A systems? * cp-m * commodore-128 * benchmarking * commodore Share Improve this question Follow asked Feb 26, 2017 at 18:03 Brian H's user avatar Brian HBrian H 58.6k1818 gold badges185185 silver badges351351 bronze badges 2 * 1 Without checking: The VIC had to "steal" memory cycles from the 6502 for RAM access, so I suspect it's the same with the Z80. - dirkt Feb 26, 2017 at 19:35 * 2 @dirkt but wouldn't you normally run CPM in 80-column mode, which bypasses the VIC and uses the 8563 VDC (or in DCR models the 8568 DVDC)? The VDC has its own video RAM which suggests it wouldn't effect performance in that mode. Maybe if you were using it in 40-column mode with the VIC due to the lack of a RGBI monitor? - mnem Feb 27, 2017 at 1:13 Add a comment | 7 Answers 7 Sorted by: Reset to default [Highest score (default) ] 37 I'm Linards Ticmanis, the guy who put out the CPMFAST package in 1999 that has been mentioned several times in the other answers (although I go by the nickname TeaRex on here). While creating that, I had to take a deep look into the innards of C128 CP/M, so that I think I can say that I have a rather detailed understanding of the way it works internally (or did have it over 20 years ago... I'm not excluding some failures of human memory here). I'm afraid there is some myth and half-truths in some of the other answers to this question. Firstly, in C128 CP/M, writing to the 80-column screen does NOT go through the 8502 CPU as several other answers assert; the Z80 talks directly to the 8563 VDC (the 8502 is used by CP/M for several other things, such as disk I/O and printer output, but not for screen output and not for keyboard input either). The reason why screen output in C128 CP/M is so slow is rather 1. The Digital Research provided BDOS of CP/M 3.0 is much slower in doing basic character I/O than the BDOS of the more common CP/M 2.2; CP/M 3.0 does support much more complex I/O device reassignments where standard output can go to any possible set of up to 16 devices at the same time; this also means that for every character being written, it has to loop in a complicated, bit-shifting way over a 16-bit mask to determine which of 16 output device drivers to actually send the character to, and of course it does all this in pure Intel 8080 code without making use of the Z80 specific instructions and registers. 2. The code in the C128's Commodore supplied CP/M BIOS (which for this purpose includes the 4KB of Z80 ROM code) is written in such a way that outputting normal printable characters such as letters or numbers (as opposed to control characters) follows the LONGEST path through the code (each character is compared to every possible control character before it is decided that it isn't one), even though it is the most common case by far. 3. C128 CP/M supports the bit-banging RS232 on the userport. Unlike in native or C64 mode, the RS232 is always enabled and set to 300 baud by default, which means that the interrupt (IRQ) rate is also much higher than in native mode; and the interrupt code for the Z80 does quite a bit of things, including scanning the full keyboard at the same rate. This wastes a lot of CPU time when RS232 is not used (i.e. practically always). 4. Bank switching between the user program (TPA in CP/M parlance) in bank 1 and the BIOS/BDOS/ROM/buffers in bank 0 happens VERY often in the C128 CP/M. Several times per character. Although the impact of this is lower than the other three points above. 5. Access to the 80-column screen RAM is doubly indirect as indicated in other answers (you have to access the RAM indirectly through some registers of the VDC chip, which in turn are only indirectly accessible to the CPUs through a rather bottleneck-y approach - you write a register number to $D600, do a little check-for-the-readiness-flag-bit-to-be-set loop and then write a register value to $D601). 6. The biggie is of course the fact that the VIC-IIe is not put into fast mode when the Z80 is running, so that the Z80 runs at 4MHz for two cycles (one 8502 half-cycle) and then stops for two cycles (the other 8502 half-cycle), giving it an effective speed of just 2 MHz, which is just too low for CP/M 3.0 in practice, although it would be sort of enough for CP/M 2.2. The C128 CP/M source code (which was available from Commodore back in the day when you bought the complete set of CP/M 3 manuals from them) contains multiple instances of code that switches the VIC-IIe between slow mode (for hardware access, e.g. access to the REU, and for switching between the two CPUs) and fast mode (for everything else); but it's all commented out, so it seems they aimed for that but couldn't get it working. I tried to mail the main developer, Von Ertwine, with a question about this back in the 90s, but unfortunately never got an answer. In practice, you CAN switch the VIC-IIe into fast mode while the Z80 is running; this causes a simple timing loop with interrupts disabled to in fact run somewhat faster (though not twice as fast), but crashes the system when you do much of anything beyond this. It would be really interesting if someone could check with a logic analayzer (which I don't have access to) what exactly happens signal-wise, especially to the Z80 clock signal, when you enable fast mode while the Z80 is running. CPMFAST adresses the first three points above by establishing several short-cuts through the code for the common case (output of a printable character, to the 80 column screen only, without RS232 use) and also increases the disk buffer area so that fewer disk accesses are needed. It cannot do anything about the points numbered 4 through 6, though. Share Improve this answer Follow edited Feb 7, 2020 at 15:19 answered Feb 7, 2020 at 8:33 TeaRex's user avatar TeaRexTeaRex 1,11566 silver badges99 bronze badges 3 * 1 TeaRex, thank you for the detailed info. I am confused on a major issue, though. You state that CP/M writes to the screen do NOT go thru the 8502 CPU, but the CP/M chapter of the C128 Programmer's Reference Guide seems to state otherwise. I quoted a section which begins with the sentence, "The 8502 is responsible for most of the low-level I/O functions." It seems very strange that they would use the word "most" yet include neither screen nor keyboard I/O in this. I am not saying you are wrong, just that if you are correct, official docs are misleading. - RichF Feb 7, 2020 at 13:35 * 1 @RichF, maybe the C128 PRG was (partially) written before the CP/ M code had been finalized? You can look at the code yourself to see what it does. - TeaRex Feb 7, 2020 at 14:02 * 1 Thanks for helping me understand better the major issues and which ones were readily (vs. not so much) solvable. Knowing that C128 FAST mode doesn't work in CP/M explains a lot. - Brian H Apr 14, 2020 at 14:58 Add a comment | 46 (2017.03.03) I have added a second answer with diagrams and more technical details. This answer is already huge and self-contained; the other focuses on the complexities due to hardware. Why does the C128 perform poorly when running CP/M? 1. The Z80A was sort of an after-thought in the C128 design. Before release it had been touted as "fully C64 compatible" (which the earlier C= Plus/4 was not). However, the C64 had a Z80 cartridge allowing it to run CP/M. For whatever reason the cartridge could not work on the C128, so they added the Z80 directly to the motherboard. At that point, they were already 2 months into their 5-month development cycle. (see reference #3 below) 2. I/O was doubly indirect. Actions such as reading from the keyboard and writing to the screen first went thru the CP/M BIOS layer. Then it had to switch CPUs! From the Commodore 128 Programmer's Reference Guide (PRG), page 500: The 8502 is responsible for most of the low-level I/O functions. The request for these functions is made through a set of mailboxes. Once the mailboxes are set up, the Z80 shuts down and the 8502 starts up (BIOS85). The 8502 looks at the command in the mailbox and performs the required task, sets the command status and shuts down. The Z80 is re-enabled; it then looks at the command status and takes the appropriate actions. 3. Updates to the screen were s-l-o-w. I believe this was due to the impact #2 had on interacting with the 8563 video controller. Although a block mode character transfer was possible, apparently the complexity of the dual-BIOS layers led to only one character being written to the screen per BIOS call. To write a character, two 8563 registers needed to be updated, which were the hardware pipeline to the 80-column video memory. That all amounts to a heckuva lot of overhead per character. 4. Some users only had the classic C64 model 1541 disk drive. This was already known for being very slow (to be fair, "faster than cassette"). The newer 1571 drive, released with the C128, was three to six times faster, had double the capacity, and supported several CP/M formats used by other manufacturers. Some of these issues were clearly not due to hardware limitations, but stemmed from a lack of optimization for the drivers used in CP/M. The engineers were on a tight schedule and implementing something that wasn't even part of the original C128 design. They would have had to rewrite the 8502 BIOS code in Z80 assembly language, but they were primarily hardware guys. I'm sure Commodore didn't want to spend extra money to optimize a feature they hadn't even asked for. So the simplest, most reliable route was to make calls to the already working and well-tested 8502 BIOS. A 1999 update to C128 CP/M, by Linards Ticmanis, addresses some of the CP/M driver performance limitations of the original and purports to improve 80-column screen updates by 75%. * http://www.commodore.ca/manuals/funet/cpm/sys/c128/system/ cpmfast.zip --------------------------------------------------------------------- (speculation added 2017.03.01) After fully reading reference #2, my understanding of the development bottleneck for the CP/M BIOS was clarified. The C128 team did have an excellent CP/M expert working off-site. It was never his goal to have the CP/M BIOS call the 8502 BIOS. Unfortunately the Commodore MOS group (the chip developers) had long-standing major problems delivering a working, stable, and reliable 8563 80-column video controller. This chip had been part of a Z8000 (16-bit version of Z80) Unix computer, the "C900", Commodore had once worked on, and apparently the chip had never been completed even for that use. Thus the 8563's fundamental design was based on an entirely different bus structure than the C128 offered. The 8563 samples the C128 team received would tend to burn themselves up, arrive with documented deficiencies, and, in general, be altogether unreliable throughout most of the development process. The CP/M guy could not use current hardware. He had a board with an older 8563 revision that wouldn't burn itself up and mostly worked. (He had to keep it cool with an ice cube sat in a tray above it, though.) But ongoing changes to the chip must have kept invalidating his BIOS. My guess is at the last minute he was told something like, "Look, we'll eventually get the I/O working in house with the 8502 BIOS. You just make calls to that, and we'll make sure on our end that it eventually works right." --------------------------------------------------------------------- Z80A only runs at 4MHz half the time. Why should this be the case? From page 575 of the PRG: SYSTEM DESCRIPTION The Z80A, a 4MHz version of Zilog's standard Z80 processor, is included as an alternate processor in the C128 system. This allows the C128 to run the CPM 3.0 operating system at an effective speed of 2 MHz. The Z80 is interfaced to the 8502 bus interface and can access all the devices that the Z80 can access. The bus interface for the Z80 (the most complex part of the Z80 implementation) is described in this section, along with Z80's operation as a coprocessor in the C128 system. BUS INTERFACE Because a Z80 bus cycle is much different than a 65xx family bus cycle, a certain amount of interfacing is required for a Z80 to control a 65xx-type bus. Since the Z80 has built-in bus arbitration control lines, it is possible to isolate the Z80 by tri-stating its address lines. Thus, both the Z80 and the 8502 share common address lines. The interfacing of the data lines is more complex. Because of the shared nature of the bus during Z80 mode, the Z80 must be isolated from the bus during AEC low. Thus, a tri-statable buffer must drive the processor bus during Z80 data writes. The reverse situation occurs during a Z80 read--the Z80 must not read things that are going on during AEC low; it must latch the data that was present during AEC high. Thus, a transparent latch drives the data input to the Z80. It is gated by the Z80 read-enable output, and latched when the 1 MHz clock is low. It will be seen that the Z80 actually runs during AEC low, but that the data bus interfaces with it only during AEC high. The AEC is a signal pin of the C128's memory management unit. It is defined on pages 584 and 585 of the PRG: AEC: Address Enable Control. Indicates whether the 8502 processor or the VIC has access to the shared bus. When low, VIC or an external DMA has the bus and VA16 have the processor bus, and no pointer or BIOS translation takes place. This signal occupies pin 16. To put it bluntly, "It's complicated." The Z80A slowdown may be thought of as something like "wait states". Wait states are to allow a CPU running faster than memory to still operate, especially in an era before on-chip CPU caches alleviated the need for the CPU to access memory every (other) cycle. The problem on the C128 is that a 8502 CPU expects different things from its bus than a Z80 does. In the modern era, you can think of different motherboards being needed for different (yet current) '86 family CPUs. They can't just run the motherboards at slower and faster speeds and expect everything to work. Bil Herd and his team had to work with one motherboard and two entirely different CPUs. Performance benchmarks? I was not able to find actual benchmarks. There were several accounts of users lamenting the C128's CP/M speed, and especially its screen updating. IMO the perception of this mode being slow was much more to do with the I/O bottleneck than the effective 2 MHz clock rate of the Z80A. There had been lots of actual 2 MHz CP/M machines using the original Z80; there were few complaints about their speed. But imagine using a CP/M spreadsheet and actually observing o n e c h a r a c t e r a t a t i m e being written to the screen. It'd be kind of annoying. Cool References 1. THE REAL STORY OF HACKING TOGETHER THE C128 by Bil Herd, lead designer 2. The C128 Story, aggregated CompuServe postings by Bil Herd 3. HEY EVERYONE! IT'S BIL HERD!!! :) 1998 usenet post to comp.sys.cbm Bil describes why, how, and problems in adding a Z80 to the C128 4. CP/M-cartridge for the C64, a README by Ruud Baltissen detailed explanation of interfacing a Z80 to a 6502 bus 5. Platform Wiki: Commodore 128, backstory, design, and marketing for the C128 6. CPM Z80 Cartridge for the Commodore VIC-40, (from early 1980s) timing and other diagrams for interfacing a Z80 to a planned successor to the VIC-20 Share Improve this answer Follow edited Mar 8, 2017 at 19:27 answered Feb 27, 2017 at 13:14 RichF's user avatar RichFRichF 8,23344 gold badges2626 silver badges5252 bronze badges 18 * 1 This is a much better and in-depth answer than mine. - Jeff Zeitlin Feb 27, 2017 at 13:26 * Despite having a lot of respect for the C128 (I own several), it was really the classic example of not sticking to one thing and doing it well. It was neither a great Commodore 64 enhancement nor a great CP/M Z80 machine. It was a little bit of both. - cbmeeks Feb 27, 2017 at 13:33 * @JeffZeitlin Heh, thanks. Your answer complements mine, though. I saw the same quote at the Wikipedia, but as a former, self-proclaimed "C128 expert", it didn't fully satisfy me. It well describes intent, but is vague on the why. So I was stubborn and spent 3 hours answering. - RichF Feb 27, 2017 at 13:41 * @scruss Thank you for the correction. That's embarrassing. - RichF Feb 27, 2017 at 13:43 * 1 @RichF I'm also wondering if the slow, mailbox-based, BIOS method of updating the screen was a hardware limitation. It seems that a CP/M driver optimization could have been created to access the 8563 more directly, bypassing the need to use BIOS calls that go through the 8502. Furthermore, I am aware of one third-party C128 CP/M update ("CPMFAST.ZIP") that purports to improve 80-column screen updates by 75%. Perhaps this is just such an optimization/ fix? commodore.ca/manuals/funet/cpm/sys/c128/system/cpmfast.zip - Brian H Feb 27, 2017 at 15:30 | Show 13 more comments 18 My first answer attempts to answer all the OP's questions without going too deep into the hardware details. Since posting that answer, I have had the pleasure of corresponding for several days with Bil Herd, the lead designer of the C128 project. In addition to what I have learned from him, I have done some additional research on my own. This answer focuses on the hardware complexities which limited CP/M's effectiveness on the C128. It won't shy away from displaying system diagrams, timing diagrams, and etc. If you don't care about this level of detail, cool, and you have been warned. Here is the System Diagram, taken from page 3 of the C128 Service Manual (C128SM - click to expand): C128 System Diagram Remember the big deal I made of the 80-column 8563 Video Display Controller in my first answer? That's the tiny bit in the lower left corner. It is almost completely isolated from the rest of the machine, except for the address and data buses. That is why communication with the 80-column video RAM takes place via two registers of the 8563. The 8563 has 37 registers total, allowing control of number of characters per line, number of lines, cursor position, video synch, etc. You might be thinking, "There is a lot going on in that diagram." Yes. The C128 is essentially 4 computers in one box: 1. a C64 with almost total compatibility, with the 8502 (upgraded 6502) running at 1 MHz and driving the 40-column VIC display 2. a low-res C128 driving the 40-column display and running the 8502 at 1 MHz 3. a high-res C128 driving the 80-column display and running the 8502 at 2 MHz 4. a Z80A computer for running the CP/M operating system. It runs at 4 MHz, "half the time". "Huh?" A diagram is in order, from page 8 of the C128SM: Z-80 Bus Timing Diagram "Okay, I sort of get it. The Z80 clock is only running half the time. I see it, but that does not explain why?." The system clock is a 1 MHz clock provided by the VIC chip. In modes #1 and #2 it lets the 8502 run half the time, and allows itself half the time to update 40 column video RAM, move sprites, etc. One nice thing about 6502-family chips is that turning over half their time to something else costs them nothing, so they share with other stuff on the bus easily. In mode #3 it runs at 2 MHz and drives the 8502 at 2 MHz. Since the 40-column display is not active, the VIC need not worry about sprites and ignores the 40-column video RAM. Note, though, that this 2 MHz mode would not help the Z80A; at best it would simply force that chip into a semi-even 2 MHz mode. Here is the kicker, why the VIC must keep running even when 40-column video is not active (from pg.33 of same manual): The VIC chip contains a register which allows the C128 system to operate at 2 MHz instead of the standard 1 MHz of the C64. This operating speed, however, disallows the use of the VIC chip as a display processor. This bit is bit zero in register 48, and setting this bit enables 2 MHz mode. During 2 MHz operation, the VIC is disabled as a video processor. The uProcessor spends the cycle full time on the bus, while VIC is responsible only for dynamic RAM refresh and DMA arbitration. Clearing this bit will bring back 1 MHz operation and allow the use of the VIC as a video display chip. During refresh and I/O access, the system clock is forced to 1 MHz regardless of the setting of this bit. (emphasis mine) Rephrasing, if the VIC were completely shut off, the system's RAM would not be refreshed, and memory data would degrade. Also the VIC is forced to 1 MHz mode during refresh and I/O. Thus it makes no sense to use the 2 MHz VIC mode with CP/M because nothing is gained in the first place, and it would keep having to switch back to 1 MHz anyway. (The 8563 refreshes its 80-column memory asynchronously with everything else.) There is even another reason for keeping the VIC alive during CP/M. Look again at the C128 System Diagram, focusing on the upper right corner. See the little box labeled C128 Extended Keyboard? What is that about? C128 keyboard with C64 inset Imagine using a business application with just the C64 keys. To get the rest, the VIC needs to be active. Well, "the rest" except the CAPS LOCK at the top of the keyboard. It operates as a simple switch, separate from the 2-dimensional keyboard matrix, and its value is fed directly to the 8502 CPU. That means the Z80A cannot read that one key directly. However, since normal CP/M I/O is indirect and utilizes the 8502 and its BIOS, that key value is available. Only a pure Z80A routine lacks access. However, such a routine would be affected by the value of the separate SHFT LOCK key. The Display Bottleneck Writing a character string to the 80-column screen from CP/M involves multiple layers of code: 1. application layer - executes a printf() or other function to display a string 2. BDOS layer - device-independent I/O handling for CP/M. BDOS can handle a full string, but must call steps 3-8 character by character. 3. BIOS layer - sets up "memory mailboxes" so 8502 CPU can know what to do 4. Z80A turns over control to 8502 5. 8502 obtains command from mailbox and readies itself to make BIOS85 call 6. 80-column screen-write call executes. 7. 8502 returns control to Z80A 8. BIOS returns to BDOS 9. BDOS sends next character to step 3 or returns to application code (Note that a native 8502 application would avoid most of these steps.) Lets look at the heart of step #6 as an 8502 disassembly, beginning at location 0181F (not the actual BIOS85 code, just an example of what it needs to do). 0181F A2 1F LDX #$lF ; 8563 R/W data register number 01821 8E 00 D6 STX $D600 ; location of 8563 command register 01824 2C 00 D6 BIT $D600 ; check high bit of command register value 01827 10 FB BPL $1824 ; loop until clear 01829 8D 01 D6 STA $D601 ; (8563 data register) write character to screen 0182C 60 RTS ; return All 80-column screen communication occurs through the two 8563 registers, mapped to memory locations $D600 and $D601. Figure 10-2 illustrates this, from page 295 of the C128 Programmer's Reference Guide. 8563 Mapped Registers $D600 tells which of the thirty-seven 8563 registers you wish to read or write, and $D601 is the location to read or write the data. Since the 8563 is often occupied with its own memory and driving the 80-column screen, it can take time to handle the $D601 value. That's why you must always check the $D600 STATUS bit before reading from or writing to $D601. One useful feature of writing to register 31 (data register) is that the screen location auto-increments after the write. You need not manually increment it. --------------------------------------------------------------------- Don't assume the 8563 has a poor design. Normal (non-CP/M) 80-column C128 programs run with no noticeable delay in screen writes. The CP/M bottleneck is not the chip itself; it is the many layers of code through which screen writes must undergo. It is one busy chip; everything else in this answer relates to its digital functionality. Don't forget that it drives the video as well, converting bytes in memory to a 4-channel per pixel video signal (RGBI). Most of what it is doing is invisible to the 8502/Z80A side of the board. If set to its normal 80x25 screen, that is driving: * 80*9 pixels per scan line * 25*9 scan lines (each 8x8 character can be embedded in a larger frame) * 60 screen refreshes per second * = 720 * 225 * 60 = 9.72 million pixels per second Time is also allocated for horizontal and vertical synchronizations. Modify the synch values, and it can generate screens of more than 88 characters by 30 lines. Turn on interlace, and you can even double the number of scan lines. That's the output end. From video RAM it must read the 80 character codes per line, read the associated byte of attributes for each character (color bits for (red, green, blue, intensity), as well as modifier bits for (alternate character set, reverse, underline, blink)). Finally it has to read the character definition RAM so that it knows what each character looks like. The 8563 character RAM is loaded during system boot-up, and both of its 256-element sets of 8x8 characters can be redefined by application programs. Internally I'm sure that some of the data is buffered within the 8563 (such as the current and maybe next character lines of data), but I don't know. The point is, no matter what's going on with the I/O ports at $D600 and $D601, the 8563 is extremely busy doing its job of displaying the screen. One more thing - because neither C128 BASIC 7 nor CP/M support it, few people realize the 8563 can also operate in a 2-color bit-mapped mode. ... not a poor design at all. I'll end with showing the 8563 register map to give you an idea of all the things this chip is handling. This is from page 37 of the C128SM. 8563 on-chip registers Share Improve this answer Follow edited Mar 7, 2017 at 1:02 answered Mar 4, 2017 at 3:36 RichF's user avatar RichFRichF 8,23344 gold badges2626 silver badges5252 bronze badges 11 * I appreciate the diagram that shows how the pseudo-wait-state happens on the Z80A data bus access. A pictures is worth a 1000 words... - Brian H Mar 4, 2017 at 17:06 * Have you looked at the CPMFAST distribution for the C128? If I understand the modifications, it runs the 8502 in 2MHz mode during its execution of CP/M BIOS calls. - Brian H Mar 4, 2017 at 17:09 * @BrianH I read the readme.txt file and looked at cx80.asm, but I could not get a feel on how it fits with the CP/M BIOS. I had assumed until you asked this that he was talking to the 8563 directly and avoiding the 8502 BIOS calls altogether. But if he is still making the calls via the 8502, having it be in 2 MHz would only help a little. Note that during I/O access, the system clock is forced to 1 MHz. The ratio of non-IO to I/O code in the 8502 video BIOS would determine how effective 2 MHz would be. In larger picture, you still have Z80 BDOS and BIOS overhead. - RichF Mar 4, 2017 at 20:18 * 1 @supercat No "need". The Z80A can talk to both the 8583 and the VIC to control either the 80-col or 40-col screens. Both if you want. AFAIK, the problem with CP/M BIOS was that during development, the 8563s were very unreliable and "fixes" kept breaking other things. Their CP/M guy tried to use the 8563 directly, but in the end, the decision was made to kludge CP/M, having it call the 8502 BIOS code, which at some point the C128 folks knew would have to become rock solid. As far as I know, the only I/O value not available to the Z80 is the value of the CAPS LOCK key, fed directly to the 8502. - RichF Mar 8, 2017 at 23:53 * 1 @RichF: That reminds me... didn't CP/M ignore the caps-lock key and use the C= key as a toggle for that purpose? - supercat Mar 9, 2017 at 0:01 | Show 6 more comments 6 According to this Wikipedia article, the Z80 in the C128 was stepped down to 2MHz: The C128 runs CP/M noticeably slower than most dedicated CP/M systems, as the Z80 processor runs at an effective speed of only 2 MHz (instead of the more common 4 MHz). From the source code of the C128 CP/M implementation, it is clear that the engineers originally planned to make it possible to run CP/M in the "fast" mode as well, with the 40-column output turned off and the Z80 running at an effective 4 MHz; however, this feature does not correctly function on the first-generation C128 hardware. So, even though the chip was rated for 4MHz, it was never actually run at that speed in the C128. Share Improve this answer Follow answered Feb 27, 2017 at 12:28 Jeff Zeitlin's user avatar Jeff ZeitlinJeff Zeitlin 1,30011 gold badge66 silver badges1212 bronze badges 2 * 1 Actually, it could be misleading to say the Z80A never runs at 4 MHz, since it is clocked with a 4 MHz signal from the VIC-II. It seems like, more precisely, there are wait states introduced during every set of potential Z80A bus access cycles; though, calling this "wait states" may also be wrong or misleading too :( - Brian H Feb 27, 2017 at 15:56 * 1 @BrianH - Strictly speaking, you're right - but whatever was happening there, it left the Z80 performing as though it were actually running at 2MHz instead of 4MHz, which I assumed (and we know about that word) was enough to answer the question. - Jeff Zeitlin Feb 27, 2017 at 16:06 Add a comment | 3 Others have pointed out the slowness causes, but here I will point out some solutions. Firstly, switch to ZPM which is a Z80 BDOS replacement for the 8080 based CP/M BDOS. CPMFAST is another option to speed up the general OS. From a programmers' perspective you can bypass BDOS and BIOS and drive the VDC directly as I've done in SG C Tools (also turn off 40 column display). Although this will not help existing programs such as Wordstar it does dramatically speed up programs specifically written for the C128. The C code looks like the following to draw a string at x,y: uchar invdc(uchar RegNum) { outp(vdcStatusReg,RegNum); /* internal vdc register to read */ while ((inp(vdcStatusReg) & 0x80) == 0x00); /* wait for status bit to be set */ return(inp(vdcDataReg)); /* read register */ } void outvdc(uchar RegNum, uchar RegVal) { outp(vdcStatusReg,RegNum); /* internal vdc register to write */ while ((inp(vdcStatusReg) & 0x80) == 0x00); /* wait for status bit to be set */ outp(vdcDataReg,RegVal); /* write register */ } /* fast vdc string print given x and y offset in current page */ void printstrvdc(uchar X, uchar Y, uchar Attr, char *TextStr) { register uchar I, TextLen; ushort DispOfs; TextLen = strlen(TextStr); if(TextLen > 0) { DispOfs = Y*vdcScrHorz+vdcDispMem+X; /* calc disp mem offset */ fillattrvdc(X,Y,TextLen,Attr); /* use block fill for attrs */ outvdc(vdcUpdAddrHi,(uchar) (DispOfs >> 8)); outvdc(vdcUpdAddrLo,(uchar) DispOfs); /* set addr of first char */ for(I = 0; TextStr[I]; I++) /* send str to vdc disp mem */ outvdc(vdcCPUData,TextStr[I]); } } Share Improve this answer Follow edited Dec 31, 2018 at 3:10 answered Dec 30, 2018 at 16:16 Steve Goldsmith's user avatar Steve GoldsmithSteve Goldsmith 3122 bronze badges 5 * 1 This is interesting information, but doesn't answer the question. Please say what each solution is solving; that way, it will address the question topic. - wizzwizz4 Dec 30, 2018 at 16:46 * The question was about CP/M performance on the C128 which includes 8080 version of CP/M and BDOS/BIOD calls (answered above). I gave two solutions to the performance issues. - Steve Goldsmith Dec 30, 2018 at 17:53 * 1 Which performance issues do these solve, though? - wizzwizz4 Dec 30, 2018 at 18:20 * 1 ZPM and CPMFAST both speed up the BDOS and BIOS functions most programs leverage because they use Z80 instead of 8080 op codes. Each distro also optimizes in other areas including screen output. The second suggestion is to bypass BDOS and BIOS all together and write directly to the VDC. This is handy for programmers to know. - Steve Goldsmith Dec 30, 2018 at 21:39 * 1 There's an edit button. - wizzwizz4 Dec 30, 2018 at 22:14 Add a comment | 2 As far as I know the Z80 only runs at the same 2MHz the 8502 runs at. Which, internally, works out to 2/4=0.5MHz. Which is just plain slow. Source: a guy who came to visit our desk last night and knew everything else about the machine. So take with a grain of salt and downvote as much as you like. Share Improve this answer Follow answered Dec 28, 2018 at 17:24 Sixtyfive's user avatar SixtyfiveSixtyfive 13144 bronze badges 5 * 1 Thanks for sharing this, but I don't see why you'd divide 2MHz by 4. Where did the 4 come from? - wizzwizz4 Dec 28, 2018 at 17:59 * Good question. Like I said, a guy came by and said so. I googled for "z80 clock divider" now and found at least one thing ( cpcwiki.eu/forum/programming/z80-clock) where someone (2nd post) talks about a "divide by 4 circuit". Perhaps someone else can shed some light ... ? - Sixtyfive Dec 28, 2018 at 18:14 * 1 In case it helps to dispel a myth: the shortest instruction on a Z80 takes four cycles, comprising two memory accesses (a fetch and a refresh) of two cycles each. Most other memory accesses take three cycles so the next big tranche of Z80 instructions is those that are seven cycles long, but there are fives and sixes, and various others that obviate any sort of attempt to fit everything to a pattern of 4n, or even 4 + 3n. - Tommy Dec 28, 2018 at 18:14 * 1 @RainerVerteidiger the Amstrad is special because it does some trickery with timing signals to coerce a 6502-esque fixed memory access cadence, with memory available for video every other tick. Which does end up (approximately) rounding up every instruction to a multiple of four cycles. But other machines use various different schemes -- on the Spectrum there's no rounding or other penalty while the processor is accessing RAM that video can't be in, on the MSX there's an extra cycle in every instruction fetch but everything else runs at the natural speed, etc. - Tommy Dec 28, 2018 at 18:21 * Rainer, you are both right and wrong. The z80 runs at an "effective speed of 2.04 MHz". Right. However, it is clocked at 4.08 MHz, but only half the time. That's the sort-of-wrong part. A number of early cp/m machines ran at 2 MHz, so that in itself was not unusually slow. Later 4 MHz become the common speed, though. Note that in competition with the 6502, a 2 MHz z80 was roughly equivalent to a 1 MHz 6502. (generally 4 cycles to do very basic stuff on a z80 vs 2 cycles on a 6502) - RichF Dec 30, 2018 at 18:18 Add a comment | 1 I am far from C128 expert of any level (HW or SW), but I think one (expensive) change could solve all those speed issues. Certainly it is not possible afterwards, but could be a design route to speed up the machine, and would keep C64 compatibility at the same time, whil Z80 could run in full 4 Mhz mode (though it does not solve the several layers and BIOS routing / slow screen update). As it was not mentioned beforehand, I write down the idea. Reading through the descriptions and time diagrams, VIC-II need to be in 1MHz mode to update the DRAMs. And because of the 1MHz of VIC-II, the Z80 and the 8502 need to be is slow mode too. But what if there would be no DRAM in the machine, just SRAM, requires no frequent refreshes, and does not degrade content (the same as the color RAM on C64)? In that case the VIC-II 1MHz mode could be cancelled in C128 and Z80 mode, or it could run continuously in 2MHz mode. Certainly SRAMs were (and still) more expensive than DRAMs, but the speed is there. As my current C=16 64K memory expansion is based on SRAMs, I though I let you know this idea. Share Improve this answer Follow answered May 3, 2020 at 16:00 MMS's user avatar MMSMMS 1111 bronze badge 2 * Welcome to RetroComputing, and thank you for sharing the idea, I'm guessing that implementing your idea would have been costly , and likely not as easy as it sounds. - RichF May 4, 2020 at 2:25 * Actually, the VIC-IIe refreshes the DRAMs even in 2MHz mode when the 8502 is running. So I don't think this is the reason why FAST mode and Z80 operation are (in practice) incompatible with each other. - TeaRex May 4, 2020 at 9:13 Add a comment | Your Answer [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] Thanks for contributing an answer to Retrocomputing Stack Exchange! * Please be sure to answer the question. Provide details and share your research! But avoid ... * Asking for help, clarification, or responding to other answers. * Making statements based on opinion; back them up with references or personal experience. To learn more, see our tips on writing great answers. Draft saved Draft discarded [ ] Sign up or log in Sign up using Google Sign up using Facebook Sign up using Email and Password Submit Post as a guest Name [ ] Email Required, but never shown [ ] Post as a guest Name [ ] Email Required, but never shown [ ] Post Your Answer Discard By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy Not the answer you're looking for? Browse other questions tagged * cp-m * commodore-128 * benchmarking * commodore or ask your own question. * The Overflow Blog * How to make time for learning in tech sponsored post * Ready to optimize your JavaScript with Rust? * Featured on Meta * Help us identify new roles for community members * Navigation and UI research starting soon Linked 26 What was the intention with the Commodore 128? 11 Getting started with CP/M 12 Did the Commodore 128's Z80 CPU also have full access to the machine's custom hardware? Related 50 What precautions to take when powering on old computer for the first time in years 12 What is the proper way to test the PSU output for a Commodore 128D? 4 Commodore C128 MOS 6526A interchangeability? 26 What was the intention with the Commodore 128? 15 Are there games for the C128 that run (mainly) on the Z80 rather than the 6502? 8 Is there a possibility for a user-defined IRQ hardware vector on a Commodore 128 in C128 mode? 12 Commodore BASIC: why was the PET's GOTO so slow? 7 What is the largest single file that can be loaded into a Commodore C128? 7 Modern heat sinks for Commodore C64/C128 3 Is there a routine like FETCH, STASH and SWAP for transfering data between memory bank 0 and 1 on the C128? Hot Network Questions * Which random generator does /dev/urandom use (LTS 20.04) * Why is apparent power not measured in Watts? * Can an odachi be called a katana? * Under what conditions do airplanes stall? * How to properly translate "Great Evil" into medieval Latin? * Creating a reference group to have equal sample sizes for Wilcoxon signed rank test * How can the final /r/ in 'razor' and 'hammer' be syllabic? * Would salt mines, lakes or flats be reasonably found in high, snowy elevations? * How to calculate the individual atomic charge from a cube file of charge density? * Why did the Council of Elrond debate hiding or sending the Ring away, if Sauron wins eventually in that scenario? * How to speed up julia script launch time * Optimal gate drive voltage for MOSFET in DC-DC * Question about the Relativization barrier * How to make an enumerated list's numbering alphabetic per the Hebrew alphabet, in a Hebrew beamer presentation? * 1980s short story - disease of self absorption * How to draw circular arrow and multiline text below a node in TikZ? * Received a 'behavior reminder' from manager. Not sure if it was just me or something she sent to the whole team * Does any country consider housing and food a right? * Why would a corporation secretly trigger kaiju attacks against humanity? * Allow non-GPL plugins in a GPL main program * Is RosAsm assembler self-hosting? * Should teachers encourage good students to help weaker ones? * Setting styles for layer with QML file from URL using PyQGIS * What are these row of bumps along my drywall near the ceiling? more hot questions Question feed Subscribe to RSS Question feed To subscribe to this RSS feed, copy and paste this URL into your RSS reader. [https://retrocomputi] * Retrocomputing * Tour * Help * Chat * Contact * Feedback Company * Stack Overflow * Teams * Advertising * Collectives * Talent * About * Press * Legal * Privacy Policy * Terms of Service * Cookie Settings * Cookie Policy Stack Exchange Network * Technology * Culture & recreation * Life & arts * Science * Professional * Business * API * Data * Blog * Facebook * Twitter * LinkedIn * Instagram Site design / logo (c) 2022 Stack Exchange Inc; user contributions licensed under CC BY-SA. rev 2022.12.9.43104 Your privacy By clicking "Accept all cookies", you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy. Accept all cookies Customize settings