]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/dos/dpmirmcl.c
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / dos / dpmirmcl.c
1 /* dos.c
2  *
3  * Code to detect the surrounding DOS/Windows environment and support routines to work with it
4  * (C) 2009-2012 Jonathan Campbell.
5  * Hackipedia DOS library.
6  *
7  * This code is licensed under the LGPL.
8  * <insert LGPL legal text here>
9  */
10
11 #ifdef TARGET_WINDOWS
12 # include <windows.h>
13 #endif
14
15 #include <stdio.h>
16 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stddef.h>
20 #include <unistd.h>
21 #include <malloc.h>
22 #include <assert.h>
23 #include <fcntl.h>
24 #include <dos.h>
25
26 #include <hw/cpu/cpu.h>
27 #include <hw/dos/dos.h>
28 #include <hw/dos/doswin.h>
29 #include <hw/dos/dosntvdm.h>
30
31 #if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
32 unsigned int dpmi_test_rm_entry_call(struct dpmi_realmode_call *rc) {
33         unsigned int res = 0;
34
35         __asm {
36                 mov     ax,0x0301
37                 xor     bx,bx
38                 xor     cx,cx
39                 mov     edi,rc          ; we trust Watcom has left ES == DS
40                 int     0x31            ; call DPMI
41                 jnc     ok
42                 
43                 mov     res,1           ; just incase some fucked up DPMI server returns CF=1 EAX=0
44                 or      eax,eax
45                 jz      ok
46                 
47                 mov     res,eax         ; OK store the error code as-is
48 ok:
49         }
50
51         return res;
52 }
53
54 static unsigned char *alt_rm_call = NULL;
55 static uint16_t alt_rm_call_sel = 0;
56
57 /* using this hack, subvert INT 06h (invalid opcode exception)
58    which the BIOS and DOS are unlikely to use during this hack */
59 #define ALT_INT 0x06
60
61 int dpmi_alternate_rm_call(struct dpmi_realmode_call *rc) {
62         uint32_t oe;
63
64         if (alt_rm_call == NULL) {
65                 alt_rm_call = dpmi_alloc_dos(32,&alt_rm_call_sel);
66                 if (alt_rm_call == NULL) {
67                         fprintf(stderr,"FATAL: DPMI alternate call: cannot alloc\n");
68                         return 0;
69                 }
70         }
71
72         /* Fuck you DOS4/GW! */
73         /* prepare executable code */
74         alt_rm_call[0] = 0x9A;  /* CALL FAR IMM */
75         *((uint16_t*)(alt_rm_call+1)) = rc->ip;
76         *((uint16_t*)(alt_rm_call+3)) = rc->cs;
77         alt_rm_call[5] = 0xCF;  /* IRET */
78
79         /* replace real-mode interrupt vector */
80         _cli();
81         oe = ((uint32_t*)0x00000000)[ALT_INT];
82         ((uint32_t*)0x00000000)[ALT_INT] =
83                 (((uint32_t)alt_rm_call >> 4UL) << 16UL) | /* seg */
84                 ((uint32_t)alt_rm_call & 0xFUL); /* ofs */
85         _sti();
86
87         /* call it! */
88         __asm {
89                 mov     ax,0x0300
90                 mov     bx,ALT_INT
91                 xor     cx,cx
92                 mov     edi,rc          ; we trust Watcom has left ES == DS
93                 int     0x31            ; call DPMI
94         }
95
96         /* restore interrupt vector */
97         _cli();
98         ((uint32_t*)0x00000000)[ALT_INT] = oe;
99         _sti();
100
101         return 1;
102 }
103
104 int dpmi_alternate_rm_call_stacko(struct dpmi_realmode_call *rc) {
105         uint32_t oe;
106
107         if (alt_rm_call == NULL) {
108                 alt_rm_call = dpmi_alloc_dos(32,&alt_rm_call_sel);
109                 if (alt_rm_call == NULL) {
110                         fprintf(stderr,"FATAL: DPMI alternate call: cannot alloc\n");
111                         return 0;
112                 }
113         }
114
115         /* Fuck you DOS4/GW! */
116         /* prepare executable code */
117         {
118                 static unsigned char code[] = {
119                         0xFC,           /* CLD */
120                         0x8C,0xD0,      /* MOV AX,SS */
121                         0x8E,0xD8,      /* MOV DS,AX */
122                         0x8E,0xC0,      /* MOV ES,AX */
123                         0x89,0xE5,      /* MOV BP,SP */
124                         0x8D,0x76,0x06, /* LEA SI,[BP+6] <- 6 byte interrupt stack */
125                         0x83,0xEC,0x20, /* SUB SP,0x20 */
126                         0xB9,0x10,0x00, /* MOV CX,0x10 */
127                         0x89,0xE7,      /* MOV DI,SP */
128                         0xF3,0xA5       /* REP MOVSW */
129                 };
130                 memcpy(alt_rm_call,code,0x16);
131         }
132         
133         alt_rm_call[0x16] = 0x9A;       /* CALL FAR IMM */
134         *((uint16_t*)(alt_rm_call+0x16+1)) = rc->ip;
135         *((uint16_t*)(alt_rm_call+0x16+3)) = rc->cs;
136         alt_rm_call[0x16+5] = 0x89;     /* MOV SP,BP */
137         alt_rm_call[0x16+6] = 0xEC;
138         alt_rm_call[0x16+7] = 0xCF;     /* IRET */
139
140         /* replace real-mode interrupt vector */
141         _cli();
142         oe = ((uint32_t*)0x00000000)[ALT_INT];
143         ((uint32_t*)0x00000000)[ALT_INT] =
144                 (((uint32_t)alt_rm_call >> 4UL) << 16UL) | /* seg */
145                 ((uint32_t)alt_rm_call & 0xFUL); /* ofs */
146         _sti();
147
148         /* call it! */
149         __asm {
150                 mov     ax,0x0300
151                 mov     bx,ALT_INT
152                 xor     cx,cx
153                 mov     edi,rc          ; we trust Watcom has left ES == DS
154                 int     0x31            ; call DPMI
155         }
156
157         /* restore interrupt vector */
158         _cli();
159         ((uint32_t*)0x00000000)[ALT_INT] = oe;
160         _sti();
161
162         return 1;
163 }
164 #undef ALT_INT
165 #endif
166
167 #if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
168 void mux_realmode_2F_call(struct dpmi_realmode_call *rc) {
169         __asm {
170                 mov     ax,0x0300
171                 mov     bx,0x002F
172                 xor     cx,cx
173                 mov     edi,rc          ; we trust Watcom has left ES == DS
174                 int     0x31            ; call DPMI
175         }
176 }
177 #endif
178 #if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
179 void mux_realmode_2F_call(struct dpmi_realmode_call far *rc) {
180         __asm {
181                 push    es
182                 mov     ax,0x0300
183                 mov     bx,0x002F
184                 xor     cx,cx
185                 mov     di,word ptr [rc+2]
186                 mov     es,di
187                 mov     di,word ptr [rc]
188                 int     0x31            ; call DPMI
189                 pop     es
190         }
191 }
192 #endif
193