summaryrefslogtreecommitdiff
path: root/board/MAI/bios_emulator/scitech/src/common/gawin32.c
blob: a2a4150953b4bcf3ee34b4c8575948f3ab469ef1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/****************************************************************************
*
*                   SciTech Nucleus Graphics Architecture
*
*               Copyright (C) 1991-1998 SciTech Software, Inc.
*                            All rights reserved.
*
*  ======================================================================
*  |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
*  |                                                                    |
*  |This copyrighted computer code contains proprietary technology      |
*  |owned by SciTech Software, Inc., located at 505 Wall Street,        |
*  |Chico, CA 95928 USA (http://www.scitechsoft.com).                   |
*  |                                                                    |
*  |The contents of this file are subject to the SciTech Nucleus        |
*  |License; you may *not* use this file or related software except in  |
*  |compliance with the License. You may obtain a copy of the License   |
*  |at http://www.scitechsoft.com/nucleus-license.txt                   |
*  |                                                                    |
*  |Software distributed under the License is distributed on an         |
*  |"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or      |
*  |implied. See the License for the specific language governing        |
*  |rights and limitations under the License.                           |
*  |                                                                    |
*  |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
*  ======================================================================
*
* Language:     ANSI C
* Environment:  Win32
*
* Description:  OS specific Nucleus Graphics Architecture services for
*               the Win32 operating system environments.
*
****************************************************************************/

#include "pm_help.h"
#include "pmapi.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

/*------------------------- Global Variables ------------------------------*/

#define DLL_NAME        "nga_w32.dll"

extern HANDLE           _PM_hDevice;
static HMODULE          hModDLL = NULL;
static ibool            useRing0Driver = false;
static ibool            haveRDTSC;
static GA_largeInteger  countFreq;

/*-------------------------- Implementation -------------------------------*/

/****************************************************************************
REMARKS:
Loads the shared "nga_w32.dll" library from disk and connects to it. This
library is *always* located in the same directory as the Nucleus
graphics.bpd file.
****************************************************************************/
static ibool LoadSharedDLL(void)
{
    char                filename[PM_MAX_PATH];
    char                bpdpath[PM_MAX_PATH];

    /* Check if we have already loaded the DLL */
    if (hModDLL)
        return true;
    PM_init();

    /* Open the DLL file */
    if (!PM_findBPD(DLL_NAME,bpdpath))
        return false;
    strcpy(filename,bpdpath);
    strcat(filename,DLL_NAME);
    if ((hModDLL = LoadLibrary(filename)) == NULL)
        return false;
    return true;
}

/****************************************************************************
PARAMETERS:
path    - Local path to the Nucleus driver files.

REMARKS:
This function is used by the application program to override the location
of the Nucleus driver files that are loaded. Normally the loader code
will look in the system Nucleus directories first, then in the 'drivers'
directory relative to the current working directory, and finally relative
to the MGL_ROOT environment variable.

Note that for Win32 we also call into the loaded PMHELP device driver
as necessary to change the local Nucleus path for system wide Nucleus
drivers.
****************************************************************************/
void NAPI GA_setLocalPath(
    const char *path)
{
    DWORD   inBuf[1];
    DWORD   outBuf[1],outCnt;

    PM_setLocalBPDPath(path);
    if (_PM_hDevice != INVALID_HANDLE_VALUE) {
        inBuf[0] = (DWORD)path;
        DeviceIoControl(_PM_hDevice, PMHELP_GASETLOCALPATH32,
            inBuf, sizeof(inBuf), outBuf, sizeof(outBuf), &outCnt, NULL);
        }
}

/****************************************************************************
RETURNS:
Pointer to the system wide PM library imports, or the internal version if none

REMARKS:
In order to support deploying new Nucleus drivers that may require updated
PM library functions, we check here to see if there is a system wide version
of the PM functions available. If so we return those functions for use with
the system wide Nucleus drivers, otherwise the compiled in version of the PM
library is used with the application local version of Nucleus.
****************************************************************************/
PM_imports * NAPI GA_getSystemPMImports(void)
{
    PM_imports * pmImp;
    PM_imports * (NAPIP _GA_getSystemPMImports)(void);

    if (LoadSharedDLL()) {
        /* Note that Visual C++ build DLL's with only a single underscore in front
         * of the exported name while Watcom C provides two of them. We check for
         * both to allow working with either compiled DLL.
         */
        if ((_GA_getSystemPMImports = (void*)GetProcAddress(hModDLL,"_GA_getSystemPMImports")) != NULL) {
            if ((_GA_getSystemPMImports = (void*)GetProcAddress(hModDLL,"__GA_getSystemPMImports")) != NULL) {
                pmImp = _GA_getSystemPMImports();
                memcpy(&_PM_imports,pmImp,MIN(_PM_imports.dwSize,pmImp->dwSize));
                return pmImp;
                }
            }
        }
    return &_PM_imports;
}

/****************************************************************************
PARAMETERS:
gaExp   - Place to store the exported functions
shared  - True if connecting to the shared, global Nucleus driver

REMARKS:
For Win32 if we are connecting to the shared, global Nucleus driver (loaded
at ring 0) then we need to load a special nga_w32.dll library which contains
thunks to call down into the Ring 0 device driver as necessary. If we are
connecting to the application local Nucleus drivers (ie: Nucleus on DirectDraw
emulation layer) then we do nothing here.
****************************************************************************/
ibool NAPI GA_getSharedExports(
    GA_exports *gaExp,
    ibool shared)
{
    GA_exports * exp;
    GA_exports * (NAPIP _GA_getSystemGAExports)(void);

    useRing0Driver = false;
    if (shared) {
        if (!LoadSharedDLL())
            PM_fatalError("Unable to load " DLL_NAME "!");
        if ((_GA_getSystemGAExports = (void*)GetProcAddress(hModDLL,"_GA_getSystemGAExports")) == NULL)
            if ((_GA_getSystemGAExports = (void*)GetProcAddress(hModDLL,"__GA_getSystemGAExports")) == NULL)
                PM_fatalError("Unable to load " DLL_NAME "!");
        exp = _GA_getSystemGAExports();
        memcpy(gaExp,exp,MIN(gaExp->dwSize,exp->dwSize));
        useRing0Driver = true;
        return true;
        }
    return false;
}

#ifndef TEST_HARNESS
/****************************************************************************
REMARKS:
Nothing special for this OS
****************************************************************************/
ibool NAPI GA_queryFunctions(
    GA_devCtx *dc,
    N_uint32 id,
    void _FAR_ *funcs)
{
    static ibool (NAPIP _GA_queryFunctions)(GA_devCtx *dc,N_uint32 id,void _FAR_ *funcs) = NULL;

    if (useRing0Driver) {
        // Call the version in nga_w32.dll if it is loaded
        if (!_GA_queryFunctions) {
            if ((_GA_queryFunctions = (void*)GetProcAddress(hModDLL,"_GA_queryFunctions")) == NULL)
                if ((_GA_queryFunctions = (void*)GetProcAddress(hModDLL,"__GA_queryFunctions")) == NULL)
                    PM_fatalError("Unable to get exports from " DLL_NAME "!");
            }
        return _GA_queryFunctions(dc,id,funcs);
        }
    return __GA_exports.GA_queryFunctions(dc,id,funcs);
}

/****************************************************************************
REMARKS:
Nothing special for this OS
****************************************************************************/
ibool NAPI REF2D_queryFunctions(
    REF2D_driver *ref2d,
    N_uint32 id,
    void _FAR_ *funcs)
{
    static ibool (NAPIP _REF2D_queryFunctions)(REF2D_driver *ref2d,N_uint32 id,void _FAR_ *funcs) = NULL;

    if (useRing0Driver) {
        // Call the version in nga_w32.dll if it is loaded
        if (!_REF2D_queryFunctions) {
            if ((_REF2D_queryFunctions = (void*)GetProcAddress(hModDLL,"_REF2D_queryFunctions")) == NULL)
                if ((_REF2D_queryFunctions = (void*)GetProcAddress(hModDLL,"__REF2D_queryFunctions")) == NULL)
                    PM_fatalError("Unable to get exports from " DLL_NAME "!");
            }
        return _REF2D_queryFunctions(ref2d,id,funcs);
        }
    return __GA_exports.REF2D_queryFunctions(ref2d,id,funcs);
}
#endif

/****************************************************************************
REMARKS:
This function initialises the high precision timing functions for the
Nucleus loader library.
****************************************************************************/
ibool NAPI GA_TimerInit(void)
{
    if (_GA_haveCPUID() && (_GA_getCPUIDFeatures() & CPU_HaveRDTSC) != 0) {
        haveRDTSC = true;
        return true;
        }
    else if (QueryPerformanceFrequency((LARGE_INTEGER*)&countFreq)) {
        haveRDTSC = false;
        return true;
        }
    return false;
}

/****************************************************************************
REMARKS:
This function reads the high resolution timer.
****************************************************************************/
void NAPI GA_TimerRead(
    GA_largeInteger *value)
{
    if (haveRDTSC)
        _GA_readTimeStamp(value);
    else
        QueryPerformanceCounter((LARGE_INTEGER*)value);
}