/* xtrsemt.ccc -- Misosys C interface to xtrs emulator traps */

/* 
 * Copyright (c) 1997-2008, Timothy P. Mann
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <errno.h>
#ifndef _TIME_T
#include <time.h>
#endif

int
emt_system(cmd)
     char *cmd;
{
#asm
    POP AF		;save return address
    POP HL		;cmd to HL
    PUSH HL             ;restore stack
    PUSH AF
    DEFW 28EDH		;emt_system
    LD H,B		;return exit status from BC
    LD L,C
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
#endasm
}

char *
emt_gtddir(buffer, bytes)
     char *buffer;
     int bytes;
{
#asm
    POP AF		;save return address
    POP HL		;buffer to HL
    POP BC		;bytes to BC
    PUSH BC
    PUSH HL
    PUSH AF
    DEFW 2AEDH		;emt_getddir
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
    LD HL,0
#endasm
}

int
emt_stddir(fname)
     char *fname;
{
#asm
    POP AF		;save return address
    POP HL		;fname to HL
    PUSH HL
    PUSH AF
    DEFW 2BEDH		;emt_setddir
    LD HL,0		;return 0 if OK
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
    LD HL,0FFFFH	;return -1
#endasm
}


int
emt_open(fname, oflag, mode)
     char *fname;
     int oflag;
     int mode;
{
#asm
    POP AF		;save return address
    POP HL		;fname to HL
    POP BC		;oflag to BC
    POP DE		;mode to DE
    PUSH DE		;restore stack
    PUSH BC
    PUSH HL
    PUSH AF
    DEFW 30EDH		;emt_open
    LD H,D		;return fd from DE
    LD L,E
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
#endasm
}

int
emt_close(fd)
     int fd;
{
#asm
    POP AF		;save return address
    POP DE		;fd to DE
    PUSH DE
    PUSH AF
    DEFW 31EDH		;emt_close
    LD HL,0		;return 0 if no error
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
    LD HL,0FFFFH	;return -1
#endasm
}

int
emt_read(fd, buffer, bytes)
     int fd;
     char *buffer;
     int bytes;
{
#asm
    POP AF		;save return address
    POP DE		;fd to DE
    POP HL		;buffer to HL
    POP BC		;bytes to BC
    PUSH BC
    PUSH HL
    PUSH DE
    PUSH AF
    DEFW 32EDH		;emt_read
    LD H,B		;return count from BC
    LD L,C
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
#endasm
}

int
emt_write(fd, buffer, bytes)
     int fd;
     char *buffer;
     int bytes;
{
#asm
    POP AF		;save return address
    POP DE		;fd to DE
    POP HL		;buffer to HL
    POP BC		;bytes to BC
    PUSH BC
    PUSH HL
    PUSH DE
    PUSH AF
    DEFW 33EDH		;emt_write
    LD H,B		;return count from BC
    LD L,C
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
#endasm
}

long
emt_lseek(fd, offset, whence)
     int fd;
     long offset; /* 4 bytes */
     int whence;
{
#asm
    PUSH IX
    LD IX,4		;point IX to argument frame, skipping
    ADD IX,SP           ;  return address and old IX value
    LD E,(IX+0)		;fd to DE
    LD D,(IX+1)
    LD HL,0		;extend offset to 8 bytes, push on stack
    PUSH HL
    PUSH HL
    LD L,(IX+4)		;high 2 bytes of 4-byte offset
    LD H,(IX+5)
    PUSH HL
    LD L,(IX+2)		;low 2 bytes
    LD H,(IX+3)
    PUSH HL
    LD HL,0		;point HL to 8-byte offset
    ADD HL,SP
    LD C,(IX+6)		;whence to BC
    LD B,(IX+7)
    DEFW 34EDH		;emt_lseek
    POP DE		;return tell value in BCDE
    POP BC
    POP HL		;ignore high-order 4 bytes
    POP HL
    POP IX
    RET Z
    LD H,0		;error code to errno
    LD L,A
    LD (ERRNO),HL
#endasm
}

int
emt_strerror(err, buffer, size)
     int err;
     char *buffer;
     int size;
{
#asm
    POP AF		;save return address
    POP DE		;err to DE temporarily
    POP HL		;buffer to HL
    POP BC		;size to BC
    PUSH BC
    PUSH HL
    PUSH DE
    PUSH AF
    LD A,E		;move err to A
    DEFW 35EDH		;emt_strerror
    LD H,B
    LD L,C
    RET Z
    LD B,0		;new error code to errno
    LD C,A
    LD (ERRNO),BC
#endasm
}

time_t
emt_time(local)
    int local;
{
#asm
    POP AF		;save return address
    POP HL		;local flag to HL temporarily
    PUSH HL
    PUSH AF
    LD A,L		;local flag to A
    DEFW 36EDH          ;emt_time
                        ;return value is in BCDE (time_t == long)
#endasm
}

int
emt_dropen(fname)
     char *fname;
{
#asm
    POP AF		;save return address
    POP HL		;fname to HL
    PUSH HL
    PUSH AF
    DEFW 37EDH		;emt_opendir
    LD H,D              ;return dirfd
    LD L,E
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
#endasm
}

int
emt_drclose(dirfd)
     int dirfd;
{
#asm
    POP AF		;save return address
    POP DE		;dirfd to DE
    PUSH DE
    PUSH AF
    DEFW 38EDH		;emt_closedir
    LD HL,0		;return 0 if no error
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
    LD HL,0FFFFH	;return -1
#endasm
}

int
emt_drread(dirfd, buffer, bytes)
     int dirfd;
     char *buffer;
     int bytes;
{
#asm
    POP AF		;save return address
    POP DE		;fd to DE
    POP HL		;buffer to HL
    POP BC		;bytes to BC
    PUSH BC
    PUSH HL
    PUSH DE
    PUSH AF
    DEFW 39EDH		;emt_readdir
    LD H,B
    LD L,C
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
#endasm
}

int
emt_chdir(fname)
     char *fname;
{
#asm
    POP AF		;save return address
    POP HL		;fname to HL
    PUSH HL
    PUSH AF
    DEFW 3AEDH		;emt_chdir
    LD HL,0		;return 0 if OK
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
    LD HL,0FFFFH	;return -1
#endasm
}


char *
emt_getcwd(buffer, bytes)
     char *buffer;
     int bytes;
{
#asm
    POP AF		;save return address
    POP HL		;buffer to HL
    POP BC		;bytes to BC
    PUSH BC
    PUSH HL
    PUSH AF
    DEFW 3BEDH		;emt_getcwd
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
    LD HL,0		;return NULL
#endasm
}

int
emt_misc(func)
     int func;
{
#asm
    POP AF		;save return address
    POP HL		;func to HL
    PUSH HL
    PUSH AF
    LD A,L		;func to A
    DEFW 3CEDH		;emt_misc, return HL
#endasm
}

void
emt_4misc(func, hl, bc, de)
     int func;
     int *hl;
     int *bc;
     int *de;
{
#asm
    PUSH IX
    LD IX,4		;point IX to argument frame, skipping
    ADD IX,SP           ;  return address and old IX value
    LD L,(IX+4)         ;bc arg to HL
    LD H,(IX+5)
    LD C,(HL)           ;*bc to BC
    INC HL
    LD B,(HL)
    LD L,(IX+6)         ;de arg to HL
    LD H,(IX+7)
    LD E,(HL)           ;*de to DE
    INC HL
    LD D,(HL)
    LD L,(IX+2)         ;hl arg to HL
    LD H,(IX+3)
    LD A,(HL)           ;*hl to HL
    INC HL
    LD H,(HL)
    LD L,A
    LD A,(IX+0)         ;func to A
    DEFW 3CEDH		;emt_misc
    PUSH HL             ;save HL return
    LD L,(IX+4)         ;bc arg to HL
    LD H,(IX+5)
    LD (HL),C           ;BC return to *bc
    INC HL
    LD (HL),B
    LD L,(IX+6)         ;de arg to HL
    LD H,(IX+7)
    LD (HL),E           ;DE return to *de
    INC HL
    LD (HL),D
    POP DE              ;HL return to DE
    LD L,(IX+2)         ;hl arg to HL
    LD H,(IX+3)
    LD (HL),E           ;DE (HL return) to *hl
    INC HL
    LD (HL),D
    EX DE,HL		;HL return back to HL (not needed)
    POP IX
#endasm
}

int
emt_ftruncate(fd, length)
     int fd;
     long length; /* 4 bytes */
{
#asm
    PUSH IX
    LD IX,4		;point IX to argument frame, skipping
    ADD IX,SP           ;  return address and old IX value
    LD E,(IX+0)		;fd to DE
    LD D,(IX+1)
    LD HL,0		;extend length to 8 bytes, push on stack
    PUSH HL
    PUSH HL
    LD L,(IX+4)		;high 2 bytes of 4-byte offset
    LD H,(IX+5)
    PUSH HL
    LD L,(IX+2)		;low 2 bytes
    LD H,(IX+3)
    PUSH HL
    LD HL,0		;point HL to 8-byte offset
    ADD HL,SP
    DEFW 3DEDH		;emt_ftruncate
    POP DE		;pop length from stack
    POP BC
    POP HL
    POP HL
    POP IX		;restore
    RET Z
    LD H,0		;error code to errno
    LD L,A
    LD (ERRNO),HL
#endasm
}

int
emt_dkopen(fname, oflag, mode)
     char *fname;
     int oflag;
     int mode;
{
#asm
    POP AF		;save return address
    POP HL		;fname to HL
    POP BC		;oflag to BC
    POP DE		;mode to DE
    PUSH DE		;restore stack
    PUSH BC
    PUSH HL
    PUSH AF
    DEFW 3EEDH		;emt_opendisk
    LD H,D		;return fd from DE
    LD L,E
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
#endasm
}

int
emt_dkclose(fd)
     int fd;
{
#asm
    POP AF		;save return address
    POP DE		;fd to DE
    PUSH DE
    PUSH AF
    DEFW 3FEDH		;emt_closedisk
    LD HL,0		;return 0 if no error
    RET Z
    LD B,0		;error code to errno
    LD C,A
    LD (ERRNO),BC
    LD HL,0FFFFH	;return -1
#endasm
}

