Porting CP/M to the VIC-20: memory map questions

Basic and Machine Language

Moderator: Moderators

Post Reply
hjalfi
Vic 20 Newbie
Posts: 6
Joined: Tue Apr 18, 2023 5:21 am
Website: http://cowlark.com
Location: zurich

Porting CP/M to the VIC-20: memory map questions

Post by hjalfi »

So I have a CP/M port to the 6502. I've got support for the PET, C64 and X16 (among others), so I thought it'd be nice to add support for the VIC-20 too to complete the set. https://github.com/davidgiven/cpm65

I'm planning on targeting a fully expanded machine. The BDOS and CCP (essentially the CP/M kernel) will live in bank 5, at 0xa000.

There are two conflicting design requirements: firstly, I need as much contiguous RAM as possible. It doesn't matter where, but it does need to be contiguous. The CP/M-65 assembler needs about 20kB just to load --- it's written in C. Secondly, I need a screen which is at least 40 columns.

IIUIC: to get 40x12 I have to use a soft font in high resolution mode. This means on the VIC-20 that I need to relocate the character map somewhere in low memory. Except, the VIC chip can only see on-board memory banks, so it's limited to the 1kB at 0x0000-0x0400 and the 4kB at 0x1000-0x2000. That's problematic. I can put the screen at 0x0200 and the character map at 0x1000, but this divides the memory into two. I get 0x1800-0x8000 as my working area. That's 26kB, which is acceptable, but everything from 0x0300 to 0x1000 is wasted.

To get 40x24 I need to use double-height characters. This doubles the size of the character map. Luckily the screen data remains the same size (240 bytes). I now get 0x2000-0x8000 as my working area, which is only 24kB.

Is there anything I've missed here? Are there any cunning tricks to let me place the character data elsewhere?
User avatar
tokra
Vic 20 Scientist
Posts: 1123
Joined: Tue Apr 27, 2010 5:32 pm
Location: Scheessel, Germany

Re: Porting CP/M to the VIC-20: memory map questions

Post by tokra »

With a 160x192 mode you can get 40x24 chars. This fits in the 4K-area from $1000-$1fff. Use chars 16 to 255 at $1000 and start the character-RAM at $1100. This has been the standard-setup and has been used by MINIGRAFIK i.e.

Otherwise you are correct. You cannot get more than 24K contiguos RAM with 160x192 graphics.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Porting CP/M to the VIC-20: memory map questions

Post by Mike »

First of all, welcome to Denial! :mrgreen:
hjalfi wrote:The CP/M-65 assembler needs about 20kB just to load --- it's written in C.
The assembler would need to be completely file based, i.e. read source from file on disk, assemble to file on disk. Even so, this does not leave much room for the symbol table which ideally should reside in RAM.

Do you see any chances to strip seldom used features from the assembler to increase free space at least a little bit?
Secondly, I need a screen which is at least 40 columns. [...] To get 40x24 I need to use double-height characters. This doubles the size of the character map. Luckily the screen data remains the same size (240 bytes). I now get 0x2000-0x8000 as my working area, which is only 24kB.
You might want to take a look at my soft 40 column solution for MINIGRAFIK. The routines have been optimized for fast output (even from BASIC!) and always draw complete text lines instead of just single characters. Below is the built-in character set, which I already chose to be ASCII, not PETSCII, as the former covers 99%+ of available text body. The drawn glyphs 'live' on a bitmap and I can draw any graphical decoration besides the text that I want, making the 'graphical' characters of PETSCII redundant:

Image

For more than just text display you would have to provide a 'shadow' text buffer though, which you could however place in the $0400..$0FFF address range and which thus would not deduct from your 24K TPA.
Is there anything I've missed here? Are there any cunning tricks to let me place the character data elsewhere?
As you have correctly noticed, it is only the internal RAM and the character ROM which the VIC chip can access (the colour RAM goes over an extra 4 bit data path and wouldn't anyhow be usable for graphics data anyway). The memory layout is fixed, so you are set with the 24K TPA in $2000..$7FFF.

You should also keep in mind that the RESET, IRQ and NMI vectors are fixed in the KERNAL ROM, the addresses $0314..$0319 hold RAM-based vectors for the 2nd-level IRQ, BRK and NMI handlers and the RESET routine checks for an autostart signature at $A000.

You find some more details in the sticky post "VIC-20 Memory Layout".

Greetings,

Michael
hjalfi
Vic 20 Newbie
Posts: 6
Joined: Tue Apr 18, 2023 5:21 am
Website: http://cowlark.com
Location: zurich

Re: Porting CP/M to the VIC-20: memory map questions

Post by hjalfi »

I've decided to go for a 40x24 screen even though it uses the extra RAM. The implementation was easy, but it does seem to be creakingly slow. Luckily I've figured out how to do half-step scrolling mostly in hardware; I will need to shuffle the bytes in the screen RAM but not in the bitmap. We'll see if this leaves enough space for the assembler...

Unfortunately right now I'm fighting IEC code. I've finally gotten the tx code working, so I can send commands to the 1541 and it's responding, but it's locking up when trying to actually read data back again. I suspect something in the bus turnaround timing.

One of the problems I'm having is that I'm developing with VICE, which doesn't run the drive and the computer in lockstep. After getting MAME working, apparently neither does that. Also, MAME and VICE fail in different ways! I think the only thing to do now is to cut-and-paste the VIC-20 ROM routines into my own code and see whether _that_ works. The real IEEE-488 bus on the PET was far less trouble...
User avatar
srowe
Vic 20 Scientist
Posts: 1340
Joined: Mon Jun 16, 2014 3:19 pm

Re: Porting CP/M to the VIC-20: memory map questions

Post by srowe »

hjalfi wrote: Fri Apr 21, 2023 4:36 pm One of the problems I'm having is that I'm developing with VICE, which doesn't run the drive and the computer in lockstep. After getting MAME working, apparently neither does that.
This doesn't happen on real hardware either, the IEC protocol is designed for that.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Porting CP/M to the VIC-20: memory map questions

Post by Mike »

hjalfi wrote:I've decided to go for a 40x24 screen even though it uses the extra RAM. The implementation was easy, but it does seem to be creakingly slow. Luckily I've figured out how to do half-step scrolling mostly in hardware; I will need to shuffle the bytes in the screen RAM but not in the bitmap.
My text display routines effectively do around 6000 characters/second and can scroll 30 lines/second, both of which I think is not particularly bad. The scrolling is software only, one big unrolled loop over all columns.

If you do hardware scrolling by remapping the text screen, that probably 'costs' you one or two text lines, as you will need these to cover up the workings of the vertical scroll register. I wonder if you perchance did a row-wise arrangement of the screen codes, which results in a more complicated address layout for the bitmap. The column-wise arrangement really is advantageous here.
Unfortunately right now I'm fighting IEC code. [...]
srowe already wrote about this - demanding lock-step operation is not backed by what you have on real hardware. You have two CPUs, the drive CPU running at 1.00 MHz, the computer CPUs running at different frequencies spanning the range from ~0.9 MHz (264 PAL 7501 in 'slow' mode) up to ~2.1 MHz (128 NTSC 8502 in 'fast' mode). VICE does its best to interleave the operations (provided, the 'drive no idle' option is active), so both CPUs advance their instruction streams corresponding to their relative frequencies. Otherwise most faster bus protocols would fail (JiffyDOS for example synchronises only once per byte and then relies on a strict 10 µs 2-bit time, with NOPs inserted into the transfer code at strategic places).

The standard IEC protocol is clocked by the talking side. As soon as the listener signals it's ready for the next byte, it must be able to follow all CLOCK signal edges, latch the DATA input bits and do an acknowledge on the DATA line upon the last bit sent. If the listener is too slow doing the latter, the talking side will flag an error.

IMO, duplicating the KERNAL IEC code within your BIOS mostly costs you memory, without anything in return. Anything you'd need to access the disc is already present within the KERNAL ROM and the drive CBM DOS. Unless you implement a faster bus protocol, that memory could instead be used to add other functionality to BDOS or resident functions to CCP.

(If you feel above paragraph somewhat goes against a purist viewpoint, you are in good company: even the C128 CP/M used routines in the 128's KERNAL to access the disk drives ;) )
hjalfi
Vic 20 Newbie
Posts: 6
Joined: Tue Apr 18, 2023 5:21 am
Website: http://cowlark.com
Location: zurich

Re: Porting CP/M to the VIC-20: memory map questions

Post by hjalfi »

It lives!

Image

This is using all three memory areas. 0x0200-0x1000 contains the BIOS, which has got all the platform-specific stuff in it. 0xa000-0xc000 contains the BDOS and CCP (with 0x700 bytes free for drivers, if that ever happens). 0x2000-0x8000 is the user TPA of 26kB. This is sufficient to run decent-sized programs and assemble source files up to about 14kB (the assembler uses between 1/3 to 1/2 the size of the source file in RAM). Naturally it's all excruciatingly slow due to the performance of the IEC protocol. I find it hard to believe that someone at Commodore looked at this and said 'this is fine, let's ship it'...

I did eventually realise that to do line-by-line scrolling I'd have to sacrifice two horizontal lines on the screen, so I didn't both and now the screen scrolls two lines at a time. Performance is fine.

Regarding using the kernel IEC routines: that is, in fact, what the C64 port of this does. The problem is the zero page layout. The C64 puts the IEC workspace up near the top of zero page, but the VIC-20 puts it right in the middle, which halves the amount of contiguous zero page. The routines also unconditionally enable interrupts, which mean that I also have to have the interrupt vectors in page 0x300. As I have quite a lot of unusable free memory it actually saves memory to reimplement these routines.

I would like to add support for a fastloader at some point; probably the JiffyDOS one as it seems the best supported and not many fastloaders have write support. I'd really prefer a properly open-source one which can be loaded at run-time, though.

Edit: Forgot to post a link to the disk images; note that some programs here don't work properly due to an llvm-mos bug which is fixed upstream, but I'm waiting for a release. https://github.com/davidgiven/cpm65/releases/tag/dev
User avatar
srowe
Vic 20 Scientist
Posts: 1340
Joined: Mon Jun 16, 2014 3:19 pm

Re: Porting CP/M to the VIC-20: memory map questions

Post by srowe »

hjalfi wrote: Sun Apr 23, 2023 9:50 am I would like to add support for a fastloader at some point; probably the JiffyDOS one as it seems the best supported and not many fastloaders have write support. I'd really prefer a properly open-source one which can be loaded at run-time, though.
You're welcome to use zippy, my implementation of JiffyDOS for the VIC, it's GPLv3

https://eden.mose.org.uk/gitweb/?p=zippy.git;a=summary

Simon
User avatar
polluks
Vic 20 Amateur
Posts: 44
Joined: Sat Apr 29, 2017 4:53 pm
Website: http://www.bilskaja.de
Location: Germany
Occupation: FI

Re: Porting CP/M to the VIC-20: memory map questions

Post by polluks »

Well done! :D
VC20 [WGA103574] + UltiMem
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Porting CP/M to the VIC-20: memory map questions

Post by Mike »

hjalfi wrote:Regarding using the kernel IEC routines: that is, in fact, what the C64 port of this does. The problem is the zero page layout. The C64 puts the IEC workspace up near the top of zero page, but the VIC-20 puts it right in the middle, which halves the amount of contiguous zero page. [...]
Not sure where you got that info from. BASIC and KERNAL of VIC-20 and C64 are very similar, and besides the C64 using $00/$01 for the CPU port, the layout of the zero page ($00..$FF) is exactly the same: $00(or $02)..$8F 'belong' to BASIC and $90..$FA 'belong' to the KERNAL; with $FB..$FE free for users, and $FF being in use during float<->ASCII conversions and thus effectively also allocated for BASIC.

In $90..$FA is where the KERNAL I/O mostly does its things for keyboard, screen, tape, IEC, RS232; with some of the addresses shared between tape, IEC and RS232. Anything that could in the widest sense be regarded as implementation of a language and which only relies on KERNAL routines (i.e. does not use any of the routines in the BASIC interpreter) can use the lower part of the zero page as it pleases.
The routines also unconditionally enable interrupts, which mean that I also have to have the interrupt vectors in page 0x300.
From what I have gathered while taking a peek with the VICE monitor, you are putting some unrelated data there. When you kick out the KERNAL on the VIC-20, at least $0314..$0319 need to be kept alife by pointing them to viable replacement routines for IRQ, BRK and NMI.

...

Two questions: as your CP/M loader supports code relocation, is it viable to "cross-assemble" *.ASM files for the VIC-20 on the C64 instead? Also, is there a tool available to access the CP/M file system within a *.d64 image from the PC?
hjalfi
Vic 20 Newbie
Posts: 6
Joined: Tue Apr 18, 2023 5:21 am
Website: http://cowlark.com
Location: zurich

Re: Porting CP/M to the VIC-20: memory map questions

Post by hjalfi »

(Thanks, Google, you ate the notification email for this message...)

Re the memory map: it's possible I got it confused with the PET. I've been staring at way too many very similar Commodore memory maps recently. Also, I completely forgot about NMI handling. I see that on the VIC-20 the RESTORE key is wired directly to the NMI line. Luckily it looks like I can disable it.

Re cross-assembling binaries: yes. CP/M-65 binaries are completely generic, and the same binary will run on any port --- that now includes the Atari 800, BBC Micro family, VIC-20, C64, PETs 4032, 8032 and 8096, and Apple IIe. No Oric yet. The filesystem is a completely generic cpmfs image, accessible with cpmtools. The corresponding diskdefs file is here: https://github.com/davidgiven/cpm65/blo ... r/diskdefs
Post Reply