]> 4ch.mooo.com Git - 16.git/blob - src/lib/dl/dos.h
wwww
[16.git] / src / lib / dl / dos.h
1 /* dos.h
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 #ifndef __HW_DOS_DOS_H
12 #define __HW_DOS_DOS_H
13
14 #include "src/lib/doslib/cpu.h"
15 //#include "src/lib/16_head.h"
16 #include <stdint.h>
17
18 #if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
19 /* NTVDM.EXE DOSNTAST.VDD call support */
20 //#include <windows/ntvdm/ntvdmlib.h>
21 #endif
22
23 #if defined(TARGET_OS2)
24 # define INCL_DOSMISC
25 # ifdef FAR /* <- conflict between OS/2 headers and cpu.h definition of "FAR" */
26 #  undef FAR
27 # endif
28 # include <os2.h>
29 #endif
30
31 extern unsigned char FAR *dos_LOL;
32
33 #if TARGET_MSDOS == 32 && !defined(TARGET_OS2)
34 extern int8_t dpmi_no_0301h; /* -1 = not tested 0 = avail 1 = N/A */
35 #else
36 # define dpmi_no_0301h 0 /* FIXME: Is it possible for DOS extenders to run non-4GW non-LE executables? */
37 #endif
38
39 #define DPMI_ENTER_AUTO 0xFF
40
41 /* DOS "Flavor" we are running under.
42  * I originally didn't care too much until one day some really strange
43  * fatal bugs popped up when running this code under FreeDOS 1.0, almost
44  * as if the FreeDOS kernel does something to fuck with the DOS extender's
45  * mind if our code attempts certain things like reading the ROM area... */
46 enum {
47         DOS_FLAVOR_NONE=0,              /* generic DOS */
48         DOS_FLAVOR_MSDOS,               /* Microsoft MS-DOS */
49         DOS_FLAVOR_FREEDOS,             /* FreeDOS */
50 };
51
52 extern uint8_t dos_flavor;
53 extern uint16_t dos_version;
54 extern const char *dos_version_method;
55 extern uint32_t freedos_kernel_version;
56 #if TARGET_MSDOS == 32
57 extern char *freedos_kernel_version_str;
58 #else
59 extern char far *freedos_kernel_version_str;
60 #endif
61 extern unsigned char vcpi_present;
62 extern unsigned char vcpi_major_version,vcpi_minor_version;
63
64 struct dos_mcb_enum {
65         uint16_t        segment;
66         uint16_t        counter;
67         /* acquired data */
68         unsigned char FAR *ptr; /* pointer to actual memory content */
69         uint16_t        size,psp,cur_segment;
70         uint8_t         type;
71         char            name[9];
72 };
73
74 #pragma pack(push,1)
75 struct dpmi_realmode_call {
76         uint32_t        edi,esi,ebp,reserved;
77         uint32_t        ebx,edx,ecx,eax;
78         uint16_t        flags,es,ds,fs,gs,ip,cs,sp,ss;
79 };
80 #pragma pack(pop)
81
82 #ifndef TARGET_OS2
83 # if TARGET_MSDOS == 32
84 /* WARNING: This is only 100% reliable if the memory in question is below the 1MB mark!
85  *          This may happen to work for pointers above the 1MB mark because DOS4GW and DOS32a tend to
86  *          allocate that way, but that 1:1 correspondence is not guaranteed */
87 static inline uint32_t ptr2phys_low1mb(unsigned char *x) {
88         return (uint32_t)x;
89 }
90 # else
91 static inline uint32_t ptr2phys_low1mb(unsigned char far *x) {
92         uint32_t r = (uint32_t)FP_SEG(x) << 4UL;
93         return r + (uint32_t)FP_OFF(x);
94 }
95 # endif
96 #endif
97
98 #if TARGET_MSDOS == 16 && !defined(TARGET_OS2)
99 static inline void far *normalize_realmode_far_ptr(void far *p) {
100         return MK_FP(
101                 FP_SEG(p) + (FP_OFF(p) >> 4),
102                 FP_OFF(p) & 0xF);
103 }
104 #endif
105
106 #ifndef TARGET_OS2
107 # if TARGET_MSDOS == 32
108 int _dos_xread(int fd,void *buffer,int bsz);
109 # else
110 int _dos_xread(int fd,void far *buffer,int bsz);
111 # endif
112
113 # if TARGET_MSDOS == 32
114 int _dos_xwrite(int fd,void *buffer,int bsz);
115 # else
116 int _dos_xwrite(int fd,void far *buffer,int bsz);
117 # endif
118 #endif
119
120 #if TARGET_MSDOS == 32 && !defined(TARGET_OS2)
121 #  define dpmi_alloc_descriptor() dpmi_alloc_descriptors(1)
122
123 void *dpmi_alloc_dos(unsigned long len,uint16_t *selector);
124 void dpmi_free_dos(uint16_t selector);
125
126 void dpmi_free_descriptor(uint16_t d);
127 uint16_t dpmi_alloc_descriptors(uint16_t c);
128 unsigned int dpmi_set_segment_base(uint16_t sel,uint32_t base);
129 unsigned int dpmi_set_segment_limit(uint16_t sel,uint32_t limit);
130 unsigned int dpmi_set_segment_access(uint16_t sel,uint16_t access);
131 void *dpmi_phys_addr_map(uint32_t phys,uint32_t size);
132 void dpmi_phys_addr_free(void *base);
133 #endif
134
135 #if TARGET_MSDOS == 32
136 unsigned char *dos_list_of_lists();
137 #else
138 unsigned char far *dos_list_of_lists();
139 #endif
140
141 #if TARGET_MSDOS == 32 && !defined(TARGET_OS2)
142 int dpmi_alternate_rm_call(struct dpmi_realmode_call *rc);
143 int dpmi_alternate_rm_call_stacko(struct dpmi_realmode_call *rc);
144 #endif
145
146 #if TARGET_MSDOS == 32 && !defined(TARGET_OS2)
147 # if defined(TARGET_WINDOWS)
148 /* as a 32-bit Windows program: even if DPMI is present, it's useless to us because we can't call into that part of Windows */
149 #  define dpmi_present 0
150 # endif
151 #endif
152 #if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS))
153 /* as a 16-bit program (DOS or Windows), DPMI might be present. Note that DPMI can be present even under NTVDM.EXE under Windows NT,
154  * because NTVDM.EXE will emulate some DPMI functions. */
155 extern unsigned char dpmi_present;
156 extern uint16_t dpmi_flags;
157 extern unsigned char dpmi_init;
158 extern uint32_t dpmi_entry_point; /* NTS: This is the real-mode address, even for 32-bit builds */
159 extern unsigned char dpmi_processor_type;
160 extern uint16_t dpmi_version;
161 extern uint16_t dpmi_private_data_length_paragraphs;
162 extern uint16_t dpmi_private_data_segment;
163 extern unsigned char dpmi_entered;      /* 0=not yet entered, 16=entered as 16bit, 32=entered as 32bit */
164 extern uint64_t dpmi_rm_entry;
165 extern uint32_t dpmi_pm_entry;
166 extern uint16_t dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss;
167
168 void __cdecl dpmi_enter_core(); /* Watcom's inline assembler is too limiting to carry out the DPMI entry and switch back */
169 #endif
170
171 #if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
172 int dpmi_private_alloc();
173 int dpmi_enter(unsigned char mode);
174 #endif
175
176 void probe_dos();
177 void probe_dpmi();
178 int probe_vcpi();
179
180 uint16_t dos_mcb_first_segment();
181 int mcb_name_is_junk(char *s/*8 char*/);
182 int dos_mcb_next(struct dos_mcb_enum *e);
183 int dos_mcb_first(struct dos_mcb_enum *e);
184 void mcb_filter_name(struct dos_mcb_enum *e);
185 unsigned char FAR *dos_mcb_get_psp(struct dos_mcb_enum *e);
186
187 struct dos_psp_cooked {
188         unsigned char FAR *raw;
189         uint16_t        memsize,callpsp,env;
190         char            cmd[130];
191 };
192
193 int dos_parse_psp(uint16_t seg,struct dos_psp_cooked *e);
194
195 struct dos_device_enum {
196         unsigned char FAR *raw,FAR *next;
197         uint16_t                ns,no,attr,entry,intent,count;
198         char                    name[9];
199 };
200
201 int dos_device_first(struct dos_device_enum *e);
202 int dos_device_next(struct dos_device_enum *e);
203
204 #if TARGET_MSDOS == 16 && !defined(TARGET_OS2)
205 uint32_t dos_linear_to_phys_vcpi(uint32_t pn);
206 #endif
207
208 #if TARGET_MSDOS == 32
209 extern struct dos_linear_to_phys_info dos_ltp_info;
210 extern unsigned char dos_ltp_info_init;
211
212 int dos_ltp_probe();
213
214 /* NTS: The return value is 64-bit so that in scenarios where we hack DPMI to support PSE and PAE modes,
215  *      the function will still return the physical address associated with the page even when it's above
216  *      the 4GB boundary. But as a 32-bit DOS program, the linear addresses will never exceed 32-bit. */
217 uint64_t dos_linear_to_phys(uint32_t linear);
218
219 int dpmi_linear_lock(uint32_t lin,uint32_t size);
220 int dpmi_linear_unlock(uint32_t lin,uint32_t size);
221 void *dpmi_linear_alloc(uint32_t try_lin,uint32_t size,uint32_t flags,uint32_t *handle);
222 int dpmi_linear_free(uint32_t handle);
223
224 #define DOS_LTP_FAILED 0xFFFFFFFFFFFFFFFFULL
225
226 struct dos_linear_to_phys_info {
227         unsigned char           paging:1;               /* paging is enabled, therefore mapping will occur. if not set, then linear == physical memory addresses */
228         unsigned char           dos_remap:1;            /* if set, the lower 1MB region (DOS conventional memory) is remapped. if clear, we can assume 1:1 mapping below 1MB */
229         unsigned char           should_lock_pages:1;    /* if set, the program should call DPMI functions to lock pages before attempting to get physical memory address */
230         unsigned char           cant_xlate:1;           /* if set, resources to determine physical memory addresses are not available (such as: running in a Windows DOS Box). however dos_remap=0 means we can assume 1:1 mapping below 1MB */
231         unsigned char           using_pae:1;            /* if set, the DOS extender or DPMI host has PAE/PSE extensions enabled. This changes how page tables are parsed, and can prevent us from mapping */
232         unsigned char           dma_dos_xlate:1;        /* usually set if dos_remap=1 to say the DOS extender or environment translates DMA addresses (i.e. Windows DOS Box), but we can't actually know the physical memory address. We can do DMA from DOS memory */
233         unsigned char           vcpi_xlate:1;           /* use VCPI to translate linear -> phys */
234         unsigned char           reserved:1;
235         uint32_t                cr0;
236         uint32_t                cr3;                    /* last known copy of the CR3 (page table base) register */
237         uint32_t                cr4;                    /* last known copy of the CR4 register */
238 };
239 #endif
240
241 #define BIOS_KS_ALT             0x08
242 #define BIOS_KT_CTRL            0x04
243
244 static inline unsigned char read_bios_keystate() { /* from 0x40:0x17 */
245 #if TARGET_MSDOS == 32
246         return *((unsigned char*)(0x400 + 0x17));
247 #else
248         return *((unsigned char far*)MK_FP(0x40,0x17));
249 #endif
250 }
251
252 #if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16
253 void far *win16_getexhandler(unsigned char n);
254 int win16_setexhandler(unsigned char n,void far *x);
255 void far *win16_getvect(unsigned char n);
256 int win16_setvect(unsigned char n,void far *x);
257 #endif
258
259 #if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32
260 typedef struct Win32OrdinalLookupInfo {
261         DWORD   entries,base,base_addr;
262         DWORD*  table;
263 } Win32OrdinalLookupInfo;
264
265 DWORD *Win32GetExportOrdinalTable(HMODULE mod,DWORD *entries,DWORD *base,DWORD *base_addr);
266 void *Win32GetOrdinalAddress(Win32OrdinalLookupInfo *nfo,unsigned int ord);
267 int Win32GetOrdinalLookupInfo(HMODULE mod,Win32OrdinalLookupInfo *info);
268 #endif
269
270 #if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16
271 extern DWORD            genthunk32w_ntdll;
272 extern DWORD            genthunk32w_kernel32;
273 extern DWORD            genthunk32w_kernel32_GetVersion;
274 extern DWORD            genthunk32w_kernel32_GetVersionEx;
275 extern DWORD            genthunk32w_kernel32_GetLastError;
276 extern BOOL             __GenThunksExist;
277 extern BOOL             __GenThunksChecked;
278 extern DWORD            (PASCAL FAR *__LoadLibraryEx32W)(LPCSTR lpName,DWORD a,DWORD b);
279 extern BOOL             (PASCAL FAR *__FreeLibrary32W)(DWORD hinst);
280 extern DWORD            (PASCAL FAR *__GetProcAddress32W)(DWORD hinst,LPCSTR name);
281 extern DWORD            (PASCAL FAR *__GetVDMPointer32W)(LPVOID ptr,UINT mask);
282 extern DWORD            (_cdecl _far *__CallProcEx32W)(DWORD params,DWORD convertMask,DWORD procaddr32,...);
283
284 /* NOTE: You call it as if it were declared CallProc32W(..., DWORD hinst,DWORD convertMask,DWORD procaddr32); Ick */
285 extern DWORD            (PASCAL FAR *__CallProc32W)(DWORD hinst,DWORD convertMask,DWORD procaddr32,...);
286
287 /* it would be nice if Open Watcom defined these constants for Win16 */
288 #define CPEX_DEST_STDCALL       0x00000000UL
289 #define CPEX_DEST_CDECL         0x80000000UL
290
291 int genthunk32_init();
292 void genthunk32_free();
293 #endif
294
295 #if TARGET_MSDOS == 16 || !defined(TARGET_WINDOWS)
296 #pragma pack(push,4)
297 /* OpenWatcom does not define the OSVERSIONINFO struct for Win16 */
298 typedef struct OSVERSIONINFO {
299         uint32_t        dwOSVersionInfoSize;
300         uint32_t        dwMajorVersion;
301         uint32_t        dwMinorVersion;
302         uint32_t        dwBuildNumber;
303         uint32_t        dwPlatformId;
304         char            szCSDVersion[128];
305 } OSVERSIONINFO;
306
307 #define MAXPNAMELEN             32
308
309 #define WAVECAPS_PITCH          0x0001
310 #define WAVECAPS_PLAYBACKRATE   0x0002
311 #define WAVECAPS_VOLUME         0x0004
312 #define WAVECAPS_LRVOLUME       0x0008
313 #define WAVECAPS_SYNC           0x0010
314 #define WAVECAPS_SAMPLEACCURATE 0x0020
315
316 typedef struct WAVEOUTCAPS {
317         uint16_t        wMid;
318         uint16_t        wPid;
319         uint32_t        vDriverVersion;
320         char            szPname[MAXPNAMELEN];
321         uint32_t        dwFormats;
322         uint16_t        wChannels;
323         uint16_t        wReserved1;
324         uint32_t        dwSupport;
325 } WAVEOUTCAPS;
326 #pragma pack(pop)
327 #endif
328
329 #if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
330 void far *dpmi_getexhandler(unsigned char n);
331 int dpmi_setexhandler(unsigned char n,void far *x);
332 #endif
333
334 #if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
335 /* TODO: This should be moved into the hw/DOS library */
336 extern unsigned char            nmi_32_hooked;
337 extern int                      nmi_32_refcount;
338 extern void                     (interrupt *nmi_32_old_vec)();
339
340 void do_nmi_32_unhook();
341 void do_nmi_32_hook();
342 #endif
343
344 #if defined(TARGET_MSDOS) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
345 enum {
346         DOS_CLOSE_AWARENESS_NOT_ACK=0,
347         DOS_CLOSE_AWARENESS_ACKED=1
348 };
349
350 void dos_vm_yield();
351 void dos_close_awareness_ack();
352 int dos_close_awareness_query();
353 void dos_close_awareness_cancel();
354 int dos_close_awareness_available();
355 int dos_close_awareness_enable(unsigned char en);
356 #endif
357
358 /* unlike DOSBox, VirtualBox's ROM BIOS contains it's version number, which we copy down here */
359 extern char virtualbox_version_str[64];
360
361 int detect_virtualbox_emu();
362
363 #if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
364 int __cdecl dpmi_lin2fmemcpy_32(unsigned char far *dst,uint32_t lsrc,uint32_t sz);
365 int __cdecl dpmi_lin2fmemcpy_16(unsigned char far *dst,uint32_t lsrc,uint32_t sz);
366 int dpmi_lin2fmemcpy(unsigned char far *dst,uint32_t lsrc,uint32_t sz);
367 int dpmi_lin2fmemcpy_init();
368 #endif
369
370 struct lib_dos_options {
371         uint8_t                 dont_load_dosntast:1;   /* do not automatically load DOSNTAST, but use it if loaded. */
372                                                         /* if not loaded and the program wants it later on, it should
373                                                          * call ntvdm_dosntast_load_vdd(); */
374         uint8_t                 dont_use_dosntast:1;    /* do not use DOSNTAST, even if loaded */
375         uint8_t                 __reserved__:6;
376 };
377
378 extern struct lib_dos_options lib_dos_option;
379
380 # define DOSNTAST_HANDLE_UNASSIGNED             0xFFFFU
381
382 # define DOSNTAST_INIT_REPORT_HANDLE            0xD0500000
383 # define DOSNTAST_INIT_REPORT_HANDLE_C          0xD0500000ULL
384 /* in: EBX = DOSNTAST_INIT_REPORT_HANDLE
385  *     ECX = NTVDM handle
386  * out: EBX = 0x55AA55AA
387  *      ECX = flat memory address where signature is stored (must be in BIOS data area) */
388
389 # define DOSNTAST_GETVERSIONEX                  0xD0500001
390 # define DOSNTAST_GETVERSIONEX_C                0xD0500001ULL
391 /* in: EBX = <command>
392  *     ECX = protected mode call (1) or real-mode call (0)
393  *     DS:ESI = OSVERSIONINFO struct
394  * out: EBX = result
395  *     DS:ESI = filled in with OS struct */
396
397 # define DOSNTAST_GET_TICK_COUNT                0xD0500002
398 # define DOSNTAST_GET_TICK_COUNT_C              0xD0500002ULL
399 /* in: EBX = <command>
400  * out: EBX = tick count */
401
402 # define DOSNTAST_GET_IO_PORT                   0xD0500003
403 # define DOSNTAST_GET_IO_PORT_C                 0xD0500003ULL
404 /* in: EBX = <command>
405  * out: EBX = 0x55AA55AA
406  *      EDX = I/O port base */
407
408 # define DOSNTAST_NOTIFY_UNLOAD                 0xD050FFFF
409 # define DOSNTAST_NOTIFY_UNLOAD_C               0xD050FFFFULL
410 /* in: EBX = <command>
411  * out: EBX = none */
412
413 # define DOSNTAST_FUNCTION_GENERAL              0x1000
414 #  define DOSNTAST_FUN_GEN_SUB_MESSAGEBOX       0x0000
415
416 # define DOSNTAST_FUNCTION_WINMM                        0x1001
417 #  define DOSNTAST_FUN_WINMM_SUB_waveOutGetNumDevs      0x0000
418 #  define DOSNTAST_FUN_WINMM_SUB_waveOutGetDevCaps      0x0001
419 #  define DOSNTAST_FUN_WINMM_SUB_waveOutOpen            0x0002
420
421 const char *dos_flavor_str(uint8_t f);
422
423 /* Windows NT-friendly version of Win386 MapAliasToFlat.
424  * The library version is naive and assumes Windows 3.x/9x/ME behavior.
425  * If you need to convert pointers NOT given by Win386's AllocAlias() functions
426  * (such as 16:16 pointers given by Window messages) and need the code to gracefully
427  * handle itself under Windows NT, use this function not MapAliasToFlat() */
428 #if TARGET_MSDOS == 32 && defined(WIN386)
429 void far *win386_alt_winnt_MapAliasToFlat(DWORD farptr);
430 void far *win386_help_MapAliasToFlat(DWORD farptr);
431 #endif
432
433 #if (TARGET_MSDOS == 16 || TARGET_MSDOS == 32) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)
434 extern unsigned short                   smartdrv_version;
435 extern int                              smartdrv_fd;
436
437 int smartdrv_close();
438 int smartdrv_flush();
439 int smartdrv_detect();
440 #endif
441
442 uint32_t dos_linear_to_phys_vcpi(uint32_t pn);
443
444 #endif /* __HW_DOS_DOS_H */
445