]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/dos/dosvcpi.c
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / dos / dosvcpi.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 unsigned char vcpi_probed = 0;
32 unsigned char vcpi_present = 0;
33 unsigned char vcpi_major_version,vcpi_minor_version;
34
35 /* NTS: According to the VCPI specification this call is only supposed to report
36  *      the physical memory address for anything below the 1MB boundary. And so
37  *      far EMM386.EXE strictly adheres to that rule by not reporting success for
38  *      addresses >= 1MB. The 32-bit limitation is a result of the VCPI system
39  *      call, since the physical address is returned in EDX. */
40 uint32_t dos_linear_to_phys_vcpi(uint32_t pn) {
41         uint32_t r=0xFFFFFFFFUL;
42
43         __asm {
44                 .586p
45                 mov     ax,0xDE06
46                 mov     ecx,pn
47                 int     67h
48                 or      ah,ah
49                 jnz     err1            ; if AH == 0 then EDX = page phys addr
50                 mov     r,edx
51 err1:
52         }
53
54         return r;
55 }
56
57 #if !defined(TARGET_WINDOWS)
58 static int int67_null() {
59         uint32_t ptr;
60
61 #if TARGET_MSDOS == 32
62         ptr = ((uint32_t*)0)[0x67];
63 #else
64         ptr = *((uint32_t far*)MK_FP(0,0x67*4));;
65 #endif
66
67         return (ptr == 0);
68 }
69 #endif
70
71 int probe_vcpi() {
72 #if defined(TARGET_WINDOWS)
73         if (!vcpi_probed) {
74                 /* NTS: Whoever said Windows 3.0 used VCPI at it's core, is a liar */
75                 vcpi_probed = 1;
76                 vcpi_present = 0;
77         }
78 #else
79 /* =================== MSDOS ================== */
80         unsigned char err=0xFF;
81
82         if (!vcpi_probed) {
83                 vcpi_probed = 1;
84
85                 /* if virtual 8086 mode isn't active, then VCPI isn't there */
86                 /* FIXME: What about cases where VCPI might be there, but is inactive (such as: EMM386.EXE resident but disabled) */
87                 if (!cpu_v86_active)
88                         return 0;
89
90                 /* NOTE: VCPI can be present whether we're 16-bit real mode or
91                  * 32-bit protected mode. Unlike DPMI we cannot assume it's
92                  * present just because we're 32-bit. */
93
94                 /* Do not call INT 67h if the vector is uninitialized */
95                 if (int67_null())
96                         return 0;
97
98                 /* Do not attempt to probe for VCPI if Windows 3.1/95/98/ME
99                  * is running. Windows 9x blocks VCPI and if called, interrupts
100                  * our execution to inform the user that the program should be
101                  * run in DOS mode. */
102                 detect_windows();
103                 if (windows_mode != WINDOWS_NONE)
104                         return 0;
105
106                 /* NTS: we load DS for each var because Watcom might put it in
107                  *      another data segment, especially in Large memory model.
108                  *      failure to account for this was the cause of mysterious
109                  *      hangs and crashes. */
110                 __asm {
111                         ; NTS: Save DS and ES because Microsoft EMM386.EXE
112                         ;      appears to change their contents.
113                         push    ds
114                         push    es
115                         mov     ax,0xDE00
116                         int     67h
117                         mov     err,ah
118
119                         mov     ax,seg vcpi_major_version
120                         mov     ds,ax
121                         mov     vcpi_major_version,bh
122
123                         mov     ax,seg vcpi_minor_version
124                         mov     ds,ax
125                         mov     vcpi_minor_version,bl
126
127                         pop     es
128                         pop     ds
129                 }
130
131                 if (err != 0)
132                         return 0;
133
134                 vcpi_present = 1;
135         }
136 #endif
137
138         return vcpi_present;
139 }
140