Giter Club home page Giter Club logo

cpm65's Introduction

CP/M-65

What?

This is a native port of Digital Research's seminal 1977 operating system CP/M to the 6502. So far it runs on:

  • The BBC Micro family, including Master, Tube, and Electron; TPA ranges from 14kB on the Electron to 57kB on the Tube.

  • Commodore 64; TPA is 46kB.

  • Commodore VIC-20; TPA is 24kB.

  • Commodore PET 4032, 8032 and 8096; the TPA ranges from 25kB to 57kB on the 8096.

  • Commander X16; TPA is 46kB.

  • Apple IIe; TPA is 46kB.

  • Atari 400/800 XL/XE; 16kB minimum; TPA ranging from 8.5kB up to over 49kB on a 64kB XL/XE machine.

  • Oric 1 and Oric Atmos (but not, currently, the Telestrat) with Microdisc interface; TPA 44kB.

  • Sorbus homebrew 6502-based computer.

  • Olimex' neo6502 6502-based computer.

Unlike the original, it supports relocatable binaries, so allowing unmodified binaries to run on any system: this is necessary as 6502 systems tend to be much less standardised than 8080 and Z80 systems. (The systems above all load programs at different base addresses.)

Currently you can cross-assemble programs from a PC, as well as a working C toolchain with llvm-mos. For native development, there's a basic assembler, a couple of editors, a BASIC, and a byte-compiled Pascal subset and interpreter. You need about 20kB to run the assembler at all, and of course more memory the bigger the program.

No, it won't let you run 8080 programs on the 6502!

CP/M-65 running on a BBC Micro CP/M-65 running on a Commodore 64 CP/M-65 running on a Commander X16 CP/M-65 running on an Apple IIe CP/M-65 running on a Commodore PET 4032 CP/M-65 running on a Commodore PET 8032 CP/M-65 running on a Commodore PET 8096 CP/M-65 running on a Commodore VIC-20 CP/M-65 running on an Atari 800XL CP/M-65 running on an Tangerine Oric 1 CP/M-65 running on the Sorbus Computer CP/M-65 running on the Olimex neo6502

Why?

Why not?

Where?

It's open source on GitHub!

How?

You have two options:

  • Download a binary release. You can then copy this onto a disk for booting on a real machine, or use it in an emulator.

  • or build it yourself.

To build it, you will need the llvm-mos toolchain. CP/M-65 support is available out of the box. Once installed, you should just be able to run the Makefile and you'll get bootable disk images for the Commodore 64 (with 1541 drive) and BBC Micro (producing a 200kB SSSD DFS disk):

make LLVM=<your llvm-mos bin directory here>/ -j$(nproc)

Building CP/M-65 is a bit of a performance because it's aggregating lots of other software, all of which need building in turn. You'll need: a C and C++ compiler, cc1541 (for creating 1541 disk images), cpmtools (for creating CP/M disk images), libfmt (all the C++ tools use this), python3 (for the build system), and FreePascal (because the MADS assembler is written in Pascal). Use these Debian packages:

cc1541 cpmtools libfmt-dev python3 fp-compiler

There are also automated tests which use mame to emulate a reasonable number of the platforms, to verify that they actually work. To use this, install mame, and then run scripts/get-roms.sh to download the necessary system ROMs. Then do:

make LLVM=<your llvm-mos bin directory here>/ -j$(nproc) +mametest

You can add +all to that if you want to do a normal build and run the tests at the same time.

BBC Micro notes

  • To run, do SHIFT+BREAK.

  • Alternatively, if you're on a Tube system, do:

    MODE 3
    *!BOOT
    
  • Alternatively alternatively, if you're on a Master system, do:

    MODE 131
    *DISK
    *!BOOT
    
  • It'll autodetect the amount of available memory. If you're not on a Tube or Master system with shadow RAM, then your screen mode will consume TPA space. On a stock BBC Micro it will run in mode 0, but you'll only get a 2.5kB TPA! Mode 7 will work better here. It will work on the Electron, but you'll have to use mode 6 which will leave you 14kB of TPA. That's unfortunately not enough to run the assembler.

  • The CP/M file system is stored in a big file (called cpmfs). This will expand up to the size defined in diskdefs: currently, 192kB (the largest that will fit on a SSSD disk). All disk access is done through MOS so you should be able to use a ramdisk, hard disk, Econet, ADFS, VDFS, etc. If so, you'll want to define your own disk format and adjust the drive definition in the BIOS to get more space.

  • The BBC Micro port has a SCREEN driver.

Commodore 64 notes

  • Load and run the CPM program to start.

  • It's excruciatingly slow as it uses normal 1541 disk accesses at 300 bytes per second. Everything works, but you won't enjoy it. At some point I want to add a fastloader.

  • The disk image produced is a hybrid of a CP/M file system and a CBMDOS file system, which can be accessed as either. The disk structures used by the other file system are hidden. You get about 170kB on a normal disk.

  • Disk accesses are done using direct block access, so it won't work on anything other than a 1541 (but it should be straightforward to add support for other drives). Sorry.

VIC-20 notes

  • See the Commodore 64 above.

  • You need a fully expanded VIC-20 with all memory banks populated, for the full 35kB.

  • You get a 40x24 screen, emulated using a four-pixel-wide soft font. It doesn't look great but is surprisingly readable, and is vastly better than the VIC-20's default 22x24 screen mode.

  • Disk accesses are slightly faster than the Commodore 64, but only just. It's still a miserable experience.

Commodore PET notes

  • You need a PET 4032, 8032 or 8096 and either a 4040 disk drive or something else which supports the same geometry. The disk image is for a 35-track SSSD system (I made it with cc1541). Adapting it for other drives should be easy.

  • The 4032 is set up for the Graphics Keyboard. The 8032 and 8096 are set up for the Business Keyboard. (It would also be trivial to emulate the Business Keyboard on the Graphics Keyboard, but that is likely to be confusing.)

  • It's much faster than the Comodore 64 --- you can run the assembler in real time without having to worry about retirement.

  • It supports drive 0: only.

  • This port runs completely bare-metal and does not use any ROM routines.

  • The PET port has a SCREEN driver.

Commander X16 notes

  • To use, place the contents of the x16.zip file on the X16's SD card. Load and run the CPM program to start.

  • The CP/M filesystem is stored in a big file called CPMFS. It needs support for the Position command in order to seek within the file. x16emu currently doesn't support this in its host filesystem, so you'll need to use an actual SD card image. (I have a pull request outstanding to add support. An SD2IEC should work too, as these support the same commands. However a real Commodore disk drive will not work.

Apple IIe notes

  • To use, place the contents of the appleiie.po file onto a disk and boot it. The disk image has been munged according to ProDOS sector ordering.

  • It supports a single drive on slot 6 drive 1. You need a 80-column card (but not any aux memory).

  • This port runs completely bare-metal and does not use any ROM routines.

Atari 800 XL/XE notes

  • Standard 720 sectors single-sided single-density disk. The first track is reserved (18 sectors). The rest contains a standard CP/M 2.2 filesystem. Boot with BASIC disabled. This one runs on any Atari with at least 16kB of RAM.

  • Or a 1MB harddisk image for use with drive emulators like SIO2SD, RespeQT, SDrive, AVG Cart etc... You can also mount it off a FAT partition with an SIDE2/3 cartridge and boot from there. That's almost emulation speed on real hardware. This one comes in two flavors. The hd version runs on any Atari with at least 16kB of RAM, the xlhd version is tailored for the XL/XE with at least 64kB of RAM. BIOS, BDOS and CCP live "under" the Atari OS ROM, which leaves over 49kB of TPA.

  • Console is standard 40x24. It has a SCREEN driver.

  • User area 1 contains loadable fonts and a utility to set a new console font (setfnt.com). This consumes at least 1kB of TPA (depending on the padding needed for alignment), but shows proper glyphs like curly braces and tilde.

  • It also contains a loadable software 80 columns driver called tty80drv.com. This will cost you 7kB of TPA for driver code, font data, and screen memory. It has a full SCREEN implementation, too.

Oric notes

  • This disk image is a MFM_DISK format disk as used by Oricutron. (If you need a simple sector image, look at .obj/oric.img.) You get about 350kB on a disk. The CCP, BIOS and BDOS all live in overlay RAM, leaving the entire user memory available for programs.

  • If you're trying to run this on an Oric 1, you need the full upgrade to 64kB (including overlay RAM).

  • Only the Microdisc interface currently works. (It's supposed to work with Jasmin too, but with Oricutron it boots but the keyboard is unresponsive, and on MAME it boots into BASIC, and I don't know why.) Only the first drive is supported. This would be easy to extend if anyone's interested.

  • The console is 40x28. It has a SCREEN driver.

  • The port runs completely bare-metal and does not use any ROM routines.

Sorbus notes

  • The Sorbus Computer is a simple, open and cheap (<$15) machine to learn about the 65(C)02 processor. It combines an original CPU with a Raspberry Pi RP2040 microcontroller that implements all the rest (like RAM, I/O, and clock).

  • For building a full image, it is also possible to copy the compiled binaries into the proper position into the source tree, and just run a global build.

  • More info is available here:

neo6502 notes

  • The neo6502 is a W65C02-based computer using emulated hardware implemented by a RP2040. This can be programmed with various different firmware packages, each emulating a different 6502-based microcomputer. This port is intended for the native firmware package for the neo6502, Morpheus. (The other ports will work if you install the appropriate emulation firmware package.)

  • It is ridiculously fast.

  • To use, unzip the cpm65.zip file into the root directory of the USB stick or other storage card. Then enter load "cpm65.neo" at the prompt. CP/M-65 will run.

  • To run on the emulator, either load it as above, or boot it directly with neo cpm65.neo@8000 run@8010.

  • This port uses an emulated BDOS, meaning that it stores its files as FAT files on the neo6502's USB stick. Most well-behaved CP/M-65 programs will work, but anything which tries to access the raw filesystem won't; such as STAT or DINFO. Files for each drive and user are stored in separate subdirectories. All 16 drives are supported (in directories A to O).

  • Drive B (i.e. /B/ on the storage device) contains some neo6502-specific utilitied. This are in no way complete, or documented.

  • The console is 53x30. It has a SCREEN driver.

Supported programs

Commands include DUMP, STAT, COPY, SUBMIT, ASM, QE and BEDIT plus some smaller utilities. I'd love more --- send me pull requests! The build system supports cc65 assembler and llvm-mos C programs. The native assembler can be used (in emulation) to cross compile programs for CP/M-65.

In the CCP, you get the usual DIR, ERA, REN, TYPE and USER. There is no SAVE as on the relocatable CP/M-65 system assembling images in memory is of questionable utility, but there's a new FREE command which shows memory usage.

You also get a port of Altirra BASIC, an open source Atari BASIC clone. This is called ATBASIC. See below for more details.

Pokey the Penguin loves to read your pull requests!

The assembler

The CP/M-65 assembler is extremely simple and very much customised to work for the CP/M-65 environment. It operates entirely in memory (so it should be fast) but it's written in C (so it's going to be big and slow). It's very very new and is likely to have lots of bugs. There is, at least, a port of the DUMP program to it which assembles, works, and is ready to play with.

Go read cpmfs/asm.txt for the documentation.

The BASIC

Altirra BASIC is an open source recreation of the BASIC used on the Atari 8-bit machines (on which CP/M-65 runs, coincidentally). It has been heavily modified by me to work on CP/M-65. Anything Atari-related has been removed, including graphics, sound, etc. In addition, I have extended the error reporting, added support for case-insensitive keywords (simply because Atari BASIC traditionally requires upper case but most CP/M-65 platforms don't have caps lock keys!), and fairly crudely added file I/O support. There is no screen editor. It is (should be) binary compatible with Atari BASIC, although programs using Atari features which aren't supported will of course not run.

It is currently rather fragile with a number of known (and, probably, unknown) bugs. Please file bug reports!

Atari BASIC is rather different from Microsoft BASIC. Please consult the user manual.

Important! Do not contact the author of Altirra BASIC for anything related *to the CP/M-65 port! Any bugs are strictly my fault.

The editors

BEdit is an incredibly simple line editor modelled after a basic interpreter (command entry, with LOAD, SAVE, LIST, line numbers etc). It's written in machine code and assembled with the CP/M-65 assembler; you can assemble it locally if you have a system with 30kB or more TPA. It'll run on all platforms.

Go read cpmfs/bedit.txt for the documentation.

QE is a much less simple vi-inspired screen editor, written in C. it's much more comfortable to use than BEDIT, but is about five times the size, and will only run on systems with a SCREEN driver, as noted above (you can also use the DEVICES command to see what devices your system supports).

The Pascal

Pascal-M is a Pascal subset intended for use on very small machines. It compiles to bytecode, M-code, which is then run with an interpreter. The compiler is itself written in Pascal-M and is capable of compiling itself (very slowly). There is a basic port to CP/M-65.

To use it, you need to use the interpreter, PINT, to run the compiler to compile your program into an OBP file. This is then translated into an OBB file by PLOAD (not written in Pascal!). You can then run the resulting OBB file with PINT. For example:

A> PINT PASC.OBB HELLO.PAS HELLO.OBP
A> PLOAD HELLO.OBP HELLO.OBB
A> PINT HELLO.OBB

The compiler will also generate a PROGRAM.ERR file containing a copy of any error messages that result from the compilation process.

Sadly, you need at least 36kB of free RAM to run the compiler, and also the disk images for various systems are full, so it's only included for a few platforms.

Pascal-M is considerably simplified from the full Pascal language, with support for only 16-bit integers, but it does support records, sets, enumerations, pointers, nested functions and procedures, etc. Performance isn't brilliant but it does work. CP/M-65 is very basic, consisting of support for text files using the traditional assign/reset/rewrite/close API. You can have as many open at once as you like but you can't seek inside a file. In addition, while new is supported, there is no dispose.

For more information on Pascal-M, see Hans Otten's website. However, do not report bugs on the CP/M-65 port to him --- file bug reports here instead.

Utilities

bin/cpmemu contains a basic CP/M-65 user mode emulator and debugger. It'll run programs on the host environment with an emulated disk, which is very useful for testing and development. To use:

./bin/cpmemu .obj/dump.com diskdefs

Add -d at the front of the command line to drop into the debugger --- use ? for basic help. It can only access 8.3-format all-lowercase filenames in the current directory, but you can also map drives. Use -h for help.

Who?

You may contact me at [email protected], or visit my website at http://www.cowlark.com. There may or may not be anything interesting there. The CP/M-65 project was designed and written by me, David Given.

License

Everything here so far except the contents of the third_party directory is © 2022-2023 David Given, and is licensed under the two-clause BSD open source license. Please see LICENSE for the full text. The tl;dr is: you can do what you like with it provided you don't claim you wrote it.

The exceptions are the contents of the third_party directory, which were written by other people and are not covered by this license. This directory as a whole contains GPL software, which means that if you redistribute the entire directory, you must conform to the terms of the GPL.

third_party/lib6502 contains a hacked copy of the lib6502 library, which is © 2005 Ian Plumarta and is available under the terms of the MIT license. See third_party/lib6502/COPYING.lib6502 for the full text.

third_party/tomsfonts contains a copy of the atari-small font, which is © 1999 Thomas A. Fine and is available under the terms of a minimal free license. See third_party/tomsfonts/LICENSE for the full text.

third_party/altirrabasic contains a hacked copy of Altirra Basic, which is © 2014 Avery Lee and is available under the terms of a minimal free license. See third_party/altirrabasic/LICENSE.md for the full text.

third_party/mads contains a copy of Mad Assembler, which is © 2018-2023 Tomasz Biela and is available under the terms of the MIT license. See third_party/mads/LICENSE for the full text.

third_party/pascal-m contains a extremely hacked up copy of the Pascal-M bytecode compiler and interpreter, which is © 1978-2021 Niklaus Wirth, Mark Rustad and Hans Otten and is available under the terms of the MIT license. See third_party/pascal-m/LICENSE for the full text.

cpm65's People

Contributors

bensonrsi avatar davidgiven avatar ivop avatar venomix666 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cpm65's Issues

VT52 waiting for valid escape sequence

Hi,

First of all, I'm very pleased to see that VT52 was turned into a loadable driver. Very nice!

The question was asked how to print escape from Altirra BASIC. That can be done with chr$(). For example:

? chr$(27);"H";chr$(27);"J"

To home the cursor and clear screen.

I noticed that when an invalid escape sequence is encountered, it keeps waiting for a valid one. ? chr$(27) <enter> and nothing gets echoed to the screen anymore (but Altirra's input routine does receive the characters). After typing H it "escapes" from that state and everything turns to normal again.

@davidgiven How does one exit atbasic? I can't get out of it! :)

Release images

Hi,

Could you also add atari800xlhd.atr to the released disk images? It is currently missing. It's the XL/XE specific port I did recently.

Working on porting the 8080 emulator to CP/M-65, but the warm weather is slowing me down. Also had to do a few tunes for an upcoming game, and did some tests for an 80 columns mode utilizing 3x6 characters and a modified display list to reduce its memory footprint from 7680 to 5760 bytes (excluding the font and driver itself). More on that later.

Regards,
Ivo

Device driver model

Looks like we're going to want this soon, so I'm going to rough out the design here...

The rationale is that various applications need different functionality that we don't want in the base BIOS because it occupies RAM. Example: a terminal emulator. These aren't cheap, and we shouldn't require users to have it in memory if they're not using it. In addition, the original CP/M was hard to extend, leading to a miserable experience when trying to, e.g., change the serial port baud rate. Let's not make that mistake here. At the same time, let's try and keep things as lightweight as possible. Conversely, we also want to be able to inline drivers into the BIOS (e.g. for a screen driver).

So the basic concept is: the BIOS keeps a singly-linked list of drivers. Drivers can be looked up by ID, returning a management routine. An application which wants to use a driver will look it up, stash the address, and can then call routines on it. An application which wants to install a driver can register a new driver on the top of the list, then adjust the memory bounds before returning so the driver code stays resident.

Each driver has a management routine for doing stuff like device lookup and enumeration, and one or more strategy routines, which care entirely driver-specific.

New BIOS entrypoints:

  • BIOS_ADD_DRIVER: writes to the top-of-list address, returning the old address.
    Intention: to install a driver, you call this, providing the new driver's management routine. The old address gets stored for use by the management routine.
    This would also cause the BIOS to recache any strategy routines it may have (see below).

  • BIOS_FIND_DRIVER: takes a 16-bit driver ID. Looks up a driver and returns its strategy routine address, or errors out if there isn't one. (This just calls DRV_FIND on the top driver below.)

That's all there is.

The management routine takes an opcode in Y and a parameter in XA.

  • Y=0: DRV_FIND: given a driver ID in XA, returns its strategy routine address, or 0.
    This compares the name with the driver's own. If it matches, the driver's strategy routine is called. Otherwise, the routine delegates to the next one on the list via the address stored when BIOS_ADD_DRIVER was called.
    A driver may respond to multiple device IDs by returning different strategy routines. e.g. a serial driver can handle multiple devices.
  • Y=1: DRV_ENUMERATE: given a function pointer in XA, calls it once with each device ID supported; then it passes control onto the next driver on the list.
    (I would omit this to begin with. We may not need it at all. I can't really see much use for it other than diagnostics.)

The BIOS code therefore becomes almost trivial, with one pointer of storage (for the current head-of-list). DRV_FIND is a cmp; bne; cpx; beq; jmp (...).

A driver example: the screen.

  • Y=0: get driver version number.
  • Y=1: get screen size.
  • Y=2: set cursor position.
  • Y=3: get cursor position.
  • Y=4: write string at cursor position.
  • Y=5: clear screen.
  • Y=6: clear vertical area (top and bottom lines are supplied).
  • Y=7: scroll up.
  • Y=8: scroll down.
  • Y=9: get key with timeout. (We'd need to define numbers for special keys like cursor keys.)
  • (optional, detected via version number): Y=10: set text style.

A TTY:

  • Y=0: get driver version.
  • Y=1: write character.
  • Y=2: read character with timeout.

(The BIOS would always supply a minimal TTY, which the BIOS console in/out routines would call. Loading a new TTY device would override the old one, and therefore the BIOS would start sending characters there instead. This new one could have a much more sophisticated terminal emulator state machine, implementing something like VT52, implemented by calling the screen driver; so making it platform independent.)

Memory banking issue in Apple 2e

In the Apple 2e CPM-65, it is not working in Apple 22JSE (https://www.scullinsteel.com/apple/e) because the bank switch is not working.

The source code is using two STA $C08b to switch the bank. Based on "Understanding the Apple IIe, by James Fielding Sather, Pg 5-24", bank switch should only work with reading twice on $C08b. Manually changing editing the image with two LDA $C08B fixes the issue.

Excerpt from apple2e.S

sta MEM_BANKING+0xb ; R/W 0xe000 RAM; bank 1 in 0xd000 <- should be changed to lda MEM_BANKING+0xb
sta MEM_BANKING+0xb ; yes, I'm sure <- should be changed to lda MEM_BANKING+0xb

Bug in CCP?

Hi,

I'm observing strange behaviour with CCP. It seems there are leftover bytes from previous commands.

A>bug z*
Z???????
A>dir .txt
A: ASM TXT : BEDIT TXT
A>bug z

Z???????TXT
A>bug zzzzz*
ZZZZZ???K??

Here's the code of bug:

.bss pblock, 165
cpm_fcb = pblock

BDOS_CONOUT = 2
BDOS = start - 3

    .zp savex,1

start:
    ldx #0

    .zrepeat
        lda cpm_fcb+1,x

        ldy #BDOS_CONOUT
        stx savex
        jsr BDOS
        ldx savex
        inx
        cpx #11
    .zuntil eq

    lda #13
    ldy #BDOS_CONOUT
    jsr BDOS

    lda #10
    ldy #BDOS_CONOUT
    jmp BDOS

Looking over ccp.S it looks like the fcb is properly cleared, but somewhere weird values are written to it. I specifically wrote bug with asm as to rule out the llvm toolchain. Any ideas?

asm produces corrupt binaries in some cases

I have a test case where adding a single byte makes the difference between working or not; looks like something's wrong with branch expansion.

Working:

0275  e4 07     ..   cpx 07
  ZPRELO 0276
0277  d0 7e     .~   bne 02f7
0279  60        `    rts 

Not working:

0276  e4 07     ..   cpx 07
  ZPRELO 0277
0278  f0 03     ..   beq 027d
027a  4c f7 01  L..  jmp 01f7
  TPARELO 027c
027d  60        `    rts 

That 0x1f7 is very wrong...

Cursor behaviour

Hi,

Glancing over the new Oric port, I noticed that you only draw a cursor during screen_getchar. Is that intended behaviour? If so, I could greatly simplify and reduce the code in the Atari port (and future 80 columns driver).

Regards,
Ivo

cpm_ram and gettpa behaviour

Hi,

I stumbled upon some strange behaviour which I cannot explain.

See this code in my test branch: https://github.com/ivop/cpm65/blob/test/apps/test.c

Output:

    CP/M-65 for the Atari 800                   
                                                
    A>free                                      
    ZP: 95 to FF. Free: 6A                      
    TPA: 1900 to BC00. Free: A300               
    CCP at: B200                                
    A>test                                      
    start: 9500                                 
    cpm▁ram: 3790                               
    end: ff00                                   
    A>                                          
$ xxd -s 1 -l 1 .obj/test.com
00000001: 21                                       !

Any idea what's going on?

I was compiling a pretty large program and cpm_ram ended up somewhere in the middle of my code.

I have confirmed this with the BBC and Apple][ port.

Regards,
Ivo

Edit: this large program: https://github.com/ivop/cpm65/blob/ubasic/apps/ubasic.c

With a hardcoded higher address it runs. Not that it's a particularly useful basic. It completely lacks syntax errors and is pretty useless, and I won't pursue that path any further, but I was flabbergasted by the weird values of tpa_start and cpm_ram.

I also briefly looked into Palo Alto's Tiny Basic, but that one has no tokenizer.

Microsoft Basic's disassembled source is available in various versions, but that looks daunting to port (CA65 assembly with lots of defines and macro's). Perhaps Altirra Basic. That one is a reimplementation of Atari Basic, open source, 8kB binary, and actively maintained. Rip out the Atari specific stuff like graphics commands, and it could be a viable candidate. Or the Microsoft Basic compatible from "the other CPM-65".

Intel 8080 emulator

Hi,

Th last few days I have been working on this. Eventually I plan to run it on top of CP/M-65 to provide BIOS and possibly BDOS functionality. That would need some copying between 8080 and 6502 memory, for example for writestring if the string crosses a memory bank border. What do you think? I'm pretty excited about it. Something I'd wanted to do for years, emulating the 8080 on a 6502.

https://github.com/ivop/atari8080

Not sure how difficult it would be to port it to other systems, too. C64 REU is slow, but apparently there's also a 256kB banked memory upgrade. Master 128 sideways RAM has some limitations I believe, so that might not work or have less than 64kB for the 8080 environment. Apple 2e seems to have 48kB banks, so that'll probably work. You can even do the same BIT trick (see instruction fetcher in 8080.s) if you only use the lower 32kB of the bank and use two banks.

Regards,
Ivo

Edit: I added a pre-assembled binary. Run with atari800 -xe 8080.xex.

Generic load BDOS from CP/M filesystem

Hi,

You mentioned a generic BDOS loader in my last pull request's comment section. This would indeed be really helpful in case the size of BDOS changes and avoid having to adjust the bootloader and disk image generation, at least for the Atari. Depending on the amount of assumptions we allow, this could be done in a few lines of code.

  • assume BDOS.SYS is first file written to the CP/M fs
  • it is always the first directory entry
  • it is stored in consecutive sectors after the directory
  • we need to adjust for reserved sectors (hardcoded, derived from dph)
  • retrieve first directory sector
  • extract rc counter
  • load that amount of sectors into __USERTPA_START__
  • relocate
  • run

Were you planning on doing this yourself? If not, I could take a stab at it.

Regards,
Ivo

cpm.h header file needed

Trying to build this project and running into an issue where a cpm.h header file is needed. I have a few (including from the z88dk library) but want to make sure I'm using the correct one.

Thanks for any help you can provide.

-Ron

Reusing a static FCB for several file operations

I have an issue in vt52term, where I reuse a global static FCB struct for opening files for both sending and receiving with Xmodem. If I only open/close the files, I get strange behavior such as the file position from the previous file being remembered when opening a new file.

I currently have a working fix where I use memset to zero the entire FCB before starting a new file operation. This works fine, but is this the way it is intended to be done? I tried just setting ex to zero, but this did not solve the problem.

I guess this boils down to two questions:

  1. Is it expected that the FCB must be cleared between a close and open operation, or is this a bug in the BDOS?
  2. If it needs to be cleared, it a complete zeroing with memset needed or is there a smarter way to do this?

Suggestion: have the CCP zero out the bss for transient commands

(I'm interested in CP/M-65 but haven't actually used it, so apologies if this suggestion is inappropriate.)

The CCP knows where a transient command's relocation data starts, and that is the same place its bss starts. COMHDR_TPA_USAGE effectively tells it how large the bss is. It could therefore zero out this region after relocation and before executing the program, which would allow programs to assume their bss is zero-initialised on startup. As I understand it, currently a program has to zero out its own bss if it cares about it actually being zero-initialised.

I appreciate even if the above is reasonable that this is an API change, and programs which relied on this would not work correctly on older versions of CP/M-65.

Thoughts on sound, timer, and joystick drivers

Brain dump below:

SOUND driver
============

Note:       0-119, ten octaves from C0-B9
Channel:    0-2
Volume:     0-15
Noise:      0,1, off/on, ch. 2 only (SN limitation we impose on others,too)

Implementation: three channels is the lowest common denominator of SN, AY,
                SID, and Pokey. Leaves channel 4 on Pokey free for timer.
                For SID, use pulse with 50/50 duty cycle to get a clear tone.
                All others play clear tone. Pokey might use distortion C
                for low notes? Notes outside the playable range are either
                transposed up/down, or ignored. Setting noise switches to
                one of the LFSR noise types.

SOUND_VERSION
    Enter:
    Exit:   A = API version

SOUND_BELL
    Enter:
    Exit:

SOUND_PLAY_NOTE
    Enter:      A = Note, X = Channel
    Exit:

SOUND_SET_VOLUME
    Enter:      A = Volume, X = Channel
    Exit:

SOUND_SET_NOISE
    Enter:      A = 0,1, X = Channel
    Exit:

SOUND_SET_IGNORE_INVALID
    Enter:      A = 0,1
    Exit:


TIMER driver
============

Granularity of time? Hertz might be computational expensive for platforms
that do not specifically have a timer frequency that can be set in hertz.
Perhaps a list of predefined values?
    1Hz, 2Hz, 10Hz, 25Hz, 30Hz, 50Hz, 60Hz, 100Hz, 1000Hz, 15.7kHz (scan line)
Or maybe only one fixed frequency of 1 VBlank?
Commodore PET can only do VB on pin CB1 of its PIA?

Implementation:     Oric, C64, BBC, VIC-20: CIA or VIA timer
                    Atari: Pokey timer or Antic (GPU) VBI
                    PET: PIA vertical retrace
                    Apple: No timers? Not even VB? Only IIc seems to have VBI

TIMER_VERSION
    Enter:
    Exit:   A = API major version, X = API minor version

TIMER_GET_CPU_SPEED     (API 1)
    Enter:
    Exit:   YXA = 24-bit frequency in Hertz
            Could be used for busy waiting timing loops if there's no timer
            capability. Of limitted use on systems with cycle stealing (RAM
            refresh, display memory access)

TIMER_WAIT_VBLANK       (API 2)
    Enter:  X = Number of times (1-255, 0 is a nop)
    Exit:

TIMER_GET_FRAME_RATE    (API 2)
    Enter:
    Exit:   A = 50 or 60

TIMER_SET_FREQUENCY     (API 3)
    Enter:  XA = Frequency (?)
    Exit:

TIMER_SET_CALLBACK      (API 3)
    Enter:  XA = Address

TIMER_START             (API 3)
    Enter:
    Exit:

TIMER_STOP              (API 3)
    Enter:
    Exit:


JOYSTICK
========

JOYSTICK_VERSION
    Enter:
    Exit:   A = API version

JOYSTICK_GET_STATUS
    Enter:  A = 0, 1    (joystick 0 or 1)
    Exit:   A = 0-7,8     (UP, UPRIGHT, RIGHT, etc... clockwise, 8 = center)
            X = trigger

Thoughts? 😄

Updates to lib6502 breaks objdump

objdump does not build with the updated lib6502 (#93) as the zpr addressing mode is not handled by the disassembler:

apps/objdump.c:191:46: error: use of undeclared identifier 'zpr_cb'

Arrow-key constants

You mentioned previously somewhere (in a pull request comment I think) that you intended to define constants for the arrow keys. What do you think about using the ASCII-codes for the ctrl-combinations that *nix has used since forever?

Up ctrl+p [0x10]
Down ctrl+n [0x0E]
Left ctrl+b [0x02]
Right ctrl+f [0x06]

Would the best place to add these on the application side be to drivers.inc/screen.h or do you see any use for the arrow keys in tty applications?

BDOS and CCP outside TPA area

Hi,

The Atari 800XL and later had 64kB of RAM instead of the 48kB maximum of the 400/800 series, but 16kB was "under" the ROM. The ROM can be switched off to access it, but there is a hole were the hardware registers live.

Current CP/M memory map:

0x0000 - 0x04ff zp, stack, Atari OS variables
0x0500 - 0xbbff BIOS, BDOS, TPA, CCP
0xbc00 - 0xbfff DL, screen memory
0xc000 - 0xcfff ROM
0xd000 - 0xd7ff hardware registers
0xd800 - 0xffff ROM

For 800XL and beyond I'd like to lay it out like this:

0x0000 - 0x04ff same
0x0500 - 0xcfff BIOS, DL+screenmem, TPA (screen memory cannot be under ROM, 4kB extra TPA)
0xd000 - 0xd7ff hardware
0xd800 - 0xffff character set copy, minimal keyboard IRQ, BDOS, CCP

What would be an acceptable way to accomplish this? BDOS does not need to claim TPA and warmboot never needs to reload CCP. ROM and interrupts (except for keyboard IRQ) are disabled, except when BIOS needs to call into the Atari OS. Loading sectors into 0xc000-0xcfff directly needs a temporary 128-byte buffer in the BIOS area.

After that, I'd also like to implement a 130XE (or expanded XL) version with an 80-column screen in an extended memory bank that's only visible to ANTIC (the screen processor). Needs ~8Kb or RAM for 320x192 graphics mode, but won't cost you any TPA space if you use extended memory. CPU/ANTIC access can be told to look at base RAM or extended RAM independently.

Regards,
Ivo

Listing multiple lines in BEdit does not work

When attempting to list multiple lines in BEdit, it prints the first line and then emits 0xFF and stops. Also while listing a single line, it emits 0xFF at the end of the line.

I have tested this on my own computer build, BBC Micro (emulated) and C64 (emulated) and the behavior is the same on all three platforms.

As I see nothing obviously wrong in the assembly code for BEdit I have also tried building it with two different version of llvm-mos (SDK v8.0.1 and SDK v1.0.0 from June) to see if it could be an issue with llvs-mos breaking the assembler, but I get the same result in both cases.

ccp internal "ren" does not work

When I try
ren ls.com l.com
the drive works for quite some time, but does not seem to change anything. dir still shows "ls.com".

BTW: Is there a way to move a file from one "user partition" to anonther?

Problem getting C64 working on emulation

Hi,

Yesterday I figured out how to get the VIC-20 and PET versions working on emulation with Vice (I already had b-em and linapple running, and of course atari800 and Altirra with wine), but I'm having problems with the C64. I got my ROMs here:

http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/

I tried about every combination of kernal and 1541 ROMs I could think of, but none work. It seems my true drive emulation of the 1541 works correctly because it works with xvic. Any idea what might be wrong?

Yesterday it got stuck after printing one dot. Today it doesn't even print a dot and goes back to the ready prompt.

kernal.901227-03.bin
characters.901225-01.bin
basic.901226-01.bin

1541-c000.325302-01.bin
1541-e000.901229-05.bin

True drive emulation enabled
RPM: 300
Wobble: 3000
Amplitude: 2000

I tried disabling wobble completely, but that makes no difference.

Regards,
Ivo

Multiple drive support

I have been experimenting with a BIOS for my homebrew computer with two drives (which in this case are two different cmpfs-files on a USB-drive), and it kind of works but I get som strange results:

  • Changing drives with e.g. 'b:' does not work, I guess that this is not implemented in the CCP?
  • Listing files on b: with dir only shows one file on the first attempt but then works fine apart from that the drive is shown as A: in the output.
  • Reading and writing files on b: works fine, but CP/M crashes when it tries to warmboot after running an application from b:, or an application which accesses b: (e.g. 'copy asm.txt b:' crashes, but the copy operation is successful)

Is support for multiple drives fully implemented or am I trying to do something which is not supposed to work at this point?

Build for Apple II 3.5" as well

With the Apple II GS and the Apple II C plus, there are two machines capable of running CP/M 65, but can't due to a different disk format (3.5" instead of 5.25").

(And I'd really like to see CP/M 65 running on my real 2gs instead of just in an emulator.)

Failing to assemble .COMs on macOS (13.6)

The order of assembly arguments in the Makefile doesn't work on macOS. bin/cpmemu $(OBJDIR)/asm.com -pA=$(dir $<) -pB=$(dir $@) ... results in the creation of files named -pA=dir and .pB=dir. It works if you move the -p options in front of the name of the file to execute: bin/cpmemu -pA=$(dir $<) -pB=$(dir $@) $(OBJDIR)/asm.com ...

edit205 is broken

I had to merge it in a half-ported state for reasons --- it doesn't work.

"REN"-like command for changing user ID

How about adding a command like REN just for changing the user?

Something like CHGU filename.ext 1 would change the user ID of the file in the current user ID to the specified one by changing the byte in the file system entry/entries. This would make the USER concept much more usable. If you want to have a file permanently on a different user ID, you can copy it first, CHGU it, and REN it on the new user ID.

I've taken a look at CCP.SYS and BDOS.SYS, but my ideas for a solution would involve a lot of copy/paste. Maybe you've got a better idea how to solve this?

Also, you might have got a better idea than CHGU to name the command.

Having 4MB of space in the filesystem on the Sorbus would really benefit from a less useless concept of user IDs.

6502 Basic

I don't see any implementation of Basic or Pascal. Well, Pascal will be harder to find or write a new one.
But 6502 Basic is already here. Can you compile it with your ASM.COM? I tried, but the format is too different.
BASIC.zip

Writing a new driver in assembly

Hi,

I started working on tty80/screen80 for the Atari. I want it as a loadable driver, but I'm stumbling upon a few problems.

First I started in "asm.com" assembly, but noticed I could not create the needed jump table. .byte <label-1 and .byte >label-1 did not work correctly. The 13 entries for screen:

0C19: 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 4B 0C 0C 0C
0C29: 0C 0C 0C 0C 0C 0C 0C 0C 0C 00

The 3 entries for tty:

0C4F: 61 61 6D 0C 0C 00

The third one here is tty_conout, so that crashes heavily ;) See https://github.com/ivop/cpm65/blob/tty80/apps/a8tty80.asm
Adding an extra dummy byte to the table only works if it is equal to the last one before. Adding .byte 0 messes things up and adds both zeroes to the end of the second table.

0C4F: 63 63 63 6F 0C 0C 0C 00

versus

0C4F: 63 63 63 0C 0C 0C 00 00

So, I tried doing it with clang instead. Added a makefile rule to compile .S instead of .c to .o, link to .com was there already, but somehow the resulting cpm65 binary is not relocated correctly. When the code runs, it is as if it was loaded at $0200 instead of higher up ($0c00 on the XL/XE, $1d00 on the 400/800).

0C30: A0 26     LDY #$26
0C32: 20 04 02  JSR $0204

which should be JSR $0C04 (jmp BDOS). See https://github.com/ivop/cpm65/blob/tty80-2/apps/a8tty80.S

I checked the invocations of llvm with the -v flag, and it seems identical to the C version, except for calling cc1as. But there's a relocation flag there, too.

Anyway, I'm stuck. I could do it all in mads, which I know pretty well, but I'd prefer to use the cpm65 tools.

Regards,
Ivo

Reserving low memory by a TPA program

Hi,

I have been working on the Atari XL port, and it's working now. BIOS, BDOS and CCP are "under" the ROM so to speak, and there's over 49kB of TPA RAM for user programs now.

atari000

But there's a problem with loading fonts. I used to load them at the end of the TPA, lower the upper limit and be done with it. That won't work if that part of RAM is under the ROM. Used to be $bc00, now it'll be $cc00. But everytime the ROM is switched on for CIO or SIO calls the font will disappear and garbage is displayed.

I have already moved the screen memory to low RAM, but that's setup before the rest is run. Now if I want SETFNT.COM to load a font, 1 kilobyte aligned (requirement of the hardware), in low memory, it will overwrite itself while it's running. Is there a way to avoid that? I could reload myself (i.e. setfnt.com loads setfnt.com somewhere higher, relocate it and run again), but I was hoping for something more elegant :)

Regards,
Ivo

Older Apple ][ support

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.. ;-)

munmap_chunk(): invalid pointer

Getting this error during the build process:

MKCBMFS src/arch/commodore+c64_cbmfs
munmap_chunk(): invalid pointer
make: *** [.obj/build.mk:1216: .obj/src/arch/commodore+c64_cbmfs/src/arch/commodore+c64_cbmfs.img] Error 1
make: *** [.obj/build.mk:1475: .obj/src/arch/commodore+pet4032_cbmfs/src/arch/commodore+pet4032_cbmfs.img] Error 1
make: *** [.obj/build.mk:1543: .obj/src/arch/commodore+pet8032_cbmfs/src/arch/commodore+pet8032_cbmfs.img] Error 1
make: *** [.obj/build.mk:1611: .obj/src/arch/commodore+pet8096_cbmfs/src/arch/commodore+pet8096_cbmfs.img] Error 1
make: *** [.obj/build.mk:1714: .obj/src/arch/commodore+vic20_cbmfs/src/arch/commodore+vic20_cbmfs.img] Error 1

Thank you for any help you can provide.

Dependency on a certain version of llvm-mos

For my builds I'm using the official llvm-mos-sdk releases.
While everything works just fine with SDK v.4.0.0:
Screenshot_20231007_192827

The newer versions v.6.0.0 and v.6.1.0 produce not working result:
Screenshot_20231007_192540

I'm focused on Oric but tested Apple][ and it hangs too.

Maybe this is not an issue of cpm65 but IMHO it should be considered when building.

Disk images

Please put disk images in Releases section. Also, because not everyone has these machines, it will be useful to post instructions how to use these images in an emulator and which one is suitable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.