• Please review our updated Terms and Rules here

How to handle system with upper memory banking?

Svenska

Veteran Member
Joined
Mar 19, 2007
Messages
761
Location
Sweden
Hi,

I have been looking into the KC85 (note: not KC85/1) series of computers for a while. They share much of their architecture, are cassette-based, very expandable systems (two module slots in the base system, four module slots each in up to four expansion chassis) and can be upgraded to massive (4 MB) amounts of memory. Floppy support was vendor-provided towards the end of their life, which consisted of at least two expansion chassis (one for the floppy system, one per drive) and supported "MicroDOS" (a clone of CP/M 2).

Since the floppy system is quite rare (and is basically a full Z80 system with its own 64 KB of memory), I am looking into running CP/M on the base system only. Unfortunately, the memory map does not match CP/M well and I don't have a good idea on how to make it work well. I am using the KC85/4 as a baseline as it has 128 KB RAM built-in; previous models can be upgraded with a module.

The memory map consists of four 16 KB pages.
* 0000h..3FFFh is always RAM ("RAM0").
* 4000h..7FFFh is always RAM ("RAM4").
* 8000h..BFFFh is the problem ("RAM8").
* C000h..DFFFh is always ROM ("CAOS C" or "BASIC").
* E000h..FFFFh is always ROM ("CAOS E").

Only RAM8 is mappable, and it may contain:
* RAM Bank 0 or 1 (all 16 KB), which are built-in.
* Additional memory modules (all 16 KB).
* Pixel RAM 0 (all 16 KB; the top 1.5 KB are extremely slow).
* Pixel RAM 1 (10 KB; top 6 KB are shared with Pixel RAM 0).
* Color RAM 0/1 (10 KB; same).

Setting up a 32 KB system is easy, but it won't be very useful. Therefore, I am looking at a 48 KB configuration, with BIOS and BDOS living in RAM8. Which contains all banked and video memory in the system. Additionally, the built-in operating system (CAOS - Cassette Aided Operating System) requires some low memory and the IX register for itself, so I would like to take over the machine fully, which requires a very large BIOS. On the other hand, it could happily live in video memory...

edit: Both the keyboard and cassette systems, as well as the optional SIO module, use interrupts in IM2. Especially the keyboard won't be much fun without.

Do you know any trickery on how to make this somewhat efficient?
 
Last edited:
Have you checked with any KC85 websites to see if they have source for MicroDOS? I expect that it would be necessary to put the changes of MicroDOS into any other CP/M variant. I read the documentation and the KC85/4 looks to have a very flexible memory remapping system. Jump FC which goes to the disk drives and then MicroDOS places RAM in the addresses assigned to CAOS giving a 50K TPA. It has to be possible to the same with different software.

The quote from the D004 programming manual hints at how memory modules can fill addresses C000H to FFFFH.
The system start of the CAOS operating mode takes place like the start of the
PC operating mode using 'JUMP FC'. *)
With 'JUMP FC' the CAOS ROM is switched off and the program in
ROM of FLOPPY DISK BASIS started. This triggers the following
doing from:
- Deleting the shared RAM
- Copying the bootstrap program to the shared RAM
- Release of the processor in FLOPPY DISK BASIS
- Waiting for an acknowledgment in the shared RAM
if the acknowledgment is negative, error message and termination
(Error reporting routine is processed at address 0 in the KC)
with positive acknowledgment and message that CAOS diskette
was started, program continuation (in PC operating mode
see there) - Copy FLOAD from address 0
- Activation ROM in the basic device
- CAOS warm start by jumping to E000H
The processes in the processor system of the FLOPPY DISK BASIS begin
with the release of the RESET. The processor first clears the
dRAM and begins processing the boot program
Address FC00H. The bootloader loads the first 512 bytes of the CAOS
Disk from drive 0 into the dRAM starting at address 9000H. connecting
The acknowledgment then takes place in the shared RAM. These 512 bytes represent
len the BOOT loader for the diskette operating system of the CAOS
operating mode. The task of the BOOT loader is to
to load the operating system from the two system tracks on the diskette and
to start. After the activation of the operating system, the
File INITIAL.SUB loaded. This triggers the loading and starting of the
Disk Extension Program (DEP).
All further accesses to the diskette are made via the command
mando FLOAD or reloadable programs.
*)
Are memory modules used in the CAOS operating mode that
occupy the memory area from C000H to FFFFH (e.g. TEXOR
or 64 KB RAM), these may only be used after the system has started
be switched on. Before a restart with 'JUMP FC 0'
these modules must also be switched 'off line'.
 
Not sure about the sources, but binaries for MicroDOS certainly exist. They won't help though, because MicroDOS cannot run on the KC85; it runs inside the "FLOPPY DISK BASIS" (D004), which is a completely independent system (it has its own processor and memory). The "JUMP FC" command hands over control, turning the KC85 into a fancy terminal.

The floppy disk system was designed for MicroDOS and has a compatible memory layout. But I don't have a D004 (never seen one either), so I want to run CP/M on the base device instead.

Putting RAM in C000h..FFFFh is definitely possible, but is only supported by a 16 KB or a 64 KB memory module (which is already required for the KC85/2 or KC85/3 systems, since they lack RAM4 otherwise). All high-capacity memory modules only ever bank RAM8, and the base device only has two module slots.
 
There was a picture of a dual floppy drive box that didn't need a distinct FLOPPY BASIS enclosure. I have never been able to find any information about it so I don't know if it uses a smaller board that works like the D004 or if it tries a more tradition FDC design with only the main box CPU.

Someone has to have tried a floppy controller module that is simpler than the D004/D008.
 
I think this is what I vaguely remembered of a floppy drive subsystem other than the D004 used with CP/M. If you have already seen this, disregard this posting.
I haven't found schematics and code that would easily allow constructing a replica.
 
Very interesting, thank you. I was not aware of this version before.

This version of CP/M uses a 64 KB module on the KC85/3, which normally lacks RAM4 and RAM8. Crucially, this module is also mapped into the ROM area at C000h, allowing CP/M to run from the top of the address space. In this instance, CP/M does not need to be run from banked memory.

Seems like strictly requiring an M011 (64K) or M022 (16K) module to backfill the ROM area is the only good way forward. :(
 
I don't see how you can get a system with more than 32K of "free ram" (minus the little bit the OS takes at the bottom of memory).

See, and this is a guess, but I assume it works, I'm assuming that you can page flip "between" CPU cycles. By this I mean that when you OUT the command for the page buffer (I assume it's an OUT), by the time the instruction is complete, the switch is made. That means that you can page flip with code living within bank area. If you can't do that, you may still be able to pull it off -- there's a little bit of "reserved" RAM down low that you may be able to squeeze in the banking code.

The key point that if you can run code within the banked area, and swap at strategic points, then the it's straightforward to scatter BIOS and BDOS calls across the banks.

But the problem is that if you try to use buffer space from free ram that's within the banked ram, then the code that works on that buffer space has to share the same bank. So, contrived example, loading a disk sector. The code to load the disk sector needs to be in the "normal" area so it can transfer to the buffer that's also in the "normal" area. Anything that doesn't need to use those buffered areas of free ram can be banked out. For example, you could have the code to read the console in a separate bank, as its only API is CPU registers. So, you have a generic routine to call code across banks (and return from it), and the machine doesn't know the wiser.

It's fiddly, your sys loader has to know about this of course. But I bet it's possible. Low ram has 32 bytes available for the BIOS (0x40-0x60, MP/M uses 0x50-0x60), plus an FCB (32 bytes), and a 128 byte buffer. The FCB and byte buffer are available to the program.

HOWEVER, you COULD snap shot those, that is, copy them out to a work area in your bank first, and leverage those areas for your cross bank purposes, and then restore them when you're done - -but that's expensive. We may not think twice about moving 320 bytes around today, but on a 4MHz Z-80, that's a big deal. But, it's possible if you need it, and if you're hitting a floppy you may well barely notice the overhead.

Anyway, with some careful analysis, it could be done. If you can make it work, then the game would be leaving as little code as necessary in top of that 16K bank, the rest would be available to the TPA. If you used the swapping trick, I bet you could proxy it all in about 2-4K of code, because then you just need trampolines across the banks for all of the BIOS calls. The rest of the BIOS/BDOS lives in the other banks.
 
It is possible to bank the entire CP/M 2.2 (Epson does this on the PX series machines) but it is not trivial because
1. There are a bunch of jump tables and bits that must be in the user visible memory
2. You must deal with calls that pass an address and bounce that data somewhere (notably the DMA buffer) if it would be overlapped by the BDOS/BIOS page in.

The BIOS case is "interesting" because a BDOS call to the BIOS will be be an address for the banked case (any user address already got bounced) but a user BIOS call is using the user bank address. Fortunately the jump table will be in the banked area so you can have two different ones for the cases that matter

So you should be able to get about a 44K TPA, although you'll also need a little bit of code below 48K to drive the video as the video memory also banks over the same space as you'd have put the BDOS and BIOS.
 
Eventually, I decided to simply require a 64 KB module. This is the only module which can overlay all four banks, providing a full 64 KB address space on all machines. Since CP/M is loaded from tape, the internal 16 KB memory (RAM0) keeps a permanent copy of BIOS, BDOS and CCP. It also stores the screen font, initialization code (run from CAOS) and helper routines to maximize TPA. Modules containing banked memory (in RAM8) are used as RAM disks.

Unfortunately, this setup uses up both module slots (64 KB RAM + RAM disk). Together with the slow cassette interface, it's not particularly useful.

Also, the place I knew had a dozen of these at least (and many other things) threw everything away when the owner changed. So I won't probably be able to get real hardware anymore. I implemented all of this within an emulator.
 
As long as you can affect the paging in a few bytes, you can use the memory from 0005 to 005B to set up the pages, and then you can install the BDOS and BIOS anywhere you can page.

There are some challenges, such as when you need to access stack or FCBs in the same page, but as long as you address that, you only need to do something at 0005... And if your architecture doesn't use interrupts you have a fair bit of space for code. The challenge is if you only can map one page from 8000 to BFFF then moving stuff like Stack or FCBs is challenging. But it's not impossible. Might involve juggling some memory.

But it might be plausible and would give you a TPA of 48K.
 
Both keyboard and cassette input require interrupt support. The keyboard uses a standard TV remote control IC and its signal is decoded in software.

Setting up pages requires different code depending on whether the target page is internal or external. Copying data from one bank to another without having enough temporary memory below 0x8000 requires multiple round trips or a bounce buffer in the BIOS page.

With all issues resolved, the result would only run on a KC85/4 (older devices lack internal RAM at 0x4000), with a TPA of at most 44 KB, and still require a banked memory module for the RAM disk. Not worth it, in my opinion.
 
Both keyboard and cassette input require interrupt support. The keyboard uses a standard TV remote control IC and its signal is decoded in software.

Setting up pages requires different code depending on whether the target page is internal or external. Copying data from one bank to another without having enough temporary memory below 0x8000 requires multiple round trips or a bounce buffer in the BIOS page.

With all issues resolved, the result would only run on a KC85/4 (older devices lack internal RAM at 0x4000), with a TPA of at most 44 KB, and still require a banked memory module for the RAM disk. Not worth it, in my opinion.
How large is the keyboard software? Would it be possible to place an additional processor to offload the keyboard routines and free up that space for TPA? It does seem a bit excessive but that fits with KC85/4 method of just throwing more low end hardware at the problem.
 
The keyboard software is about 200 bytes, half of which is the keymap itself. Cassette input is probably similar in size, but has not been written yet. Both are real-time components. Video output is much larger at about 3.2 KB (2 KB font data), owed to the weird KC85/3 video memory layout. The VT-52 emulation takes another 800 bytes.

Replacing the keyboard hardware with another special-purpose module seems excessive indeed, although supporting the V.24 (= RS232) module might be nice.

It is probably easier to combine 64 KB RAM + 1 MB banked memory in a single module (each physical slot provides four addresses with up to 1 MB address space each), which would leave the second slot available. Far more useful than your suggestion in my opinion, and mostly compatible with existing software as well.
 
It is possible to bank the entire CP/M 2.2 (Epson does this on the PX series machines) but it is not trivial because
1. There are a bunch of jump tables and bits that must be in the user visible memory
2. You must deal with calls that pass an address and bounce that data somewhere (notably the DMA buffer) if it would be overlapped by the BDOS/BIOS page in.

The BIOS case is "interesting" because a BDOS call to the BIOS will be be an address for the banked case (any user address already got bounced) but a user BIOS call is using the user bank address. Fortunately the jump table will be in the banked area so you can have two different ones for the cases that matter

So you should be able to get about a 44K TPA, although you'll also need a little bit of code below 48K to drive the video as the video memory also banks over the same space as you'd have put the BDOS and BIOS.
What are the challenges of banking the entire CP/M 2.2 and how can they be overcome to achieve a TPA of about 44K? I would be very happy if you could let me know, thanks
 
What are the challenges of banking the entire CP/M 2.2 and how can they be overcome to achieve a TPA of about 44K? I would be very happy if you could let me know, thanks

You modify the CP/M code to put it simply, so as to add your extra requirements.

You also need to have a DETAILED knowledge of CP/M... I could do it now, but I have recently rewritten CP/M 2.2 from scratch to get that kind of knowledge and am still at beginner level. Others here dedicated years to that level of knowledge and there are some true experts on the forum. Many will help you understand what you don't. You don't need to write your own OS, but you do need to spend considerable time understanding the source until you can modify it. The good news is it's not very large. But you will need to be very familiar with assembly language.

You don't have to put thee jump table in system memory, but it's a good idea since it will increase compatability. You start by getting a copy of a working CP/M set of source code ( If you don't have one, I have one I cleaned up that works in z80 - though others here here have ones that work in 8080 as CP/M did... I translated one for my new assembler ) and you need a functional assembler so you can compile code.

Then you need enough knowledge about your machine to build your own bootloader. To initially know enough to get the CP/M loaded. You will have to load the OS from the DISK ( Including getting your modified code onto the boot disk ).

Then you have two entry points in the zero page to modify and you need to store your BIOS jump table as high as possible in memory since where it starts is the end of memory as most programs recognize it. There's also a single jump in the zero page at 0005 for the BDOS calls and a reset vector at 0000 you need to change. You have some space at 0040 where you can insert some code that most software will leave alone. Your BIOS jump table will also need to initially page out the current memory and page in the BIOS and vice-versa on exit.

Then you hook the jumps at the top of memory and the jumps in the zero page and insert code to page in CP/M when you call it, Page it out when it's done, and enough in the BIOS to load the CCP when it's rebooting.

You will need to check where the stack is, and move it somewhere safe during this process ( just move it to high memory somewhere in your micro-BIOS ) and you'll also need a space to store the FCB if DE is pointing to the memory you're going to page out, so you'll have to copy the FCB to common memory sufficient to move the FCB prior to paging if it's in the memory you're paging out, including updating the vector in DE and restoring this on return to your program.

Which isn't that big a task. But it's not trivial either.

What I would recommend though is building an emulator first. Then use that to check and validate your code.
 
You modify the CP/M code to put it simply, so as to add your extra requirements.

You also need to have a DETAILED knowledge of CP/M... I could do it now, but I have recently rewritten CP/M 2.2 from scratch to get that kind of knowledge and am still at beginner level. Others here dedicated years to that level of knowledge and there are some true experts on the forum. Many will help you understand what you don't. You don't need to write your own OS, but you do need to spend considerable time understanding the source until you can modify it. The good news is it's not very large. But you will need to be very familiar with assembly language.

You don't have to put thee jump table in system memory, but it's a good idea since it will increase compatability. You start by getting a copy of a working CP/M set of source code ( If you don't have one, I have one I cleaned up that works in z80 - though others here here have ones that work in 8080 as CP/M did... I translated one for my new assembler ) and you need a functional assembler so you can compile code.

Then you need enough knowledge about your machine to build your own bootloader. To initially know enough to get the CP/M loaded. You will have to load the OS from the DISK ( Including getting your modified code onto the boot disk ).

Then you have two entry points in the zero page to modify and you need to store your BIOS jump table as high as possible in memory since where it starts is the end of memory as most programs recognize it. There's also a single jump in the zero page at 0005 for the BDOS calls and a reset vector at 0000 you need to change. You have some space at 0040 where you can insert some code that most software will leave alone. Your BIOS jump table will also need to initially page out the current memory and page in the BIOS and vice-versa on exit. gb whatsapp pro

Then you hook the jumps at the top of memory and the jumps in the zero page and insert code to page in CP/M when you call it, Page it out when it's done, and enough in the BIOS to load the CCP when it's rebooting.

You will need to check where the stack is, and move it somewhere safe during this process ( just move it to high memory somewhere in your micro-BIOS ) and you'll also need a space to store the FCB if DE is pointing to the memory you're going to page out, so you'll have to copy the FCB to common memory sufficient to move the FCB prior to paging if it's in the memory you're paging out, including updating the vector in DE and restoring this on return to your program.

Which isn't that big a task. But it's not trivial either.

What I would recommend though is building an emulator first. Then use that to check and validate your code.
Thank you so much @cj7hawk
 
Back
Top