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.
7 * This code is licensed under the LGPL.
8 * <insert LGPL legal text here>
16 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
26 #include <hw/cpu/cpu.h>
27 #include <hw/dos/dos.h>
28 #include <hw/dos/doswin.h>
29 #include <hw/dos/dosntvdm.h>
31 #if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
32 unsigned int dpmi_test_rm_entry_call(struct dpmi_realmode_call *rc) {
39 mov edi,rc ; we trust Watcom has left ES == DS
43 mov res,1 ; just incase some fucked up DPMI server returns CF=1 EAX=0
47 mov res,eax ; OK store the error code as-is
54 static unsigned char *alt_rm_call = NULL;
55 static uint16_t alt_rm_call_sel = 0;
57 /* using this hack, subvert INT 06h (invalid opcode exception)
58 which the BIOS and DOS are unlikely to use during this hack */
61 int dpmi_alternate_rm_call(struct dpmi_realmode_call *rc) {
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");
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 */
79 /* replace real-mode interrupt vector */
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 */
92 mov edi,rc ; we trust Watcom has left ES == DS
96 /* restore interrupt vector */
98 ((uint32_t*)0x00000000)[ALT_INT] = oe;
104 int dpmi_alternate_rm_call_stacko(struct dpmi_realmode_call *rc) {
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");
115 /* Fuck you DOS4/GW! */
116 /* prepare executable code */
118 static unsigned char code[] = {
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 */
130 memcpy(alt_rm_call,code,0x16);
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 */
140 /* replace real-mode interrupt vector */
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 */
153 mov edi,rc ; we trust Watcom has left ES == DS
157 /* restore interrupt vector */
159 ((uint32_t*)0x00000000)[ALT_INT] = oe;
167 #if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
168 void mux_realmode_2F_call(struct dpmi_realmode_call *rc) {
173 mov edi,rc ; we trust Watcom has left ES == DS
178 #if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
179 void mux_realmode_2F_call(struct dpmi_realmode_call far *rc) {
185 mov di,word ptr [rc+2]