Moved most of the real-mode stuff to dlls/winedos.
[wine] / dlls / winedos / int21.c
1 /*
2  * DOS interrupt 21h handler
3  */
4
5 #include "config.h"
6
7 #include "windef.h"
8 #include "winbase.h"
9 #include "ntddk.h"
10 #include "wine/winbase16.h"
11 #include "dosexe.h"
12 #include "miscemu.h"
13 #include "msdos.h"
14 #include "console.h"
15 #include "debugtools.h"
16
17 DEFAULT_DEBUG_CHANNEL(int21);
18
19
20 /***********************************************************************
21  *           DOSVM_Int21Handler
22  *
23  * int 21h real-mode handler. Most calls are passed directly to DOS3Call.
24  */
25 void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
26 {
27     RESET_CFLAG(context);  /* Not sure if this is a good idea */
28
29     switch(AH_reg(context))
30     {
31     case 0x00: /* TERMINATE PROGRAM */
32         TRACE("TERMINATE PROGRAM\n");
33         MZ_Exit( context, FALSE, 0 );
34         break;
35
36     case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
37         TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
38         AL_reg(context) = CONSOLE_GetCharacter();
39         /* FIXME: no echo */
40         break;
41
42     case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
43         TRACE("Write Character to Standard Output\n");
44         CONSOLE_Write(DL_reg(context), 0, 0, 0);
45         break;
46
47     case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
48         /* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */
49         if (DL_reg(context) == 0xff) {
50             static char scan = 0;
51             TRACE("Direct Console Input\n");
52             if (scan) {
53                 /* return pending scancode */
54                 AL_reg(context) = scan;
55                 RESET_ZFLAG(context);
56                 scan = 0;
57             } else {
58                 char ascii;
59                 if (DOSVM_Int16ReadChar(&ascii,&scan,TRUE)) {
60                     DOSVM_Int16ReadChar(&ascii,&scan,FALSE);
61                     /* return ASCII code */
62                     AL_reg(context) = ascii;
63                     RESET_ZFLAG(context);
64                     /* return scan code on next call only if ascii==0 */
65                     if (ascii) scan = 0;
66                 } else {
67                     /* nothing pending, clear everything */
68                     AL_reg(context) = 0;
69                     SET_ZFLAG(context);
70                     scan = 0; /* just in case */
71                 }
72             }
73         } else {
74             TRACE("Direct Console Output\n");
75             CONSOLE_Write(DL_reg(context), 0, 0, 0);
76         }
77         break;
78
79     case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
80         /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
81         TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
82         DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
83         break;
84
85     case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
86         /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
87         TRACE("CHARACTER INPUT WITHOUT ECHO\n");
88         DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
89         break;
90
91     case 0x0b: /* GET STDIN STATUS */
92         {
93             char x1,x2;
94
95             if (CONSOLE_CheckForKeystroke(&x1,&x2))
96                 AL_reg(context) = 0xff;
97             else
98                 AL_reg(context) = 0;
99         }
100         break;
101
102     case 0x25: /* SET INTERRUPT VECTOR */
103         DOSVM_SetRMHandler( AL_reg(context),
104                             (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
105         break;
106
107     case 0x35: /* GET INTERRUPT VECTOR */
108         TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
109         {
110             FARPROC16 addr = DOSVM_GetRMHandler( AL_reg(context) );
111             context->SegEs = SELECTOROF(addr);
112             BX_reg(context) = OFFSETOF(addr);
113         }
114         break;
115
116     case 0x44: /* IOCTL */
117         switch (AL_reg(context))
118         {
119         case 0x0b:   /* SET SHARING RETRY COUNT */
120             TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n",
121                   CX_reg(context), DX_reg(context));
122             if (!CX_reg(context))
123             {
124                 AX_reg(context) = 1;
125                 SET_CFLAG(context);
126                 break;
127             }
128             DOSMEM_LOL()->sharing_retry_delay = CX_reg(context);
129             if (!DX_reg(context))
130                 DOSMEM_LOL()->sharing_retry_count = DX_reg(context);
131             RESET_CFLAG(context);
132             break;
133         }
134         break;
135
136     case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
137         TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
138         if (!MZ_Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
139                       AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) ))
140         {
141             AX_reg(context) = GetLastError();
142             SET_CFLAG(context);
143         }
144         break;
145
146     case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
147         TRACE("EXIT with return code %d\n",AL_reg(context));
148         MZ_Exit( context, FALSE, AL_reg(context) );
149         break;
150
151     case 0x4d: /* GET RETURN CODE */
152         TRACE("GET RETURN CODE (ERRORLEVEL)\n");
153         AX_reg(context) = DOSVM_retval;
154         DOSVM_retval = 0;
155         break;
156
157     case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
158         TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n");
159         DOSVM_psp = BX_reg(context);
160         break;
161
162     case 0x51: /* GET PSP ADDRESS */
163         TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n");
164         /* FIXME: should we return the original DOS PSP upon */
165         /*        Windows startup ? */
166         BX_reg(context) = DOSVM_psp;
167         break;
168
169     case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
170         TRACE("SYSVARS - GET LIST OF LISTS\n");
171         {
172             context->SegEs = HIWORD(DOS_LOLSeg);
173             BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB);
174         }
175         break;
176
177     case 0x62: /* GET PSP ADDRESS */
178         TRACE("GET CURRENT PSP ADDRESS\n");
179         /* FIXME: should we return the original DOS PSP upon */
180         /*        Windows startup ? */
181         BX_reg(context) = DOSVM_psp;
182         break;
183
184     default:
185         DOS3Call( context );
186     }
187 }