From 6c247029bd8fef40d25f18a21830f76e7133ce23 Mon Sep 17 00:00:00 2001 From: keie Date: Mon, 1 Apr 1985 14:44:26 +0000 Subject: [PATCH] *** empty log message *** --- mach/z80/libmon/Makefile | 28 ++ mach/z80/libmon/README | 12 + mach/z80/libmon/char.her.s | 31 ++ mach/z80/libmon/head_em.s | 80 +++ mach/z80/libmon/mon.cpm.s | 924 +++++++++++++++++++++++++++++++++++ mach/z80/libmon/mon.s | 102 ++++ mach/z80/libmon/putchr.nas.s | 28 ++ mach/z80/libmon/putchr.s | 21 + mach/z80/libmon/subr.s | 197 ++++++++ mach/z80/libsys/Makefile | 28 ++ mach/z80/libsys/README | 12 + mach/z80/libsys/char.her.s | 31 ++ mach/z80/libsys/head_em.s | 80 +++ mach/z80/libsys/mon.cpm.s | 924 +++++++++++++++++++++++++++++++++++ mach/z80/libsys/mon.s | 102 ++++ mach/z80/libsys/putchr.nas.s | 28 ++ mach/z80/libsys/putchr.s | 21 + mach/z80/libsys/subr.s | 197 ++++++++ 18 files changed, 2846 insertions(+) create mode 100644 mach/z80/libmon/Makefile create mode 100644 mach/z80/libmon/README create mode 100644 mach/z80/libmon/char.her.s create mode 100644 mach/z80/libmon/head_em.s create mode 100644 mach/z80/libmon/mon.cpm.s create mode 100644 mach/z80/libmon/mon.s create mode 100644 mach/z80/libmon/putchr.nas.s create mode 100644 mach/z80/libmon/putchr.s create mode 100644 mach/z80/libmon/subr.s create mode 100644 mach/z80/libsys/Makefile create mode 100644 mach/z80/libsys/README create mode 100644 mach/z80/libsys/char.her.s create mode 100644 mach/z80/libsys/head_em.s create mode 100644 mach/z80/libsys/mon.cpm.s create mode 100644 mach/z80/libsys/mon.s create mode 100644 mach/z80/libsys/putchr.nas.s create mode 100644 mach/z80/libsys/putchr.s create mode 100644 mach/z80/libsys/subr.s diff --git a/mach/z80/libmon/Makefile b/mach/z80/libmon/Makefile new file mode 100644 index 000000000..c6dfd6fc6 --- /dev/null +++ b/mach/z80/libmon/Makefile @@ -0,0 +1,28 @@ +TAIL=tail.hermac +# Other possibilities are: tail.nascom and tail.cpm + +all: tail.cpm tail.nascom tail.hermac + +install: $(TAIL) + ../../install head_em.s head_em + ../../install $(TAIL) tail_sys + +cmp: $(TAIL) + -../../compare head_em.s head_em + -../../compare $(TAIL) tail_sys + +tail.cpm: mon.cpm.s + @echo Warning: untested, this is an example + arch cr tail.cpm mon.cpm.s + +tail.nascom: mon.s putchr.nas.s + arch cr tail.nascom mon.s putchr.nas.s + +tail.hermac: mon.s char.her.s + arch cr tail.hermac mon.s char.her.s + +opr: + make pr | opr +pr: + @pr `pwd`/Makefile `pwd`/head_em.s + @pr `pwd`/subr.s `pwd`/mon.s `pwd`/mon.cpm.s `pwd`/putchr.s `pwd`/putchr.nas.s `pwd`/char.her.s diff --git a/mach/z80/libmon/README b/mach/z80/libmon/README new file mode 100644 index 000000000..55e9255b9 --- /dev/null +++ b/mach/z80/libmon/README @@ -0,0 +1,12 @@ +This directory contains files for three different environments: +- The Hermac computer. +- The Nascom computer. +- A CPM system. + +The default system used is the Hermac on which this software was +tested. The Nascom environment has been known to work too. +The CPM files are included as an example only. These have never +been tested. + +The definition of TAIL in the Makefile decides which environment +you use. diff --git a/mach/z80/libmon/char.her.s b/mach/z80/libmon/char.her.s new file mode 100644 index 000000000..8ee338af2 --- /dev/null +++ b/mach/z80/libmon/char.her.s @@ -0,0 +1,31 @@ +.define getchar, putchar + +! These getchar and putchar routines can be used for HERMAC computer + +! Read a character from HERMAC-monitor +! Character is returned in a-reg + +getchar: + in a,0xF1 + and 1 + jp z,getchar + in a,0xF0 + cp 0x0D + jp nz,1f + ld a,0x0A +1: ret + +! Write character on HERMAC monitor +! Assumes character in a-reg + +putchar: + cp 0x0A + jp nz,1f + ld a,0x1F +1: push af +2: in a,0xF1 + and 4 + jp z,2b + pop af + out 0xF0,a + ret diff --git a/mach/z80/libmon/head_em.s b/mach/z80/libmon/head_em.s new file mode 100644 index 000000000..1f91d0e35 --- /dev/null +++ b/mach/z80/libmon/head_em.s @@ -0,0 +1,80 @@ +.define EARRAY,ERANGE,EILLINS,EILLSIZE,ECASE,EMON,EHEAP +.define hol0,trapproc,trpim,argv,hp,.reghp,envp,begbss,ignmask +.define savebc,savede,savehl,saveix,saveaf,saveiy,ebadmon + EARRAY = 0 + ERANGE = 1 + EHEAP = 17 + EILLINS=18 + EILLSIZE=19 + ECASE=20 + EMON=25 + ebadmon=25 + + + .base 0x1000 +.text + + ! clear .bss + ld sp,0x7ffe !address of fbase + ld de,endbss + ld h,d + ld l,e + ld bc,begbss + sbc hl,bc + ld a,h + or l + jr z,1f +2: + xor a + ld (de),a + dec de + dec hl + ld a,h + or l + jr nz,2b +1: ! hl == 0 + + ld bc,envp + push bc + ld bc,argv + push bc + ld bc,1 + push bc + call _m_a_i_n + + jp 0x20 + +.bss +begbss: +.data +hol0: + .word 0,0 + .word 0,0 +saveaf: + .word 0 +savebc: + .word 0 +savede: + .word 0 +savehl: + .word 0 +saveix: + .word 0 +saveiy: + .word 0 +ignmask: + .word 0 +hp: + .word 0 +trapproc: + .word 0 +trpim: + .word 0 +argv: + .word 3f +envp: + .word 0 +3: + .asciz 'PROGRAM' +.reghp: + .word endbss diff --git a/mach/z80/libmon/mon.cpm.s b/mach/z80/libmon/mon.cpm.s new file mode 100644 index 000000000..79fd46703 --- /dev/null +++ b/mach/z80/libmon/mon.cpm.s @@ -0,0 +1,924 @@ +.define .mon +.define uxfinish + +! monitor instruction +! a small collection of UNIX system calls implemented under CP/M + +! ux_indir=e.mon +! ux_fork=e.mon +! ux_wait=e.mon +! ux_link=e.mon +! ux_exec=e.mon +! ux_chdir=e.mon +! ux_mknod=e.mon +! ux_chmod=e.mon +! ux_chown=e.mon +! ux_break=e.mon +! ux_stat=e.mon +! ux_seek=e.mon +! ux_mount=e.mon +! ux_umount=e.mon +! ux_setuid=e.mon +! ux_getuid=e.mon +! ux_stime=e.mon +! ux_ptrace=e.mon +! ux_alarm=e.mon +! ux_fstat=e.mon +! ux_pause=e.mon +! ux_utime=e.mon +! ux_stty=e.mon +! ux_gtty=e.mon +! ux_access=e.mon +! ux_nice=e.mon +! ux_sync=e.mon +! ux_kill=e.mon +! ux_dup=e.mon +! ux_pipe=e.mon +! ux_times=e.mon +! ux_prof=e.mon +! ux_unused=e.mon +! ux_setgid=e.mon +! ux_getgid=e.mon +! ux_sig=e.mon +! ux_umask=e.mon +! ux_chroot=e.mon + + EPERM = 1 + ENOENT = 2 + ESRCH = 3 + EINTR = 4 + EIO = 5 + ENXIO = 6 + E2BIG = 7 + ENOEXEC = 8 + EBADF = 9 + ECHILD = 10 + EAGAIN = 11 + ENOMEM = 12 + EACCES = 13 + EFAULT = 14 + ENOTBLK = 15 + EBUSY = 16 + EEXIST = 17 + EXDEV = 18 + ENODEV = 19 + ENOTDIR = 20 + EISDIR = 21 + EINVAL = 22 + ENFILE = 23 + EMFILE = 24 + ENOTTY = 25 + ETXTBSY = 26 + EFBIG = 27 + ENOSPC = 28 + ESPIPE = 29 + EROFS = 30 + EMLINK = 31 + EPIPE = 32 + EDOM = 33 +! Structure of filearea maintained by this implementation +! First iobuffer of 128 bytes +! Then the fcb area of 36 bytes +! The number of bytes left in the buffer, 1 byte +! The iopointer into the buffer, 2 bytes +! The openflag 0 unused, 1 reading, 2 writing, 1 byte +! The filedescriptor starting at 3, 1 byte +! The number of CTRL-Zs that have been absorbed, 1 byte +! The byte read after a sequence of CTRL-Zs, 1 byte + + maxfiles=8 + filesize=128+36+1+2+1+1+1+1 + + filefcb=0 ! pointers point to fcb + position=33 + nleft=36 + iopointer=37 + openflag=39 + fildes=40 + zcount=41 + zsave=42 + + .errnz filefcb + +0: .space maxfiles*filesize + filearea = 0b+128 +sibuf: + .word 0 + .space 82 +siptr: .space 2 +saveargs: + .space 128 +argc: .space 2 +ttymode:.byte 9,9,8,21;.short 06310+RAW*040 ! raw = 040 + +return: + .word 0,0 +uxinit: + xor a + ld c,maxfiles + ld hl,0b +1: ld b,filesize +2: ld (hl),a + inc hl + djnz 2b + dec c + jr nz,1b + ret + +uxfinish: + ld a,maxfiles-1 +1: push af + call closefil + pop af + dec a + cp 0377 + jr nz,1b + ret + +.mon: + pop ix + ld (return),ix ! return adres + pop de ! system call number + xor a + or d + jr nz,unimpld ! too big + ld a,e + and 0300 ! only 64 system calls + jr nz,unimpld + sla e + ld hl,systab + add hl,de + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl + jp (hl) + +systab: + .word e.mon ! ux_indir + .word ux_exit + .word e.mon ! ux_fork + .word ux_read + .word ux_write + .word ux_open + .word ux_close + .word e.mon ! ux_wait + .word ux_creat + .word e.mon ! ux_link + .word ux_unlink + .word e.mon ! ux_exec + .word e.mon ! ux_chdir + .word ux_time + .word e.mon ! ux_mknod + .word e.mon ! ux_chmod + .word e.mon ! ux_chown + .word e.mon ! ux_break + .word e.mon ! ux_stat + .word e.mon ! ux_seek + .word ux_getpid + .word e.mon ! ux_mount + .word e.mon ! ux_umount + .word e.mon ! ux_setuid + .word e.mon ! ux_getuid + .word e.mon ! ux_stime + .word e.mon ! ux_ptrace + .word e.mon ! ux_alarm + .word e.mon ! ux_fstat + .word e.mon ! ux_pause + .word e.mon ! ux_utime + .word e.mon ! ux_stty + .word e.mon ! ux_gtty + .word e.mon ! ux_access + .word e.mon ! ux_nice + .word ux_ftime + .word e.mon ! ux_sync + .word e.mon ! ux_kill + .word unimpld + .word unimpld + .word unimpld + .word e.mon ! ux_dup + .word e.mon ! ux_pipe + .word e.mon ! ux_times + .word e.mon ! ux_prof + .word e.mon ! ux_unused + .word e.mon ! ux_setgid + .word e.mon ! ux_getgid + .word e.mon ! ux_sig + .word unimpld + .word unimpld + .word unimpld + .word unimpld + .word unimpld + .word ux_ioctl + .word unimpld + .word unimpld + .word unimpld + .word unimpld + .word unimpld ! ux_exece + .word e.mon ! ux_umask + .word e.mon ! ux_chroot + .word unimpld + .word unimpld + +emptyfile: + ! searches for a free filestructure + ! returns pointer in iy, 0 if not found + ld ix,filearea + ld l,maxfiles +1: + xor a + or (ix+openflag) + jr nz,3f + ld a,maxfiles+3 + sub l + ld (ix+fildes),a +! #ifdef CPM1 + push iy + push ix + ld de,-128 + add ix,de + push ix + pop de + ld c,setdma + call bdos + pop ix + pop iy + or a ! to clear C +! #endif + ret +3: + ld de,filesize + add ix,de + dec l + jr nz,1b + scf + ret + +findfile: + ld ix,filearea + ld de,filesize +0: + dec a + ret m + add ix,de + jr 0b + +getchar: + push iy + push de + push hl + dec (ix+nleft) + jp p,0f + push ix + pop hl + ld de,-128 + add hl,de + ld (ix+iopointer),l + ld (ix+iopointer+1),h + ex de,hl + push ix + ld c,setdma + call bdos +! #ifdef CPM1 + ld c,seqread +! #else +! ld c,randomread +! #endif + pop de + call bdos + or a + jr z,1f + ld (ix+zcount),0 + pop hl + pop de + pop iy + scf + ret +1: + inc (ix+position) + jr nz,2f + inc (ix+position+1) +2: + ld a,127 + ld (ix+nleft),a +0: + ld h,(ix+iopointer+1) + ld l,(ix+iopointer) + ld a,(hl) + inc hl + ld (ix+iopointer),l + ld (ix+iopointer+1),h + pop hl + pop de + pop iy + ret + or a + +putchar: + push hl + ld h,(ix+iopointer+1) + ld l,(ix+iopointer) + ld (hl),a + dec (ix+nleft) + jr z,0f + inc hl + ld (ix+iopointer+1),h + ld (ix+iopointer),l + pop hl + ret +0: + pop hl +flsbuf: + push hl + push de + push iy + push ix + pop hl + ld de,-128 + add hl,de + ld (ix+iopointer+1),h + ld (ix+iopointer),l + ex de,hl + push ix + ld c,setdma + call bdos + pop de +! #ifdef CPM1 + ld c,seqwrite +! #else +! ld c,randomwrite +! #endif + call bdos + or a + jr z,1f + pop iy + pop de + pop hl + scf + ret +1: + inc (ix+position) + jr nz,2f + inc (ix+position+1) +2: + ld a,128 + ld (ix+nleft),a + ld b,a + push ix + pop hl + ld de,-128 + add hl,de + ld a,26 ! ctrl z +1: ld (hl),a + inc hl + djnz 1b + pop iy + pop de + pop hl + or a + ret + +parsename: + ! parses file name pointed to by hl and fills in fcb + ! of the file pointed to by ix. + ! recognizes filenames as complicated as 'b:file.zot' + ! and as simple as 'x' + + push iy + push ix + pop de + xor a + push de + ld b,36 ! sizeof fcb +0: ld (de),a + inc de + djnz 0b + pop de + inc hl + ld a,(hl) + dec hl + cp ':' ! drive specified ? + jr nz,1f + ld a,(hl) + inc hl + inc hl + dec a + and 15 + inc a ! now 1<= a <= 16 + ld (de),a +1: inc de + ld b,8 ! filename maximum of 8 characters +1: ld a,(hl) + or a + jr nz,8f + dec hl + ld a,'.' +8: + inc hl + cp '.' + jr z,2f + and 0177 ! no parity + bit 6,a + jr z,9f + and 0337 ! UPPER case +9: + ld (de),a + inc de + djnz 1b + ld a,(hl) + inc hl + cp '.' + jr z,3f + ld a,' ' + ld (de),a + inc de + ld (de),a + inc de + ld (de),a + pop iy + ret ! filenames longer than 8 are truncated +2: ld a,' ' ! fill with spaces +0: ld (de),a + inc de + djnz 0b +3: ld b,3 ! length of extension +1: ld a,(hl) + inc hl + or a + jr z,4f + cp 0100 + jp m,2f + and 0137 +2: ld (de),a + inc de + djnz 1b + pop iy + ret +4: ld a,' ' +0: ld (de),a + inc de + djnz 0b + pop iy + ret + +! various routines +ux_close: + pop hl + ld a,l + sub 3 + jp m,1f + cp maxfiles + call m,closefil +1: ld hl,0 + push hl ; jr rtn + +closefil: + call findfile + ld a,(ix+openflag) + or a + jr z,3f + ld (ix+openflag),0 + cp 1 + jr z,2f + ld a,(ix+nleft) + cp 128 + jr z,2f + call flsbuf +2: + push iy + push ix + pop de + ld c,close + call bdos + pop iy +3: ret + +ux_ioctl: + pop hl + ld a,l + sub 3 + jp p,1f + pop hl + ld a,h + cp 't' + jr nz,e.mon + ld a,l + cp 8 + jr z,tiocgetp + cp 9 + jr z,tiocsetp + jr e.mon +1: pop hl + pop hl + ld hl,-1 + push hl ; jr rtn +tiocgetp: + pop de + ld hl,ttymode +2: push bc + ld bc,6 + ldir + ld h,b + ld l,c + pop bc + push hl ; jr rtn +tiocsetp: + pop hl + ld de,ttymode + jr 2b + +ux_time: + call time4 +rtn: ld ix,(return) ; jp (ix) + +ux_ftime: + pop hl + ld (retarea+6),hl + call time4 + ld hl,(retarea+6) + pop de + ld (hl),e + inc hl + ld (hl),d + inc hl + pop de + ld (hl),e + inc hl + ld (hl),d + inc hl + xor a + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + ld ix,(return) ; jp (ix) + +time4: + pop hl + ld (retarea),iy + ld (retarea+2),bc + ld (retarea+4),hl + ld hl,(timebuf+2) + push hl + ld hl,(timebuf) + push hl + ld hl,0 + push hl + ld hl,50 + push hl + call .dvu4 + ld iy,(retarea) + ld bc,(retarea+2) + ld hl,(retarea+4) + jp (hl) +ux_exit: + call uxfinish + ld c,reset + call bdos + ! no return + +ux_creat: + call emptyfile + jr c,openfailed + pop hl + call parsename + pop hl ! file mode, not used under CP/M + push iy + push ix + push ix + pop de + ld c,delete + call bdos + pop de + ld c,makefile + call bdos + pop iy + ld l,1 + jr afteropen +ux_open: + call emptyfile + jr nc,1f +openfailed: + pop hl + pop hl ! remove params + ld hl,EMFILE + push hl + push hl ; jr rtn +1: + pop hl ! filename + call parsename + push iy + ld c,open + push ix + pop de + call bdos + pop iy + pop hl +afteropen: + inc a + jr nz,1f + ld hl,ENOENT + push hl + push hl ; jr rtn +1: + inc l + ld (ix+openflag),l + xor a + ld (ix+nleft),a + ld (ix+zcount),a + ld (ix+zsave),26 + bit 1,l + jr z,2f + ld (ix+nleft),128 +2: + ld (ix+position),a + ld (ix+position+1),a + push ix + pop hl + push bc + ld b,128 +3: dec hl + ld (hl),26 + djnz 3b + pop bc + ld (ix+iopointer+1),h + ld (ix+iopointer),l + ld h,a + ld l,(ix+fildes) + push hl + ld l,a + push hl ; jr rtn + +ux_read: + pop hl + ld a,l + sub 3 + jp p,readfile + ld a,(ttymode+4) + bit 5,a + jr z,1f ! not raw + push iy +! #ifdef CPM1 +!raw echo interface + ld c,consolein + call bdos +! #else +! !no echo interface +! 4: +! ld c,diconio +! ld e,0xff +! call bdos +! or a +! jr z,4b +!end of no echo interface +! #endif + pop iy + pop hl + ld (hl),a + pop hl + ld hl,1 + push hl + ld hl,0 + push hl ; jr rtn +1: + ld hl,sibuf+1 ! read from console assumed + dec (hl) + jp p,2f + dec hl ! go read console line + ld (hl),80 ! max line length + push iy + push hl + ld c,readconsole + ex de,hl + call bdos + ld c,writeconsole + ld e,'\n' + call bdos + pop hl + pop iy + inc hl + inc (hl) + ld (siptr),hl ! ready for transfer + push hl + ld e,(hl) + ld d,0 + add hl,de + ld (hl),'\r' + inc hl + ld (hl),'\n' + pop hl +2: + push bc + pop ix + ld b,(hl) + inc b ! bytes remaining + pop hl ! copy to + pop de ! bytes wanted (probably 512) + push ix + ld ix,(siptr) ! copy from + xor a ! find out minimum of ramaining and wanted + or d + jr nz,3f ! more than 255 wanted (forget that) + ld a,b + cp e + jp m,3f ! not enough remaining + ld b,e +3: + ld c,b ! keep copy +0: + inc ix + ld a,(ix) + ld (hl),a + inc hl + djnz 0b + ld a,(sibuf+1) + sub c + inc a + ld (sibuf+1),a + ld (siptr),ix + pop hl + push bc + ld c,b + push bc ! load 0 + ld b,h + ld c,l + ld ix,(return) ; jp (ix) +readfile: + call findfile + pop de + pop hl ! count + push bc + ld bc,0 +0: + xor a + or l + jr z,1f + dec l +3: +! warning: this may not work if zcount overflows + ld a,(ix+zcount) + or a + jr nz,5f + ld a,(ix+zsave) + cp 26 + jr z,4f + ld (ix+zsave),26 + jr 8f +4: + call getchar + jr c,2f + ld (de),a + sub 26 ! CTRL-Z + jr z,7f + ld a,(ix+zcount) + or a + jr z,6f + ld a,(de) + ld (ix+zsave),a +5: + ld a,26 + dec (ix+zcount) +8: + ld (de),a +6: + inc de + inc bc + jr 0b +1: + dec l + dec h + jp p,3b +2: + pop hl + push bc + ld b,h + ld c,l + ld hl,0 + push hl ; jr rtn +7: + inc (ix+zcount) + jr 4b + +ux_write: + pop hl + ld a,l + sub 3 + jp p,writefile + pop hl ! buffer address + pop de ! count + push de + ld ix,0 + push ix + push bc + ld b,e ! count now in 'db' +0: + ld a,b + or a + jr nz,1f + ld a,d + or a + jr nz,2f + pop bc + ld ix,(return) ; jp (ix) +2: + dec d +1: + dec b + ld e,(hl) + inc hl + push bc + push de + push hl + ld c,writeconsole + call bdos + pop hl + pop de + pop bc + jr 0b +writefile: + call findfile + pop de + pop hl ! count + push bc + ld bc,0 +0: + xor a + or l + jr z,1f + dec l +3: + ld a,(de) + inc de + call putchar + jr c,4f + inc bc + jr 0b +1: + dec l + dec h + jp p,3b + ld ix,0 +2: + pop hl + push bc + ld b,h + ld c,l + push ix + ld ix,(return) ; jp (ix) +4: + ld ix,ENOSPC + jr 2b + +ux_unlink: + pop hl + ld ix,fcb + call parsename + push bc + ld c,delete + ld de,fcb + call bdos + pop bc + inc a + jr nz,1f + ld hl,ENOENT + push hl ; jr rtn +1: + ld hl,0 + push hl ; jr rtn + +ux_getpid: + ld hl,12345 ! nice number + push hl ; jr rtn + + + + + + +retarea: .word 0 ! base of buffer for result values (max 8 bytes) + .word 0 + .word 0 + .word 0 + +trapproc: + .word 0 + +nextp: .byte 0 + +header: +ntext: .word 0 +ndata: .word 0 +nproc: .word 0 +entry: .word 0 +nline: .word 0 + +hp: .word 0 +pb: .word 0 +pd: .word 0 diff --git a/mach/z80/libmon/mon.s b/mach/z80/libmon/mon.s new file mode 100644 index 000000000..0e997f14f --- /dev/null +++ b/mach/z80/libmon/mon.s @@ -0,0 +1,102 @@ +.define .mon + +! Monitor call +! Expects on stack: monitor call number +! parameters +! Implemented are the following monitor calls: +! number 1: exit +! number 3: read +! number 4: write +! number 5: open +! number 6: close +! number 54: ioctl +! If called with a number of a call that is not implemented, +! a trap is generated. + +.mon: + pop ix ! returnaddress + + pop hl ! monitor call number + ld a,l + cp 1 + jp z,monexit ! is it an exit? + cp 3 + jp z,monread ! is it a read? + cp 4 + jp z,monwrite ! is it a write? + cp 5 + jp z,monopen ! is it an open? + cp 6 + jp z,monclose ! is it a close? + cp 54 + jp z,monioctl + jp ebadmon ! trap + +monexit: + jp 0x38 + +monread: + pop hl ! file-descriptor, not used + pop hl ! hl = pointer to output buffer + pop de ! de = number of bytes to be read + ld bc,0 ! bc will contain the number of bytes actually read +1: ld a,d + or e + jr z,2f + call getchar + push af + call putchar ! echo character + pop af + ld (hl),a + inc hl + inc bc + dec de + cp 0x0A ! is it a newline? + jp nz,1b +2: push bc + ld hl,0 + push hl + jp (ix) + +monwrite: + pop hl ! file-descriptor, not used + pop hl ! hl = pointer to output buffer + pop de ! de = number of bytes + push de +1: ld a,e + or d + jr z,2f + ld a,(hl) + call putchar + inc hl +dec de + jp 1b + +2: push de ! no error + jp (ix) + + +monopen: + pop hl ! pointer to string + pop hl ! flag + ld hl,-1 + push hl ! push file descriptor + push hl ! push error code twice + push hl + jp (ix) + +monclose: + ex (sp),hl ! pop file descriptor and push error code + pop hl ! file descriptor + ld hl,-1 + push hl ! push error code twice + push hl + jp (ix) + +monioctl: + pop hl ! file descriptor + pop hl ! request + ld hl,0 + ex (sp),hl ! remove argp and push error code + jp (ix) + diff --git a/mach/z80/libmon/putchr.nas.s b/mach/z80/libmon/putchr.nas.s new file mode 100644 index 000000000..e0dbdeb67 --- /dev/null +++ b/mach/z80/libmon/putchr.nas.s @@ -0,0 +1,28 @@ +.define putchr +! output routine in monitor +CRT = 0x013B +! output a charcter +! entry: ascii character in a +putchr: + push hl + push bc + ld hl,tab + ld b,5 +1: cp (hl) + jr z,fetch + inc hl + inc hl + djnz 1b +2: call CRT + pop bc + pop hl + ret +fetch: inc hl + ld a,(hl) + jr 2b +! conversion table for nascom characters +tab: .byte 0x0D,0x00 + .byte 0x1B,0x1E + .byte 0x08,0x1D + .byte 0x0A,0x1F + .byte 0x7F,0x00 diff --git a/mach/z80/libmon/putchr.s b/mach/z80/libmon/putchr.s new file mode 100644 index 000000000..db15bf216 --- /dev/null +++ b/mach/z80/libmon/putchr.s @@ -0,0 +1,21 @@ +.define putchr + +putchr: + push hl + push de + push bc + cp 0x0A + jr nz,1f + ld a,0x1F +1: + ld c,a +2: + in a,0xF1 + and 4 + jr z,2b + ld a,c + out 0xF0,a + pop bc + pop de + pop hl + ret diff --git a/mach/z80/libmon/subr.s b/mach/z80/libmon/subr.s new file mode 100644 index 000000000..253048892 --- /dev/null +++ b/mach/z80/libmon/subr.s @@ -0,0 +1,197 @@ +.define _read,_write,_ioctl,_getpid,_open,_close,_exit,_errno +_read: + ld (savebc),bc + push af + pop bc + ld (saveaf),bc ! save all registers in savereg + ld (savede),de + ld (savehl),hl + ld (saveix),ix + ex (sp),hl ! return address in hl + pop bc ! skip return address + pop bc ! get fd + ld a,b ! check fd = 0 + or c + jr nz,errrd + pop de ! get buffer + pop bc ! get count + ld ix,0 ! reset counter + push bc + push de + push ix + push hl ! return address + ex de,hl ! buffer to hl +1: ld a,b + or c + jr z,done ! done if count = 0 + call getchr + ld (hl),a + inc hl ! increment pointer + inc ix ! increment char counter + dec bc ! decrement count + cp 0xA + jr nz,1b ! done if char = CR +done: + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + ret +errrd: + push bc + push hl ! return address + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + ld ix,-1 + ret + +_write: + ld (savebc),bc + push af + pop bc + ld (saveaf),bc ! save all registers in savereg + ld (savede),de + ld (savehl),hl + ld (saveix),ix + ex (sp),hl ! return address in hl + pop de ! skip return address + pop de ! get fd + ld a,e ! check for fd = 1 + cp 1 + jr nz,errwr + ld a,d + or a + jr nz,errwr + pop de ! buffer in de + pop bc ! count in bc + push bc + push de + push de + push hl + ex de,hl ! buffer in hl + ld e,c + ld d,b ! count also in de +1: ld a,b + or c + jr z,exit + ld a,(hl) + call putchr + inc hl + dec bc + jr 1b +errwr: + push de + push hl + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + ld ix,-1 ! error in fd + ret +exit: + push de ! count on stack + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + pop ix ! return count to caller + ret + +_ioctl: + ret +_getpid: + ret + +! open return a file descriptor (0,1,2) +! depending on 'mode' +! mode 2 doesn't work!! +_open: + ld (savebc),bc + push af + pop bc + ld (saveaf),bc ! save all registers in savereg + ld (savede),de + ld (savehl),hl + ld (saveix),ix + pop bc ! return address + pop de ! name pointer + pop ix ! mode (0 for read, + ! 1 for write) + push ix + push de + push bc + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + ret ! return fd = 0 for read + ! fd = 1 for write + +_close: + ld ix,0 ! return succes + ret +_exit: +jp 0x38 +.data +_errno: + .word 0 +! output routine in monitor +CRT = 0x013B +! output a charcter +! entry: ascii character in a +.text +!putchr: +! push hl +! push bc +! ld hl,tab +! ld b,5 +!1: cp (hl) +! jr z,fetch +! inc hl +! inc hl +! djnz 1b +!2: call CRT +! pop bc +! pop hl +! ret +!fetch: inc hl +! ld a,(hl) +! jr 2b +!! conversion table for nascom characters +!tab: .byte 0x0D,0x00 +! .byte 0x1B,0x1E +! .byte 0x08,0x1D +! .byte 0x0A,0x1F +! .byte 0x7F,0x00 + +KBD = 0x69 +! get character from keyboard +getchr: + call KBD + jr nc,getchr + cp 0x1F + jr z,CR + cp 0x1D + jr z,BS + ret +CR: ld a,0xA + ret +BS: ld a,0x8 + ret diff --git a/mach/z80/libsys/Makefile b/mach/z80/libsys/Makefile new file mode 100644 index 000000000..c6dfd6fc6 --- /dev/null +++ b/mach/z80/libsys/Makefile @@ -0,0 +1,28 @@ +TAIL=tail.hermac +# Other possibilities are: tail.nascom and tail.cpm + +all: tail.cpm tail.nascom tail.hermac + +install: $(TAIL) + ../../install head_em.s head_em + ../../install $(TAIL) tail_sys + +cmp: $(TAIL) + -../../compare head_em.s head_em + -../../compare $(TAIL) tail_sys + +tail.cpm: mon.cpm.s + @echo Warning: untested, this is an example + arch cr tail.cpm mon.cpm.s + +tail.nascom: mon.s putchr.nas.s + arch cr tail.nascom mon.s putchr.nas.s + +tail.hermac: mon.s char.her.s + arch cr tail.hermac mon.s char.her.s + +opr: + make pr | opr +pr: + @pr `pwd`/Makefile `pwd`/head_em.s + @pr `pwd`/subr.s `pwd`/mon.s `pwd`/mon.cpm.s `pwd`/putchr.s `pwd`/putchr.nas.s `pwd`/char.her.s diff --git a/mach/z80/libsys/README b/mach/z80/libsys/README new file mode 100644 index 000000000..55e9255b9 --- /dev/null +++ b/mach/z80/libsys/README @@ -0,0 +1,12 @@ +This directory contains files for three different environments: +- The Hermac computer. +- The Nascom computer. +- A CPM system. + +The default system used is the Hermac on which this software was +tested. The Nascom environment has been known to work too. +The CPM files are included as an example only. These have never +been tested. + +The definition of TAIL in the Makefile decides which environment +you use. diff --git a/mach/z80/libsys/char.her.s b/mach/z80/libsys/char.her.s new file mode 100644 index 000000000..8ee338af2 --- /dev/null +++ b/mach/z80/libsys/char.her.s @@ -0,0 +1,31 @@ +.define getchar, putchar + +! These getchar and putchar routines can be used for HERMAC computer + +! Read a character from HERMAC-monitor +! Character is returned in a-reg + +getchar: + in a,0xF1 + and 1 + jp z,getchar + in a,0xF0 + cp 0x0D + jp nz,1f + ld a,0x0A +1: ret + +! Write character on HERMAC monitor +! Assumes character in a-reg + +putchar: + cp 0x0A + jp nz,1f + ld a,0x1F +1: push af +2: in a,0xF1 + and 4 + jp z,2b + pop af + out 0xF0,a + ret diff --git a/mach/z80/libsys/head_em.s b/mach/z80/libsys/head_em.s new file mode 100644 index 000000000..1f91d0e35 --- /dev/null +++ b/mach/z80/libsys/head_em.s @@ -0,0 +1,80 @@ +.define EARRAY,ERANGE,EILLINS,EILLSIZE,ECASE,EMON,EHEAP +.define hol0,trapproc,trpim,argv,hp,.reghp,envp,begbss,ignmask +.define savebc,savede,savehl,saveix,saveaf,saveiy,ebadmon + EARRAY = 0 + ERANGE = 1 + EHEAP = 17 + EILLINS=18 + EILLSIZE=19 + ECASE=20 + EMON=25 + ebadmon=25 + + + .base 0x1000 +.text + + ! clear .bss + ld sp,0x7ffe !address of fbase + ld de,endbss + ld h,d + ld l,e + ld bc,begbss + sbc hl,bc + ld a,h + or l + jr z,1f +2: + xor a + ld (de),a + dec de + dec hl + ld a,h + or l + jr nz,2b +1: ! hl == 0 + + ld bc,envp + push bc + ld bc,argv + push bc + ld bc,1 + push bc + call _m_a_i_n + + jp 0x20 + +.bss +begbss: +.data +hol0: + .word 0,0 + .word 0,0 +saveaf: + .word 0 +savebc: + .word 0 +savede: + .word 0 +savehl: + .word 0 +saveix: + .word 0 +saveiy: + .word 0 +ignmask: + .word 0 +hp: + .word 0 +trapproc: + .word 0 +trpim: + .word 0 +argv: + .word 3f +envp: + .word 0 +3: + .asciz 'PROGRAM' +.reghp: + .word endbss diff --git a/mach/z80/libsys/mon.cpm.s b/mach/z80/libsys/mon.cpm.s new file mode 100644 index 000000000..79fd46703 --- /dev/null +++ b/mach/z80/libsys/mon.cpm.s @@ -0,0 +1,924 @@ +.define .mon +.define uxfinish + +! monitor instruction +! a small collection of UNIX system calls implemented under CP/M + +! ux_indir=e.mon +! ux_fork=e.mon +! ux_wait=e.mon +! ux_link=e.mon +! ux_exec=e.mon +! ux_chdir=e.mon +! ux_mknod=e.mon +! ux_chmod=e.mon +! ux_chown=e.mon +! ux_break=e.mon +! ux_stat=e.mon +! ux_seek=e.mon +! ux_mount=e.mon +! ux_umount=e.mon +! ux_setuid=e.mon +! ux_getuid=e.mon +! ux_stime=e.mon +! ux_ptrace=e.mon +! ux_alarm=e.mon +! ux_fstat=e.mon +! ux_pause=e.mon +! ux_utime=e.mon +! ux_stty=e.mon +! ux_gtty=e.mon +! ux_access=e.mon +! ux_nice=e.mon +! ux_sync=e.mon +! ux_kill=e.mon +! ux_dup=e.mon +! ux_pipe=e.mon +! ux_times=e.mon +! ux_prof=e.mon +! ux_unused=e.mon +! ux_setgid=e.mon +! ux_getgid=e.mon +! ux_sig=e.mon +! ux_umask=e.mon +! ux_chroot=e.mon + + EPERM = 1 + ENOENT = 2 + ESRCH = 3 + EINTR = 4 + EIO = 5 + ENXIO = 6 + E2BIG = 7 + ENOEXEC = 8 + EBADF = 9 + ECHILD = 10 + EAGAIN = 11 + ENOMEM = 12 + EACCES = 13 + EFAULT = 14 + ENOTBLK = 15 + EBUSY = 16 + EEXIST = 17 + EXDEV = 18 + ENODEV = 19 + ENOTDIR = 20 + EISDIR = 21 + EINVAL = 22 + ENFILE = 23 + EMFILE = 24 + ENOTTY = 25 + ETXTBSY = 26 + EFBIG = 27 + ENOSPC = 28 + ESPIPE = 29 + EROFS = 30 + EMLINK = 31 + EPIPE = 32 + EDOM = 33 +! Structure of filearea maintained by this implementation +! First iobuffer of 128 bytes +! Then the fcb area of 36 bytes +! The number of bytes left in the buffer, 1 byte +! The iopointer into the buffer, 2 bytes +! The openflag 0 unused, 1 reading, 2 writing, 1 byte +! The filedescriptor starting at 3, 1 byte +! The number of CTRL-Zs that have been absorbed, 1 byte +! The byte read after a sequence of CTRL-Zs, 1 byte + + maxfiles=8 + filesize=128+36+1+2+1+1+1+1 + + filefcb=0 ! pointers point to fcb + position=33 + nleft=36 + iopointer=37 + openflag=39 + fildes=40 + zcount=41 + zsave=42 + + .errnz filefcb + +0: .space maxfiles*filesize + filearea = 0b+128 +sibuf: + .word 0 + .space 82 +siptr: .space 2 +saveargs: + .space 128 +argc: .space 2 +ttymode:.byte 9,9,8,21;.short 06310+RAW*040 ! raw = 040 + +return: + .word 0,0 +uxinit: + xor a + ld c,maxfiles + ld hl,0b +1: ld b,filesize +2: ld (hl),a + inc hl + djnz 2b + dec c + jr nz,1b + ret + +uxfinish: + ld a,maxfiles-1 +1: push af + call closefil + pop af + dec a + cp 0377 + jr nz,1b + ret + +.mon: + pop ix + ld (return),ix ! return adres + pop de ! system call number + xor a + or d + jr nz,unimpld ! too big + ld a,e + and 0300 ! only 64 system calls + jr nz,unimpld + sla e + ld hl,systab + add hl,de + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl + jp (hl) + +systab: + .word e.mon ! ux_indir + .word ux_exit + .word e.mon ! ux_fork + .word ux_read + .word ux_write + .word ux_open + .word ux_close + .word e.mon ! ux_wait + .word ux_creat + .word e.mon ! ux_link + .word ux_unlink + .word e.mon ! ux_exec + .word e.mon ! ux_chdir + .word ux_time + .word e.mon ! ux_mknod + .word e.mon ! ux_chmod + .word e.mon ! ux_chown + .word e.mon ! ux_break + .word e.mon ! ux_stat + .word e.mon ! ux_seek + .word ux_getpid + .word e.mon ! ux_mount + .word e.mon ! ux_umount + .word e.mon ! ux_setuid + .word e.mon ! ux_getuid + .word e.mon ! ux_stime + .word e.mon ! ux_ptrace + .word e.mon ! ux_alarm + .word e.mon ! ux_fstat + .word e.mon ! ux_pause + .word e.mon ! ux_utime + .word e.mon ! ux_stty + .word e.mon ! ux_gtty + .word e.mon ! ux_access + .word e.mon ! ux_nice + .word ux_ftime + .word e.mon ! ux_sync + .word e.mon ! ux_kill + .word unimpld + .word unimpld + .word unimpld + .word e.mon ! ux_dup + .word e.mon ! ux_pipe + .word e.mon ! ux_times + .word e.mon ! ux_prof + .word e.mon ! ux_unused + .word e.mon ! ux_setgid + .word e.mon ! ux_getgid + .word e.mon ! ux_sig + .word unimpld + .word unimpld + .word unimpld + .word unimpld + .word unimpld + .word ux_ioctl + .word unimpld + .word unimpld + .word unimpld + .word unimpld + .word unimpld ! ux_exece + .word e.mon ! ux_umask + .word e.mon ! ux_chroot + .word unimpld + .word unimpld + +emptyfile: + ! searches for a free filestructure + ! returns pointer in iy, 0 if not found + ld ix,filearea + ld l,maxfiles +1: + xor a + or (ix+openflag) + jr nz,3f + ld a,maxfiles+3 + sub l + ld (ix+fildes),a +! #ifdef CPM1 + push iy + push ix + ld de,-128 + add ix,de + push ix + pop de + ld c,setdma + call bdos + pop ix + pop iy + or a ! to clear C +! #endif + ret +3: + ld de,filesize + add ix,de + dec l + jr nz,1b + scf + ret + +findfile: + ld ix,filearea + ld de,filesize +0: + dec a + ret m + add ix,de + jr 0b + +getchar: + push iy + push de + push hl + dec (ix+nleft) + jp p,0f + push ix + pop hl + ld de,-128 + add hl,de + ld (ix+iopointer),l + ld (ix+iopointer+1),h + ex de,hl + push ix + ld c,setdma + call bdos +! #ifdef CPM1 + ld c,seqread +! #else +! ld c,randomread +! #endif + pop de + call bdos + or a + jr z,1f + ld (ix+zcount),0 + pop hl + pop de + pop iy + scf + ret +1: + inc (ix+position) + jr nz,2f + inc (ix+position+1) +2: + ld a,127 + ld (ix+nleft),a +0: + ld h,(ix+iopointer+1) + ld l,(ix+iopointer) + ld a,(hl) + inc hl + ld (ix+iopointer),l + ld (ix+iopointer+1),h + pop hl + pop de + pop iy + ret + or a + +putchar: + push hl + ld h,(ix+iopointer+1) + ld l,(ix+iopointer) + ld (hl),a + dec (ix+nleft) + jr z,0f + inc hl + ld (ix+iopointer+1),h + ld (ix+iopointer),l + pop hl + ret +0: + pop hl +flsbuf: + push hl + push de + push iy + push ix + pop hl + ld de,-128 + add hl,de + ld (ix+iopointer+1),h + ld (ix+iopointer),l + ex de,hl + push ix + ld c,setdma + call bdos + pop de +! #ifdef CPM1 + ld c,seqwrite +! #else +! ld c,randomwrite +! #endif + call bdos + or a + jr z,1f + pop iy + pop de + pop hl + scf + ret +1: + inc (ix+position) + jr nz,2f + inc (ix+position+1) +2: + ld a,128 + ld (ix+nleft),a + ld b,a + push ix + pop hl + ld de,-128 + add hl,de + ld a,26 ! ctrl z +1: ld (hl),a + inc hl + djnz 1b + pop iy + pop de + pop hl + or a + ret + +parsename: + ! parses file name pointed to by hl and fills in fcb + ! of the file pointed to by ix. + ! recognizes filenames as complicated as 'b:file.zot' + ! and as simple as 'x' + + push iy + push ix + pop de + xor a + push de + ld b,36 ! sizeof fcb +0: ld (de),a + inc de + djnz 0b + pop de + inc hl + ld a,(hl) + dec hl + cp ':' ! drive specified ? + jr nz,1f + ld a,(hl) + inc hl + inc hl + dec a + and 15 + inc a ! now 1<= a <= 16 + ld (de),a +1: inc de + ld b,8 ! filename maximum of 8 characters +1: ld a,(hl) + or a + jr nz,8f + dec hl + ld a,'.' +8: + inc hl + cp '.' + jr z,2f + and 0177 ! no parity + bit 6,a + jr z,9f + and 0337 ! UPPER case +9: + ld (de),a + inc de + djnz 1b + ld a,(hl) + inc hl + cp '.' + jr z,3f + ld a,' ' + ld (de),a + inc de + ld (de),a + inc de + ld (de),a + pop iy + ret ! filenames longer than 8 are truncated +2: ld a,' ' ! fill with spaces +0: ld (de),a + inc de + djnz 0b +3: ld b,3 ! length of extension +1: ld a,(hl) + inc hl + or a + jr z,4f + cp 0100 + jp m,2f + and 0137 +2: ld (de),a + inc de + djnz 1b + pop iy + ret +4: ld a,' ' +0: ld (de),a + inc de + djnz 0b + pop iy + ret + +! various routines +ux_close: + pop hl + ld a,l + sub 3 + jp m,1f + cp maxfiles + call m,closefil +1: ld hl,0 + push hl ; jr rtn + +closefil: + call findfile + ld a,(ix+openflag) + or a + jr z,3f + ld (ix+openflag),0 + cp 1 + jr z,2f + ld a,(ix+nleft) + cp 128 + jr z,2f + call flsbuf +2: + push iy + push ix + pop de + ld c,close + call bdos + pop iy +3: ret + +ux_ioctl: + pop hl + ld a,l + sub 3 + jp p,1f + pop hl + ld a,h + cp 't' + jr nz,e.mon + ld a,l + cp 8 + jr z,tiocgetp + cp 9 + jr z,tiocsetp + jr e.mon +1: pop hl + pop hl + ld hl,-1 + push hl ; jr rtn +tiocgetp: + pop de + ld hl,ttymode +2: push bc + ld bc,6 + ldir + ld h,b + ld l,c + pop bc + push hl ; jr rtn +tiocsetp: + pop hl + ld de,ttymode + jr 2b + +ux_time: + call time4 +rtn: ld ix,(return) ; jp (ix) + +ux_ftime: + pop hl + ld (retarea+6),hl + call time4 + ld hl,(retarea+6) + pop de + ld (hl),e + inc hl + ld (hl),d + inc hl + pop de + ld (hl),e + inc hl + ld (hl),d + inc hl + xor a + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + ld ix,(return) ; jp (ix) + +time4: + pop hl + ld (retarea),iy + ld (retarea+2),bc + ld (retarea+4),hl + ld hl,(timebuf+2) + push hl + ld hl,(timebuf) + push hl + ld hl,0 + push hl + ld hl,50 + push hl + call .dvu4 + ld iy,(retarea) + ld bc,(retarea+2) + ld hl,(retarea+4) + jp (hl) +ux_exit: + call uxfinish + ld c,reset + call bdos + ! no return + +ux_creat: + call emptyfile + jr c,openfailed + pop hl + call parsename + pop hl ! file mode, not used under CP/M + push iy + push ix + push ix + pop de + ld c,delete + call bdos + pop de + ld c,makefile + call bdos + pop iy + ld l,1 + jr afteropen +ux_open: + call emptyfile + jr nc,1f +openfailed: + pop hl + pop hl ! remove params + ld hl,EMFILE + push hl + push hl ; jr rtn +1: + pop hl ! filename + call parsename + push iy + ld c,open + push ix + pop de + call bdos + pop iy + pop hl +afteropen: + inc a + jr nz,1f + ld hl,ENOENT + push hl + push hl ; jr rtn +1: + inc l + ld (ix+openflag),l + xor a + ld (ix+nleft),a + ld (ix+zcount),a + ld (ix+zsave),26 + bit 1,l + jr z,2f + ld (ix+nleft),128 +2: + ld (ix+position),a + ld (ix+position+1),a + push ix + pop hl + push bc + ld b,128 +3: dec hl + ld (hl),26 + djnz 3b + pop bc + ld (ix+iopointer+1),h + ld (ix+iopointer),l + ld h,a + ld l,(ix+fildes) + push hl + ld l,a + push hl ; jr rtn + +ux_read: + pop hl + ld a,l + sub 3 + jp p,readfile + ld a,(ttymode+4) + bit 5,a + jr z,1f ! not raw + push iy +! #ifdef CPM1 +!raw echo interface + ld c,consolein + call bdos +! #else +! !no echo interface +! 4: +! ld c,diconio +! ld e,0xff +! call bdos +! or a +! jr z,4b +!end of no echo interface +! #endif + pop iy + pop hl + ld (hl),a + pop hl + ld hl,1 + push hl + ld hl,0 + push hl ; jr rtn +1: + ld hl,sibuf+1 ! read from console assumed + dec (hl) + jp p,2f + dec hl ! go read console line + ld (hl),80 ! max line length + push iy + push hl + ld c,readconsole + ex de,hl + call bdos + ld c,writeconsole + ld e,'\n' + call bdos + pop hl + pop iy + inc hl + inc (hl) + ld (siptr),hl ! ready for transfer + push hl + ld e,(hl) + ld d,0 + add hl,de + ld (hl),'\r' + inc hl + ld (hl),'\n' + pop hl +2: + push bc + pop ix + ld b,(hl) + inc b ! bytes remaining + pop hl ! copy to + pop de ! bytes wanted (probably 512) + push ix + ld ix,(siptr) ! copy from + xor a ! find out minimum of ramaining and wanted + or d + jr nz,3f ! more than 255 wanted (forget that) + ld a,b + cp e + jp m,3f ! not enough remaining + ld b,e +3: + ld c,b ! keep copy +0: + inc ix + ld a,(ix) + ld (hl),a + inc hl + djnz 0b + ld a,(sibuf+1) + sub c + inc a + ld (sibuf+1),a + ld (siptr),ix + pop hl + push bc + ld c,b + push bc ! load 0 + ld b,h + ld c,l + ld ix,(return) ; jp (ix) +readfile: + call findfile + pop de + pop hl ! count + push bc + ld bc,0 +0: + xor a + or l + jr z,1f + dec l +3: +! warning: this may not work if zcount overflows + ld a,(ix+zcount) + or a + jr nz,5f + ld a,(ix+zsave) + cp 26 + jr z,4f + ld (ix+zsave),26 + jr 8f +4: + call getchar + jr c,2f + ld (de),a + sub 26 ! CTRL-Z + jr z,7f + ld a,(ix+zcount) + or a + jr z,6f + ld a,(de) + ld (ix+zsave),a +5: + ld a,26 + dec (ix+zcount) +8: + ld (de),a +6: + inc de + inc bc + jr 0b +1: + dec l + dec h + jp p,3b +2: + pop hl + push bc + ld b,h + ld c,l + ld hl,0 + push hl ; jr rtn +7: + inc (ix+zcount) + jr 4b + +ux_write: + pop hl + ld a,l + sub 3 + jp p,writefile + pop hl ! buffer address + pop de ! count + push de + ld ix,0 + push ix + push bc + ld b,e ! count now in 'db' +0: + ld a,b + or a + jr nz,1f + ld a,d + or a + jr nz,2f + pop bc + ld ix,(return) ; jp (ix) +2: + dec d +1: + dec b + ld e,(hl) + inc hl + push bc + push de + push hl + ld c,writeconsole + call bdos + pop hl + pop de + pop bc + jr 0b +writefile: + call findfile + pop de + pop hl ! count + push bc + ld bc,0 +0: + xor a + or l + jr z,1f + dec l +3: + ld a,(de) + inc de + call putchar + jr c,4f + inc bc + jr 0b +1: + dec l + dec h + jp p,3b + ld ix,0 +2: + pop hl + push bc + ld b,h + ld c,l + push ix + ld ix,(return) ; jp (ix) +4: + ld ix,ENOSPC + jr 2b + +ux_unlink: + pop hl + ld ix,fcb + call parsename + push bc + ld c,delete + ld de,fcb + call bdos + pop bc + inc a + jr nz,1f + ld hl,ENOENT + push hl ; jr rtn +1: + ld hl,0 + push hl ; jr rtn + +ux_getpid: + ld hl,12345 ! nice number + push hl ; jr rtn + + + + + + +retarea: .word 0 ! base of buffer for result values (max 8 bytes) + .word 0 + .word 0 + .word 0 + +trapproc: + .word 0 + +nextp: .byte 0 + +header: +ntext: .word 0 +ndata: .word 0 +nproc: .word 0 +entry: .word 0 +nline: .word 0 + +hp: .word 0 +pb: .word 0 +pd: .word 0 diff --git a/mach/z80/libsys/mon.s b/mach/z80/libsys/mon.s new file mode 100644 index 000000000..0e997f14f --- /dev/null +++ b/mach/z80/libsys/mon.s @@ -0,0 +1,102 @@ +.define .mon + +! Monitor call +! Expects on stack: monitor call number +! parameters +! Implemented are the following monitor calls: +! number 1: exit +! number 3: read +! number 4: write +! number 5: open +! number 6: close +! number 54: ioctl +! If called with a number of a call that is not implemented, +! a trap is generated. + +.mon: + pop ix ! returnaddress + + pop hl ! monitor call number + ld a,l + cp 1 + jp z,monexit ! is it an exit? + cp 3 + jp z,monread ! is it a read? + cp 4 + jp z,monwrite ! is it a write? + cp 5 + jp z,monopen ! is it an open? + cp 6 + jp z,monclose ! is it a close? + cp 54 + jp z,monioctl + jp ebadmon ! trap + +monexit: + jp 0x38 + +monread: + pop hl ! file-descriptor, not used + pop hl ! hl = pointer to output buffer + pop de ! de = number of bytes to be read + ld bc,0 ! bc will contain the number of bytes actually read +1: ld a,d + or e + jr z,2f + call getchar + push af + call putchar ! echo character + pop af + ld (hl),a + inc hl + inc bc + dec de + cp 0x0A ! is it a newline? + jp nz,1b +2: push bc + ld hl,0 + push hl + jp (ix) + +monwrite: + pop hl ! file-descriptor, not used + pop hl ! hl = pointer to output buffer + pop de ! de = number of bytes + push de +1: ld a,e + or d + jr z,2f + ld a,(hl) + call putchar + inc hl +dec de + jp 1b + +2: push de ! no error + jp (ix) + + +monopen: + pop hl ! pointer to string + pop hl ! flag + ld hl,-1 + push hl ! push file descriptor + push hl ! push error code twice + push hl + jp (ix) + +monclose: + ex (sp),hl ! pop file descriptor and push error code + pop hl ! file descriptor + ld hl,-1 + push hl ! push error code twice + push hl + jp (ix) + +monioctl: + pop hl ! file descriptor + pop hl ! request + ld hl,0 + ex (sp),hl ! remove argp and push error code + jp (ix) + diff --git a/mach/z80/libsys/putchr.nas.s b/mach/z80/libsys/putchr.nas.s new file mode 100644 index 000000000..e0dbdeb67 --- /dev/null +++ b/mach/z80/libsys/putchr.nas.s @@ -0,0 +1,28 @@ +.define putchr +! output routine in monitor +CRT = 0x013B +! output a charcter +! entry: ascii character in a +putchr: + push hl + push bc + ld hl,tab + ld b,5 +1: cp (hl) + jr z,fetch + inc hl + inc hl + djnz 1b +2: call CRT + pop bc + pop hl + ret +fetch: inc hl + ld a,(hl) + jr 2b +! conversion table for nascom characters +tab: .byte 0x0D,0x00 + .byte 0x1B,0x1E + .byte 0x08,0x1D + .byte 0x0A,0x1F + .byte 0x7F,0x00 diff --git a/mach/z80/libsys/putchr.s b/mach/z80/libsys/putchr.s new file mode 100644 index 000000000..db15bf216 --- /dev/null +++ b/mach/z80/libsys/putchr.s @@ -0,0 +1,21 @@ +.define putchr + +putchr: + push hl + push de + push bc + cp 0x0A + jr nz,1f + ld a,0x1F +1: + ld c,a +2: + in a,0xF1 + and 4 + jr z,2b + ld a,c + out 0xF0,a + pop bc + pop de + pop hl + ret diff --git a/mach/z80/libsys/subr.s b/mach/z80/libsys/subr.s new file mode 100644 index 000000000..253048892 --- /dev/null +++ b/mach/z80/libsys/subr.s @@ -0,0 +1,197 @@ +.define _read,_write,_ioctl,_getpid,_open,_close,_exit,_errno +_read: + ld (savebc),bc + push af + pop bc + ld (saveaf),bc ! save all registers in savereg + ld (savede),de + ld (savehl),hl + ld (saveix),ix + ex (sp),hl ! return address in hl + pop bc ! skip return address + pop bc ! get fd + ld a,b ! check fd = 0 + or c + jr nz,errrd + pop de ! get buffer + pop bc ! get count + ld ix,0 ! reset counter + push bc + push de + push ix + push hl ! return address + ex de,hl ! buffer to hl +1: ld a,b + or c + jr z,done ! done if count = 0 + call getchr + ld (hl),a + inc hl ! increment pointer + inc ix ! increment char counter + dec bc ! decrement count + cp 0xA + jr nz,1b ! done if char = CR +done: + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + ret +errrd: + push bc + push hl ! return address + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + ld ix,-1 + ret + +_write: + ld (savebc),bc + push af + pop bc + ld (saveaf),bc ! save all registers in savereg + ld (savede),de + ld (savehl),hl + ld (saveix),ix + ex (sp),hl ! return address in hl + pop de ! skip return address + pop de ! get fd + ld a,e ! check for fd = 1 + cp 1 + jr nz,errwr + ld a,d + or a + jr nz,errwr + pop de ! buffer in de + pop bc ! count in bc + push bc + push de + push de + push hl + ex de,hl ! buffer in hl + ld e,c + ld d,b ! count also in de +1: ld a,b + or c + jr z,exit + ld a,(hl) + call putchr + inc hl + dec bc + jr 1b +errwr: + push de + push hl + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + ld ix,-1 ! error in fd + ret +exit: + push de ! count on stack + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + pop ix ! return count to caller + ret + +_ioctl: + ret +_getpid: + ret + +! open return a file descriptor (0,1,2) +! depending on 'mode' +! mode 2 doesn't work!! +_open: + ld (savebc),bc + push af + pop bc + ld (saveaf),bc ! save all registers in savereg + ld (savede),de + ld (savehl),hl + ld (saveix),ix + pop bc ! return address + pop de ! name pointer + pop ix ! mode (0 for read, + ! 1 for write) + push ix + push de + push bc + ld bc,(saveaf) + push bc + pop af + ld bc,(savebc) + ld de,(savede) + ld hl,(savehl) + ld ix,(saveix) + ret ! return fd = 0 for read + ! fd = 1 for write + +_close: + ld ix,0 ! return succes + ret +_exit: +jp 0x38 +.data +_errno: + .word 0 +! output routine in monitor +CRT = 0x013B +! output a charcter +! entry: ascii character in a +.text +!putchr: +! push hl +! push bc +! ld hl,tab +! ld b,5 +!1: cp (hl) +! jr z,fetch +! inc hl +! inc hl +! djnz 1b +!2: call CRT +! pop bc +! pop hl +! ret +!fetch: inc hl +! ld a,(hl) +! jr 2b +!! conversion table for nascom characters +!tab: .byte 0x0D,0x00 +! .byte 0x1B,0x1E +! .byte 0x08,0x1D +! .byte 0x0A,0x1F +! .byte 0x7F,0x00 + +KBD = 0x69 +! get character from keyboard +getchr: + call KBD + jr nc,getchr + cp 0x1F + jr z,CR + cp 0x1D + jr z,BS + ret +CR: ld a,0xA + ret +BS: ld a,0x8 + ret -- 2.34.1