Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Older Apple ][ support #120

Open
andreasbaumann opened this issue Feb 13, 2024 · 5 comments
Open

Older Apple ][ support #120

andreasbaumann opened this issue Feb 13, 2024 · 5 comments

Comments

@andreasbaumann
Copy link

andreasbaumann commented Feb 13, 2024

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
Copy link
Owner

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
Copy link
Author

andreasbaumann commented Feb 20, 2024

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
Copy link
Owner

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
Copy link
Author

andreasbaumann commented Mar 1, 2024

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:

  • A non-waiting screen_getchar was missing (there is a screen_waitchar in lib/screen.h, lib/screen.S) which is able to report a timeout (also in screentest.asm the code doesn't check for the carry bit and just checks the key). In assembly we can check the carry flag, this translates to cpm_error or so for "normal" system calls (in cpm-65 in llvm-mos).
    I was wondering whether to go the C route and use an int16_t for that and passing '-1' to indicate timeout in screen_getchar?
  • Where to get randomness from (I know that Applesoft Basic did it by increasing some KEYIN counter in the zero page)
    Putting that into the screen/tty driver feels a little bit awkward. Currently the seed is 42 in tetris.c which makes gaming
    somewhat predictable. ;-)
    (I also realize that randomness is a dirty side effect and would not end up in a CP/M syscall probably).

@andreasbaumann
Copy link
Author

Created a pull request #177

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants