I'm wondering if some kind person would have a copy of a "CP/M" version of xmodem?By way of background, I'll explain 1) what this is, 2) why it might be useful, 3) why it may not have ever been written 4) solutions, and 5) specific edits needed to existing xmodem source code.1) "CP/M" xmodem is a program that would run on any CP/M machine. It would use CP/M BDOS calls rather than direct I/O.
4) A simple workaround is to send files as Intel Hex. These only use ascii characters under 127. There are programs to turn binary to hex "UNLOAD.COM" and hex to binary "LOAD.COM". There are some limitations - eg all files need to be offset by 256 bytes as LOAD cannot handle the first 256 bytes of a program, as it was designed to create a file that would be loaded into a Z80 at address 256.
Lots of great ideas, thanks!!
Lots of great ideas, thanks!!will check out mload and kermit.
; Assemble with z88dk for RC2014 CP/M
; zcc +cpm -clib=sdcc_iy -v -m --list test.asm -o test
; appmake +glue --ihex --clean -b test -c test
; python slowprint.py > /dev/ttyUSB0 < test__.ihxB> a:sh
MicroShell - Version 2.0
Copyright(c)1982 New Generation Systems
B0% pip test.hex=con:
; CTRL Z to finish downloading
B0% mload test.hex
B0% test
; test program runs (or doesn't run).Re bdos calls, looking at sample BIOS from gaby.de, the code the user writes is supposed to set the 7th bit low. The CP/M ccp for instance, printing a character, just calls that bdos code the user added. So if you call your own bdos code with a jump to 0005, I don't think CP/M gets involved in that?
Any bdos the user has written should send and receive control characters ok. So all characters from 0 to 127 are valid, and that includes ACK and NAK. What won't go through are any binary numbers from 128 to 255, but what if you never use these numbers? A hex file, for instance uses : and numbers 0 to 9 and letters A to F and CR and LF and ^Z at the end. So all those should go through calls to BDOS? (ie a call to 0005H, and then CP/M doesn't even know you did that call)
Z80pack from Udo Munk also has some stuff on CP/NET.
> CP/M was new to me 12-18 months ago so when I went through the BIOS for the
> first time I saw the "and 7Fh' statement in Console In routine and thought
> that was unnecessary and commented it out. I did this for both CP/M-68K as
> well as CP/M2.2 for Z280 and didn't have any issues. I use XMODEM for
> CP/M2.2 and KERMIT for CP/M-68K both using the console I/O for file
> transfer. They both work well.
None of my CP/M or MP/M BIOSen do the masking. Never had a problem as a result.
I think it was in the reference BIOS because at the time 7bit + parity
was the default.
Phillip Stevens suggested Kermit earlier in this post. Very interesting suggestion! I found a 'generic' version of Kermit that uses CP/M calls so doesn't need to be recompiled, and some instructions http://altairclone.com/downloads/cpm/CPM%202.2/Kermit/ReadMe.pdf Ran STAT and told it to link the RDR to UR2 and the PUN to UP2. Then ran Kermit and the command SET PORT UR2 and set it to send a file (the sender outputs the first packet) and a packet of data appeared on the punch device port. Very nice!!Kermit is interesting because you can change the packet size. On an arduino the serial buffer is 64 bytes, so if the packet size is smaller than this, there will never be buffer overruns.
a> MLOAD KERM411=CPSKER,CPVGENPerfect timing, many thanks for those links as that is just what I am looking for.
There is an excellent description of the problem on this site http://www.quicktrip.co.nz/jaqblog/home/69-z80part4 Essentially, calls to the RDR device will hang CP/M, so the workaround is to use IOBYTE and let Kermit direct where things go. Then a few tweaks inside the BIOS to direct output to various UARTs depending on IOBYTE.
It is great fun getting inside the Kermit protocol and getting the first few packets working. I started with a SEND and decoded the first packet to make sure I understood the protocol. Then change it to receiving, and I know the packet I send is the right protocol, then see what comes back. It is a very logical system. There is a workaround for the 7 bit problem for instance and that gets sorted in the first packet. Ultimately, I'd like Kermit to become a generic FAT disk drive for any CP/M system as I think that could be quite useful.
Reading through the Kermit site http://www.columbia.edu/kermit/archive.html there is this rather delightful quote:"Kermit 80 was one of the original Kermit programs, first written in 1981 for the Intertec Superbrain and then made portable to many other CP/M systems, all mutually incompatible: [insert long list of computers]"
Indeed, all "mutually incompatible". There must be a generic CP/M version in all that list! I think what I am looking for here is the source code for CPVGEN.HEX.
; This is the header for the system-independent portion of KERMIT, which
; consists of the following files (in this order):
;
; CPSKER.ASM - this file
; CPSDEF.ASM - definitions for both KERMIT and KERSYS
; CPSMIT.ASM - initialization, main loop, miscellaneous commands
; CPSCOM.ASM - (BYE, EXIT, LOG, SET, SHOW, and STATUS) (Part1 of 2)
; CPSPK1.ASM - the KERMIT protocol handler (SEND, RECEIVE, LOGOUT,
; CPSPK2.ASM - and FINISH commands) (In two parts)
; CPSREM.ASM - REMOTE commands etc
; CPSSER.ASM - SERVER commands etc (Empty as yet)
; CPSTT.ASM - the transparent commands (TRANSMIT, CONNECT)
; CPSCPM.ASM - CP/M commands (DIR, ERA)
; CPSWLD.ASM - the wildcard handler
; CPSCMD.ASM - the command parser
; CPSUTL.ASM - utility routines
; CPSDAT.ASM - Data space and the overlay link space
On Tuesday, 7 August 2018 23:52:05 UTC+10, James Moxham wrote:Reading through the Kermit site http://www.columbia.edu/kermit/archive.html there is this rather delightful quote:"Kermit 80 was one of the original Kermit programs, first written in 1981 for the Intertec Superbrain and then made portable to many other CP/M systems, all mutually incompatible: [insert long list of computers]"Indeed, all "mutually incompatible". There must be a generic CP/M version in all that list! I think what I am looking for here is the source code for CPVGEN.HEX.There are at least two pieces of code you need. In the zip file above the system specifics are contained in cpxsys.asm, and the more generic code in cpsker.asm. You should be able to get a good idea of what is going on from these two files, although there are others to understand too.Good luck with the 8080 mnemonics. :-P
;
; System-dependent initialization
; Called once at program start.
sysinit:
;
; [13] Had to move this call to here, as the prtstr routine needs this
; before the config message is sent out. It has only been moved.
;
call iniadr ;Initialize the BIOS addresses; This one is hopefully the last "improvement" in view of GENERIC
; Kermit. It uses for Character-I/O the BIOS-routines ( instead of the
; "normal" BDOS routines. What does it give us (hopefully) : More speed,
; higher chance of success ( I/O byte implemented in BIOS [if at all]),
; but no "extra" device handling - that's done by BDOS.
;
; How do we "get" the call-adresses? Location 0 has a JMP Warm-Boot
; in CP/M which points into the second location of the BIOS JMP-Vector. The
; next three locations of the JMP-Vector point to the CONSTAT,CONIN,CONOUT
; BIOS-routines. CONOUT wants the character in C.
;
; - Bernie Eiben
iniadr: lhld 1 ;get BIOS Warmstart-address
lxi d,3 ;next adress is CONSTAT in BIOS
dad d
shld bconst+1 ;stuff it into the call-instruction
lxi d,3 ;next adress is CONIN in BIOS
dad d
shld bconin+1 ;
lxi d,3 ;next adress is CONOUT in BIOS
dad d
shld bcnout+1
lxi d,3 ;next address is LIST in BIOS
dad d
shld blsout+1
lxi d,10*3 ;get printer status routine
dad d
shld bprtst
ret ;And return
bconst: jmp $-$ ;Call BIOS directly (filled in by iniadr)
bconin: jmp $-$ ;Call BIOS directly (filled in by iniadr)
bcnout: jmp $-$ ;Call BIOS directly (filled in by iniadr)
blsout: jmp $-$ ;....
bprtst: jmp $-$ ;Call BIOS directly for printer statusAs an aside, I see there are a number of serial UART boards for the RC2014, are these using IOBYTE or are programs being patched to talk to specific ports?
Time for a few tweaks to the CP/M bios. I am hoping that by keeping the kermit packet size under the buffer size of the arduino, I can then push the baud rate up on the data transfer serial port.
Sorry about keeping you awake thinking about this!
| const: | |
| LD A,(iobyte) | |
| AND 00001011b ; Mask off console and high bit of reader | |
| CP 00001010b ; redirected to reader on UR1/2 (Serial A) | |
| JR Z,constA | |
| CP 00000010b ; redirected to reader on TTY/RDR (Serial B) | |
| JR Z,constB | |
| AND $03 ; remove the reader from the mask - only console bits then remain | |
| CP $01 | |
| JR NZ,constB |
| ; MAP LOGICAL CHARACTER DEVICES TO PHYSICAL CHARACTER DEVICES | |
| ; | |
| ; IOBYTE (0003H) | |
| ; ============== | |
| ; | |
| ; Device LST: PUN: RDR: CON: | |
| ; Bit positions 7 6 5 4 3 2 1 0 | |
| ; | |
| ; Dec Binary | |
| ; | |
| ; 0 00 TTY: TTY: TTY: TTY: | |
| ; 1 01 CRT: PTP: PTR: CRT: | |
| ; 2 10 LPT: UP1: UR1: BAT: | |
| ; 3 11 UL1: UP2: UR2: UC1: | |
| ; | |
| ; TTY: Teletype device (slow speed console) | |
| ; CRT: Cathode ray tube device (high speed console) | |
| ; BAT: Batch processing (input from RDR:, output to LST:) | |
| ; UC1: User-defined console | |
| ; PTR: Paper tape reader (high speed reader) | |
| ; UR1: User-defined reader #1 | |
| ; UR2: User-defined reader #2 | |
| ; PTP: Paper tape punch (high speed punch) | |
| ; UP1: User-defined punch #1 | |
| ; UP2: User-defined punch #2 | |
| ; LPT: Line printer | |
| ; UL1: User-defined list device #1 |
JMP BOOT ;-3: Cold start routine JMP WBOOT ; 0: Warm boot - reload command processor JMP CONST ; 3: Console status JMP CONIN ; 6: Console input JMP CONOUT ; 9: Console output JMP LIST ;12: Printer output JMP PUNCH ;15: Paper tape punch output JMP READER ;18: Paper tape reader input