3 * Detect whether or not we're running under the DOSBox emulator
4 * (C) 2010-2012 Jonathan Campbell.
5 * Hackipedia DOS library.
7 * This code is licensed under the LGPL.
8 * <insert LGPL legal text here>
18 #include <hw/cpu/cpu.h>
19 #include <hw/dos/dos.h>
20 #include <hw/dos/dosbox.h>
22 #if defined(TARGET_WINDOWS) || defined(TARGET_OS2)
24 static const char *dosbox_fakebios = "DOSBox FakeBIOS v1.0";
27 /* the ROM area doesn't change. so remember our last result */
28 #if defined(TARGET_WINDOWS) || defined(TARGET_OS2)
30 static signed char dosbox_detect_cache = -1;
33 int detect_dosbox_emu() {
34 #if defined(TARGET_OS2)
35 /* TODO: So... how does one read the ROM BIOS area from OS/2? */
37 #elif defined(TARGET_WINDOWS)
38 /* TODO: I know that from within Windows there are various ways to scan the ROM BIOS area.
39 * Windows 1.x and 2.x (if real mode) we can just use MK_FP as we do under DOS, but
40 * we have to use alternate means if Windows is in protected mode. Windows 2.x/3.x protected
41 * mode (and because of compatibility, Windows 95/98/ME), there are two methods open to us:
42 * One is to use selector constants that are hidden away in KRNL386.EXE with names like _A0000,
43 * _B0000, etc. They are data selectors that when loaded into the segment registers point to
44 * their respective parts of DOS adapter ROM and BIOS ROM. Another way is to use the Win16
45 * API to create a data selector that points to the BIOS. Windows 386 Enhanced mode may map
46 * additional things over the unused parts of adapter ROM, but experience shows that it never
47 * relocates or messes with the VGA BIOS or with the ROM BIOS,
49 * My memory is foggy at this point, but I remember that under Windows XP SP2, one of the
50 * above Win16 methods still worked even from under the NT kernel.
52 * For Win32 applications, if the host OS is Windows 3.1 Win32s or Windows 95/98/ME, we can
53 * take advantage of a strange quirk in the way the kernel maps the lower 1MB. For whatever
54 * reason, the VGA RAM, adapter ROM, and ROM BIOS areas are left open even for Win32 applications
55 * with no protection. Thus, a Win32 programmer can just make a pointer like
56 * char *a = (char*)0xA0000 and scribble on legacy VGA RAM to his heart's content (though on
57 * modern PCI SVGA hardware the driver probably instructs the card to disable VGA compatible
58 * mapping). In fact, this ability to scribble on RAM directly is at the heart of one of Microsoft's
59 * earliest and hackiest "Direct Draw" interfaces known as "DISPDIB.DLL", a not-to-well documented
60 * library responsible for those Windows 3.1 multimedia apps and games that were somehow able to
61 * run full-screen 320x200x256 color VGA despite being Windows GDI-based apps. Ever wonder how the
62 * MCI AVI player was able to go full-screen when DirectX and WinG were not invented yet? Now you
65 * There are some VFW codecs out there as well, that also like to abuse DISPDIB.DLL for "fullscreen"
66 * modes. One good example is the old "Motion Pixels" codec, that when asked to go fullscreen,
67 * uses DISPDIB.DLL and direct VGA I/O port trickery to effectively set up a 320x480 256-color mode,
68 * which it then draws on "fake hicolor" style to display the video (though a bit dim since you're
69 * sort of watching a video through a dithered mesh, but...)
71 * In case you were probably wondering, no, Windows NT doesn't allow Win32 applications the same
72 * privilege. Win32 apps writing to 0xA0000 would page fault and crash. Curiously enough though,
73 * NTVDM.EXE does seem to open up the 0xA0000-0xFFFFF memory area to Win16 applications if they
74 * use the right selectors and API calls. */
78 # if TARGET_MSDOS == 32
85 if (dosbox_detect_cache >= 0)
86 return (int)dosbox_detect_cache;
88 # if TARGET_MSDOS == 32
89 if (dos_flavor == DOS_FLAVOR_FREEDOS) {
90 /* FIXME: I have no idea why but FreeDOS 1.0 has a strange conflict with DOS32a where if this code
91 * tries to read the ROM BIOS it causes a GPF and crashes (or sometimes runs off into the
92 * weeds leaving a little garbage on the screen). DOS32a's register dump seems to imply that
93 * at one point our segment limits were suddenly limited to 1MB (0xFFFFF). I have no clue
94 * what the hell is triggering it, but I know from testing we can avoid that crash by not
96 if (freedos_kernel_version == 0x000024UL) /* 0.0.36 */
97 return (dosbox_detect_cache=0);
101 /* signs that we're running under DOSBOX:
102 * - the majority of the adapter ROM area is 0x00 (not 0xFF or any other value). Here we check 0xE000:0xFF00 and 0xF000:0x000.
103 * - an ASCII string is visible at 0xF000:0xE061: "DOSBox FakeBIOS v1.0" */
105 # if TARGET_MSDOS == 32
106 scan = (const char*)0xEFF00UL;
108 scan = (const char far*)MK_FP(0xE000,0xFF00);
111 for (i=0;i < 256;i++) {
113 return (dosbox_detect_cache=0);
116 # if TARGET_MSDOS == 32
117 scan = (const char*)0xF0000UL;
119 scan = (const char far*)MK_FP(0xF000,0x0000);
121 for (i=0;i < 256;i++) {
123 return (dosbox_detect_cache=0);
126 # if TARGET_MSDOS == 32
127 scan = (const char*)0xFE061UL;
129 scan = (const char far*)MK_FP(0xF000,0xE061);
133 if (dosbox_fakebios[i] != scan[i])
134 return (dosbox_detect_cache=0);
135 } while (dosbox_fakebios[i++] != 0);
137 return (dosbox_detect_cache=1);