/*
 * DOS interrupt 21h handler
 *
 * Copyright 1993, 1994 Erik Bos
 * Copyright 1996 Alexandre Julliard
 * Copyright 1997 Andreas Mohr
 * Copyright 1998 Uwe Bonnes
 * Copyright 1998, 1999 Ove Kaaven
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"

#include "windef.h"
#include "winbase.h"
#include "ntddk.h"
#include "wine/winbase16.h"
#include "dosexe.h"
#include "miscemu.h"
#include "msdos.h"
#include "file.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(int21);

void WINAPI DOSVM_Int21Handler_Ioctl( CONTEXT86 *context )
{
  const DOS_DEVICE *dev = DOSFS_GetDeviceByHandle(
      DosFileHandleToWin32Handle(BX_reg(context)) );

  if (dev && !strcasecmp( dev->name, "EMMXXXX0" )) {
    EMS_Ioctl_Handler(context);
    return;
  }

  switch (AL_reg(context))
  {
  case 0x0b: /* SET SHARING RETRY COUNT */
      TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n",
           CX_reg(context), DX_reg(context));
      if (!CX_reg(context))
      {
         AX_reg(context) = 1;
         SET_CFLAG(context);
         break;
      }
      DOSMEM_LOL()->sharing_retry_delay = CX_reg(context);
      if (!DX_reg(context))
         DOSMEM_LOL()->sharing_retry_count = DX_reg(context);
      RESET_CFLAG(context);
      break;
  default:
      DOS3Call( context );
  }
}

/***********************************************************************
 *           DOSVM_Int21Handler
 *
 * int 21h real-mode handler. Most calls are passed directly to DOS3Call.
 */
void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{
    RESET_CFLAG(context);  /* Not sure if this is a good idea */

    if(AH_reg(context) == 0x0c) /* FLUSH BUFFER AND READ STANDARD INPUT */
    {
        BYTE al = AL_reg(context); /* Input function to execute after flush. */

        /* FIXME: buffers are not flushed */

        /*
         * If AL is not one of 0x01, 0x06, 0x07, 0x08, or 0x0a,
         * the buffer is flushed but no input is attempted.
         */
        if(al != 0x01 && al != 0x06 && al != 0x07 && al != 0x08 && al != 0x0a)
            return;

        AH_reg(context) = al;
    }

    switch(AH_reg(context))
    {
    case 0x00: /* TERMINATE PROGRAM */
        TRACE("TERMINATE PROGRAM\n");
        MZ_Exit( context, FALSE, 0 );
        break;

    case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
        TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
        DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
        DOSVM_PutChar(AL_reg(context));
	break;

    case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
        TRACE("Write Character to Standard Output\n");
        DOSVM_PutChar(DL_reg(context));
        break;

    case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
        /* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */
        if (DL_reg(context) == 0xff) {
            static char scan = 0;
            TRACE("Direct Console Input\n");
            if (scan) {
                /* return pending scancode */
                AL_reg(context) = scan;
                RESET_ZFLAG(context);
                scan = 0;
            } else {
                char ascii;
                if (DOSVM_Int16ReadChar(&ascii,&scan,TRUE)) {
                    DOSVM_Int16ReadChar(&ascii,&scan,FALSE);
                    /* return ASCII code */
                    AL_reg(context) = ascii;
                    RESET_ZFLAG(context);
                    /* return scan code on next call only if ascii==0 */
                    if (ascii) scan = 0;
                } else {
                    /* nothing pending, clear everything */
                    AL_reg(context) = 0;
                    SET_ZFLAG(context);
                    scan = 0; /* just in case */
                }
            }
        } else {
            TRACE("Direct Console Output\n");
            DOSVM_PutChar(DL_reg(context));
        }
        break;

    case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
        /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
        TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
        DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
        break;

    case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
        /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
        TRACE("CHARACTER INPUT WITHOUT ECHO\n");
        DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
        break;

    case 0x0b: /* GET STDIN STATUS */
        {
            BIOSDATA *data = DOSMEM_BiosData();
            if(data->FirstKbdCharPtr == data->NextKbdCharPtr)
                AL_reg(context) = 0;
            else
                AL_reg(context) = 0xff;
        }
        break;

    case 0x25: /* SET INTERRUPT VECTOR */
        DOSVM_SetRMHandler( AL_reg(context),
                            (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
        break;

    case 0x35: /* GET INTERRUPT VECTOR */
        TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
        {
            FARPROC16 addr = DOSVM_GetRMHandler( AL_reg(context) );
            context->SegEs = SELECTOROF(addr);
            BX_reg(context) = OFFSETOF(addr);
        }
        break;

    case 0x40: /* WRITE TO FILE OR DEVICE */
        /* Writes to stdout are handled here. */
        if (BX_reg(context) == 1) {
          BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
                                         context->SegDs,
                                         context->Edx);
          int i;

          for(i=0; i<CX_reg(context); i++)
            DOSVM_PutChar(ptr[i]);
        } else
          DOS3Call( context );
        break;

    case 0x44: /* IOCTL */
        DOSVM_Int21Handler_Ioctl( context );
        break;

    case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
        TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
        if (!MZ_Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
                      AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) ))
        {
            AX_reg(context) = GetLastError();
            SET_CFLAG(context);
        }
        break;

    case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
        TRACE("EXIT with return code %d\n",AL_reg(context));
        MZ_Exit( context, FALSE, AL_reg(context) );
        break;

    case 0x4d: /* GET RETURN CODE */
        TRACE("GET RETURN CODE (ERRORLEVEL)\n");
        AX_reg(context) = DOSVM_retval;
        DOSVM_retval = 0;
        break;

    case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
        TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n");
        DOSVM_psp = BX_reg(context);
        break;

    case 0x51: /* GET PSP ADDRESS */
        TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n");
        /* FIXME: should we return the original DOS PSP upon */
        /*        Windows startup ? */
        BX_reg(context) = DOSVM_psp;
        break;

    case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
        TRACE("SYSVARS - GET LIST OF LISTS\n");
        {
            context->SegEs = HIWORD(DOS_LOLSeg);
            BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB);
        }
        break;

    case 0x62: /* GET PSP ADDRESS */
        TRACE("GET CURRENT PSP ADDRESS\n");
        /* FIXME: should we return the original DOS PSP upon */
        /*        Windows startup ? */
        BX_reg(context) = DOSVM_psp;
        break;

    default:
        DOS3Call( context );
    }
}
