*** empty log message ***

This commit is contained in:
keie 1985-04-01 14:44:26 +00:00
parent 6bbdb92784
commit 6c247029bd
18 changed files with 2846 additions and 0 deletions

28
mach/z80/libmon/Makefile Normal file
View file

@ -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

12
mach/z80/libmon/README Normal file
View file

@ -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.

View file

@ -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

80
mach/z80/libmon/head_em.s Normal file
View file

@ -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

924
mach/z80/libmon/mon.cpm.s Normal file
View file

@ -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

102
mach/z80/libmon/mon.s Normal file
View file

@ -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)

View file

@ -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

21
mach/z80/libmon/putchr.s Normal file
View file

@ -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

197
mach/z80/libmon/subr.s Normal file
View file

@ -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

28
mach/z80/libsys/Makefile Normal file
View file

@ -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

12
mach/z80/libsys/README Normal file
View file

@ -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.

View file

@ -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

80
mach/z80/libsys/head_em.s Normal file
View file

@ -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

924
mach/z80/libsys/mon.cpm.s Normal file
View file

@ -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

102
mach/z80/libsys/mon.s Normal file
View file

@ -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)

View file

@ -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

21
mach/z80/libsys/putchr.s Normal file
View file

@ -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

197
mach/z80/libsys/subr.s Normal file
View file

@ -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