davidgiven / cpm65

CP/M for the 6502
BSD 2-Clause "Simplified" License
264 stars 24 forks source link

Older Apple ][ support #120

Open andreasbaumann opened 6 months ago

andreasbaumann commented 6 months ago

Hi,

I started a branch in https://github.com/andreasbaumann/cpm65/tree/apple2_plus to tackle older Apple machines with 40-column displays only (or later some Videx 80-columns card).

I can report that CP/M-65 runs just fine on my IMC-2001 Apple ][ plus clone, many thanks for that. :-)

I also started a screen driver, but run into a 2K BIOS issue, I think in the loader (hence I disabled or didn't implement some things yet). Tested with CLS, SCRNTEST, LIFE and QE, they seem to work so far.

Any ideas how to solve that, but the obvious one: to support reading from extends in loader.S?

What about loading the screen driver in userland after booting (like capsdrv.asm)? It's assembled with ASM currently, but this could also be llvm, I suppose.

Another wild idea is to load a SCREEN.SYS after BIOS.SYS (again with a 2K limit).

I can of course also try to learn proper 6502 assembly coding and do some byte shaving.. ;-)

davidgiven commented 6 months ago

Oh, good that it runs --- the Apple II disk system is notoriously touchy.

Regarding making the BIOS bigger: the answer is, I'm not sure. We get up to one track loaded for us automatically, which is currently all we need. Loading another track would mean calling into the Apple II ROM as the disk driver isn't ready yet. That would also mean allocating another track from the already rather small disks for the extra BIOS --- but given that the minimum block size in CP/M is 2kB, we'd have to do that anyway.

The other thing is to build the BIOS twice, once for 40-column machines and once for 80-column machines (I guess you're trying to autodetect whether the card's installed?). That's a bit suboptimal but might be the easiest option.

andreasbaumann commented 6 months ago

The code for the 40 and 80 column mode is not that different, just some address calculations differ and the switching between the two text pages, so this can easily be done with an #ifdef.

I think I found a solution for the memory problem: I followed the ideas in the atari800 port: I'm keeping a very simple TTY driver in bdos.sys, which can run in 40/80 columns mode depending on the Apple model. Then there is a SCRNDRV.COM which loads an extended TTY/SCREEN driver on top which can be as big as it wants (ok, less than the size of a floppy disk perhaps).

This should be ok, as the BIOS bootup and the CCP should work just fine with the first TTY driver. Before using anything which requires a working SCREEN driver one can simply load it with SCRNDRV.COM.

Switches are in apple2e.inc and I can set the model in build.py to

    cflags=["-DAPPLE2E"],
    cflags=["-DAPPLE2PLUS"],

(not sure if that is the smartest thing to do, will see)

There is some trouble ahead, because in principle I would like to call the old TTY driver from the new one (for instance to stop the disk motor). But I need the same cursorx, etc. variables in the TTY and the SCREEN driver. One option would be to put them in well known places in the zero page. I tried in an older commit to have a common.S file to share the variables between bdos.sys and scrndrv.com, but then realised that the first one gets relocated and the second one loaded into user space, so they cannot share variables this way.

davidgiven commented 6 months ago

Very nice!

Re exposing BIOS data: I hadn't thought about that. I think there are probably two ways to do it; the first is to add extra calls to the BIOS strategy table, but this is a little fraught because the numbers must be sequential and it would cause problems if new BIOS calls were ever to be added. The second is to create a driver. Allocating an ID for 'internal BIOS use' would be easy, and then you could add whatever entrypoints you like. The downside there is that there is some overhead for a driver, although it's not a lot --- twenty bytes plus the name, plus two bytes per entrypoint.

Also, it's very easy to persuade the build system to make something twice with different flags. That is, indeed, the whole reason it exists...

andreasbaumann commented 5 months ago

Didn't tackle the BIOS variable sharing thing yet, as I still have a lot of bugs in the screen driver itself I want to test and fix first.

I added a simple tetris from https://codeberg.org/eu/tetris.git, seems ok from the license point of view and is really small. This tests the timeout parameter of the screen_getchar in a natural way (the tetris pieces should move down also when you don't press a key). :-)

Some interesting questions arise: