rinit.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199
  1. /*=============================================================================
  2. Name : rinit.cpp
  3. Purpose : rGL / OpenGL enumeration initialization routines
  4. Created 1/5/1999 by khent
  5. Copyright Relic Entertainment, Inc. All rights reserved.
  6. =============================================================================*/
  7. #define WIN32_LEAN_AND_MEAN
  8. #define STRICT
  9. #define D3D_OVERLOADS
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include <ddraw.h>
  13. #include <dinput.h>
  14. #include <d3drm.h>
  15. #include <stdio.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "rinit.h"
  20. #include "devstats.h"
  21. extern "C" unsigned int glNT;
  22. extern "C" unsigned int gl95;
  23. extern "C" unsigned int mainSoftwareDirectDraw;
  24. extern "C" unsigned int mainOutputCRC;
  25. extern "C" unsigned long strCurLanguage;
  26. #define RIN_MODESINDEVSTATLIST 10
  27. unsigned int rinDevstatModeTable[RIN_MODESINDEVSTATLIST][3] =
  28. {
  29. 16, 640, DEVSTAT_NO_64048016,
  30. 16, 800, DEVSTAT_NO_80060016,
  31. 16, 1024, DEVSTAT_NO_102476816,
  32. 16, 1280, DEVSTAT_NO_1280102416,
  33. 16, 1600, DEVSTAT_NO_1600120016,
  34. 32, 640, DEVSTAT_NO_64048032,
  35. 32, 800, DEVSTAT_NO_80060032,
  36. 32, 1024, DEVSTAT_NO_102476832,
  37. 32, 1280, DEVSTAT_NO_1280102432,
  38. 32, 1600, DEVSTAT_NO_1600120032,
  39. };
  40. extern "C" unsigned int* devTable;
  41. extern "C" int devTableLength;
  42. //3dfx fullscreen-only present boolean
  43. static bool bFullscreenDevice;
  44. static rdevice* rDeviceList;
  45. static int nDevices;
  46. extern "C" unsigned int gDevcaps = 0xFFFFFFFF;
  47. extern "C" unsigned int gDevcaps2 = 0x00000000;
  48. char* gDescription = NULL;
  49. char* gDriverName = NULL;
  50. typedef HRESULT(WINAPI * DIRECTDRAWCREATE)(GUID*, LPDIRECTDRAW*, IUnknown*);
  51. typedef HRESULT(WINAPI * DIRECTINPUTCREATE)(HINSTANCE, DWORD, LPDIRECTINPUT*, IUnknown*);
  52. #define SST_VOODOO 0
  53. #define SST_VOODOO2 1
  54. #define SST_OTHER 2
  55. extern "C" unsigned int sstHardwareExists(int*);
  56. extern "C" unsigned int glCapNT(void);
  57. void* memAlloc(int size)
  58. {
  59. unsigned char* block;
  60. block = (unsigned char*)malloc(size);
  61. memset(block, 0, size);
  62. return (void*)block;
  63. }
  64. void memFree(void* memblock)
  65. {
  66. free(memblock);
  67. }
  68. extern "C" unsigned int crc32Compute(void*, unsigned int);
  69. /*-----------------------------------------------------------------------------
  70. Name : rinDeviceCRC
  71. Description : generate a CRC of the detected devices for detection of
  72. changing hardware (light assurance that previous video
  73. mode will still be working correctly)
  74. Inputs :
  75. Outputs :
  76. Return : crc32
  77. ----------------------------------------------------------------------------*/
  78. unsigned int rinDeviceCRC(void)
  79. {
  80. rdevice* cdev;
  81. rdevice* devlist;
  82. rdevice* pdevlist;
  83. unsigned int crc;
  84. if (nDevices == 0 || rDeviceList == NULL)
  85. {
  86. return 0;
  87. }
  88. devlist = (rdevice*)memAlloc(nDevices * sizeof(rdevice));
  89. pdevlist = devlist;
  90. cdev = rDeviceList;
  91. do
  92. {
  93. memcpy(pdevlist, cdev, sizeof(rdevice));
  94. pdevlist->modes = NULL;
  95. pdevlist->next = NULL;
  96. pdevlist++;
  97. cdev = cdev->next;
  98. } while (cdev != NULL);
  99. crc = crc32Compute((void*)devlist, nDevices * sizeof(rdevice));
  100. memFree(devlist);
  101. return crc;
  102. }
  103. /*-----------------------------------------------------------------------------
  104. Name : rinAddMode
  105. Description : add a display mode to a video driver
  106. Inputs : dev - the device to add the mode to
  107. width, height - dimensions
  108. depth - bitdepth
  109. Outputs :
  110. Return :
  111. ----------------------------------------------------------------------------*/
  112. void rinAddMode(rdevice* dev, int width, int height, int depth)
  113. {
  114. rmode* mode;
  115. rmode* cmode;
  116. mode = (rmode*)memAlloc(sizeof(rmode));
  117. mode->width = width;
  118. mode->height = height;
  119. mode->depth = depth;
  120. if (dev->modes == NULL)
  121. {
  122. //no modes yet
  123. dev->modes = mode;
  124. mode->next = NULL;
  125. }
  126. else
  127. {
  128. //add to tail
  129. cmode = dev->modes;
  130. while (cmode->next != NULL)
  131. {
  132. cmode = cmode->next;
  133. }
  134. cmode->next = mode;
  135. mode->next = NULL;
  136. }
  137. }
  138. /*-----------------------------------------------------------------------------
  139. Name : rinModeAccepted
  140. Description : decides whether a given mode is supported
  141. Inputs : dev - the device in question
  142. width, height, depth - display mode characteristics
  143. Outputs :
  144. Return : true or false
  145. ----------------------------------------------------------------------------*/
  146. static bool rinModeAccepted(rdevice* dev, int width, int height, int depth)
  147. {
  148. int index;
  149. //accept 16 & 32 bit mode only
  150. if (depth != 16 && depth != 32)
  151. {
  152. return false;
  153. }
  154. //possibly eliminate 32bit modes, if devstats tells us to
  155. if (depth == 32)
  156. {
  157. if (dev->type == RIN_TYPE_DIRECT3D)
  158. {
  159. if (dev->devcaps & DEVSTAT_NO_32BIT)
  160. {
  161. return false;
  162. }
  163. }
  164. else if (dev->type == RIN_TYPE_OPENGL)
  165. {
  166. if ((dev->devcaps & DEVSTAT_NO_32BIT_GL) ||
  167. (dev->devcaps & DEVSTAT_NO_32BIT))
  168. {
  169. return false;
  170. }
  171. }
  172. }
  173. //only sane, supported, modes
  174. switch (width)
  175. {
  176. case 640:
  177. if (height != 480) return false;
  178. break;
  179. case 800:
  180. if (height != 600) return false;
  181. break;
  182. case 1024:
  183. if (height != 768) return false;
  184. break;
  185. case 1280:
  186. if (height != 1024) return false;
  187. break;
  188. case 1600:
  189. if (height != 1200) return false;
  190. break;
  191. default:
  192. return false;
  193. }
  194. //check for specifically disabled display modes
  195. for (index = 0; index < RIN_MODESINDEVSTATLIST; index++)
  196. {
  197. if (rinDevstatModeTable[index][0] == depth &&
  198. rinDevstatModeTable[index][1] == width)
  199. {
  200. if (dev->devcaps & rinDevstatModeTable[index][2])
  201. {
  202. return false;
  203. }
  204. }
  205. }
  206. return true;
  207. }
  208. /*-----------------------------------------------------------------------------
  209. Name : rinSortModes
  210. Description : sorts a device's display modes the way I like them
  211. (one bitdepth at a time)
  212. Inputs : dev - the device whose modes are to be sorted
  213. Outputs :
  214. Return :
  215. ----------------------------------------------------------------------------*/
  216. void rinSortModes(rdevice* dev)
  217. {
  218. rmode* cmode;
  219. rmode* freeMode;
  220. rdevice dummy;
  221. int depths[] = {16,32,0};
  222. int depth;
  223. if (dev->modes == NULL)
  224. {
  225. return;
  226. }
  227. memset(&dummy, 0, sizeof(rdevice));
  228. for (depth = 0; depths[depth] != 0; depth++)
  229. {
  230. cmode = dev->modes;
  231. do
  232. {
  233. if (cmode->depth == depths[depth])
  234. {
  235. if (rinModeAccepted(dev, cmode->width, cmode->height, cmode->depth))
  236. {
  237. rinAddMode(&dummy, cmode->width, cmode->height, cmode->depth);
  238. }
  239. }
  240. cmode = cmode->next;
  241. } while (cmode != NULL);
  242. }
  243. //free modes on dev
  244. cmode = dev->modes;
  245. while (cmode != NULL)
  246. {
  247. freeMode = cmode; //save to free
  248. cmode = cmode->next; //next
  249. memFree(freeMode); //free
  250. }
  251. //attach new modes
  252. dev->modes = dummy.modes;
  253. }
  254. /*-----------------------------------------------------------------------------
  255. Name : rinCopyModes
  256. Description : copy one driver's display modes to another
  257. Inputs : devOut - output device
  258. devIn - input device
  259. Outputs :
  260. Return :
  261. ----------------------------------------------------------------------------*/
  262. void rinCopyModes(rdevice* devOut, rdevice* devIn)
  263. {
  264. rmode* cmode;
  265. cmode = devIn->modes;
  266. if (cmode == NULL)
  267. {
  268. devOut->modes = NULL;
  269. }
  270. else
  271. {
  272. do
  273. {
  274. rinAddMode(devOut, cmode->width, cmode->height, cmode->depth);
  275. cmode = cmode->next;
  276. } while (cmode != NULL);
  277. }
  278. }
  279. /*-----------------------------------------------------------------------------
  280. Name : rinCopyModesSelectively
  281. Description : copy certain display modes from one device to another
  282. Inputs : devOut - output device
  283. devIn - input device
  284. depth - bitdepth of acceptable modes
  285. maxWidth - maximum acceptable width
  286. Outputs :
  287. Return :
  288. ----------------------------------------------------------------------------*/
  289. void rinCopyModesSelectively(rdevice* devOut, rdevice* devIn, int depth, int maxWidth)
  290. {
  291. rmode* cmode;
  292. cmode = devIn->modes;
  293. if (cmode == NULL)
  294. {
  295. devOut->modes = NULL;
  296. }
  297. else
  298. {
  299. do
  300. {
  301. if ((cmode->depth == depth) &&
  302. (cmode->width <= maxWidth))
  303. {
  304. rinAddMode(devOut, cmode->width, cmode->height, cmode->depth);
  305. }
  306. cmode = cmode->next;
  307. } while (cmode != NULL);
  308. }
  309. }
  310. /*-----------------------------------------------------------------------------
  311. Name : rinAddDevice
  312. Description : add a device to the head of the device list
  313. Inputs : dev - the device to add
  314. Outputs : rDeviceList is modified
  315. Return :
  316. ----------------------------------------------------------------------------*/
  317. void rinAddDevice(rdevice* dev)
  318. {
  319. rdevice* cdev;
  320. if (rDeviceList == NULL)
  321. {
  322. rDeviceList = dev;
  323. dev->next = NULL;
  324. }
  325. else
  326. {
  327. //add to head
  328. cdev = rDeviceList;
  329. dev->next = cdev;
  330. rDeviceList = dev;
  331. }
  332. }
  333. /*-----------------------------------------------------------------------------
  334. Name : rinGetDeviceList
  335. Description : return pointer to device list
  336. Inputs :
  337. Outputs :
  338. Return : rDeviceList
  339. ----------------------------------------------------------------------------*/
  340. rdevice* rinGetDeviceList(void)
  341. {
  342. return rDeviceList;
  343. }
  344. /*-----------------------------------------------------------------------------
  345. Name : rinFreeDevices
  346. Description : clear the device list (free memory and such)
  347. Inputs :
  348. Outputs : rDeviceList and constituents are freed
  349. Return :
  350. ----------------------------------------------------------------------------*/
  351. int rinFreeDevices(void)
  352. {
  353. rdevice* dev;
  354. rdevice* freeDev;
  355. rmode* mode;
  356. rmode* freeMode;
  357. //device loop
  358. dev = rDeviceList;
  359. while (dev != NULL)
  360. {
  361. //mode loop
  362. mode = dev->modes;
  363. while (mode != NULL)
  364. {
  365. freeMode = mode; //save to free
  366. mode = mode->next; //next
  367. memFree(freeMode); //free
  368. }
  369. freeDev = dev; //save to free
  370. dev = dev->next; //next
  371. memFree(freeDev); //free
  372. }
  373. rDeviceList = NULL;
  374. //success
  375. return 1;
  376. }
  377. /*-----------------------------------------------------------------------------
  378. Name : rinEnumDisplayModes_cb
  379. Description : callback during display mode enumeration
  380. Inputs : ...
  381. Outputs :
  382. Return :
  383. ----------------------------------------------------------------------------*/
  384. static HRESULT WINAPI rinEnumDisplayModes_cb(LPDDSURFACEDESC2 ddsd, LPVOID lpContext)
  385. {
  386. rdevice* dev;
  387. dev = (rdevice*)lpContext;
  388. if ((ddsd->dwFlags & DDSD_WIDTH) &&
  389. (ddsd->dwFlags & DDSD_HEIGHT) &&
  390. (ddsd->dwFlags & DDSD_PIXELFORMAT))
  391. {
  392. if (ddsd->ddpfPixelFormat.dwRGBBitCount != 16 &&
  393. ddsd->ddpfPixelFormat.dwRGBBitCount != 32)
  394. {
  395. goto SKIP_MODE;
  396. }
  397. if (ddsd->dwWidth < 640 || ddsd->dwHeight < 480)
  398. {
  399. goto SKIP_MODE;
  400. }
  401. if (ddsd->dwWidth > 1600)
  402. {
  403. goto SKIP_MODE;
  404. }
  405. rinAddMode(dev,
  406. ddsd->dwWidth, ddsd->dwHeight,
  407. ddsd->ddpfPixelFormat.dwRGBBitCount);
  408. }
  409. SKIP_MODE:
  410. return D3DENUMRET_OK;
  411. }
  412. /*-----------------------------------------------------------------------------
  413. Name : rinEnumPrimaryDisplayModes_cb
  414. Description : callback during display mode enumeration, old DDraw
  415. Inputs : ...
  416. Outputs :
  417. Return :
  418. ----------------------------------------------------------------------------*/
  419. static HRESULT WINAPI rinEnumPrimaryDisplayModes_cb(LPDDSURFACEDESC ddsd, LPVOID lpContext)
  420. {
  421. rdevice* dev;
  422. dev = (rdevice*)lpContext;
  423. if (dev == NULL)
  424. {
  425. goto SKIP_MODE;
  426. }
  427. if ((ddsd->dwFlags & DDSD_WIDTH) &&
  428. (ddsd->dwFlags & DDSD_HEIGHT) &&
  429. (ddsd->dwFlags & DDSD_PIXELFORMAT))
  430. {
  431. if (ddsd->ddpfPixelFormat.dwRGBBitCount != 16 &&
  432. ddsd->ddpfPixelFormat.dwRGBBitCount != 32)
  433. {
  434. goto SKIP_MODE;
  435. }
  436. if (ddsd->dwWidth < 640 || ddsd->dwHeight < 480)
  437. {
  438. goto SKIP_MODE;
  439. }
  440. if (ddsd->dwWidth > 1600)
  441. {
  442. goto SKIP_MODE;
  443. }
  444. rinAddMode(dev,
  445. ddsd->dwWidth, ddsd->dwHeight,
  446. ddsd->ddpfPixelFormat.dwRGBBitCount);
  447. }
  448. SKIP_MODE:
  449. return D3DENUMRET_OK;
  450. }
  451. static FILE* crcLog;
  452. static void rinResetCRCLog(void)
  453. {
  454. crcLog = fopen("d3dDeviceCRC.txt", "wt");
  455. }
  456. static void rinOutputCRC(LPSTR desc, LPSTR name, unsigned int crc)
  457. {
  458. if (crcLog != NULL)
  459. {
  460. fprintf(crcLog, "%08X [%s][%s]\n", crc, desc, name);
  461. }
  462. }
  463. static void rinCloseCRCLog(void)
  464. {
  465. if (crcLog != NULL)
  466. {
  467. fclose(crcLog);
  468. crcLog = NULL;
  469. }
  470. }
  471. D3DDEVICEDESC _caps;
  472. /*-----------------------------------------------------------------------------
  473. Name : rinEnoughCaps
  474. Description : check for at least alphablending and depthbuffering before
  475. considering this a valid device
  476. Inputs :
  477. Outputs :
  478. Return :
  479. ----------------------------------------------------------------------------*/
  480. bool rinEnoughCaps(LPSTR strDesc, LPSTR strName, LPD3DDEVICEDESC caps)
  481. {
  482. D3DPRIMCAPS* tri = &caps->dpcTriCaps;
  483. _caps = *caps;
  484. //reset some possibly variable fields
  485. _caps.dwSize = 0;
  486. _caps.dwFlags = 0;
  487. _caps.dcmColorModel = 0;
  488. _caps.dwDevCaps = 0;
  489. _caps.bClipping = 0;
  490. //check for alphablending, source caps first
  491. if (!(tri->dwSrcBlendCaps & D3DPBLENDCAPS_SRCALPHA) &&
  492. !(tri->dwSrcBlendCaps & D3DPBLENDCAPS_ONE))
  493. {
  494. return false;
  495. }
  496. //check dest blend caps
  497. if (!(tri->dwDestBlendCaps & D3DPBLENDCAPS_INVSRCALPHA) &&
  498. !(tri->dwDestBlendCaps & D3DPBLENDCAPS_ONE) &&
  499. !(tri->dwDestBlendCaps & D3DPBLENDCAPS_ZERO))
  500. {
  501. return false;
  502. }
  503. //it can blend, but can it depthbuffer ?
  504. if (!(tri->dwZCmpCaps & D3DPCMPCAPS_LESS) &&
  505. !(tri->dwZCmpCaps & D3DPCMPCAPS_LESSEQUAL))
  506. {
  507. return false;
  508. }
  509. //check for some kind of texture filtering
  510. if (!(tri->dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR) &&
  511. !(tri->dwTextureFilterCaps & D3DPTFILTERCAPS_NEAREST))
  512. {
  513. return false;
  514. }
  515. //check texture address caps
  516. if (!(tri->dwTextureAddressCaps & D3DPTADDRESSCAPS_CLAMP) &&
  517. !(tri->dwTextureAddressCaps & D3DPTADDRESSCAPS_WRAP))
  518. {
  519. return false;
  520. }
  521. return true;
  522. }
  523. //internal count of num valid devs on D3D object
  524. static int D3Ddevs;
  525. static int numD3Ddevs;
  526. static HRESULT WINAPI rinEnumDirect3DDevices_cb(
  527. GUID* pGUID, LPSTR strDesc, LPSTR strName, LPD3DDEVICEDESC pHALDesc,
  528. LPD3DDEVICEDESC pHELDesc, LPVOID pvContext)
  529. {
  530. int* devs = (int*)pvContext;
  531. if (pGUID == NULL || pHALDesc == NULL || pHELDesc == NULL)
  532. {
  533. return D3DENUMRET_CANCEL;
  534. }
  535. if (pHALDesc->dwFlags != 0)
  536. {
  537. //has a HAL, might be something we want. check caps
  538. if (rinEnoughCaps(strDesc, strName, pHALDesc))
  539. {
  540. D3Ddevs++;
  541. }
  542. }
  543. return D3DENUMRET_OK;
  544. }
  545. /*-----------------------------------------------------------------------------
  546. Name : rinEnumPrimary_cb
  547. Description : callback during DirectDraw <= 3 device enumeration
  548. Inputs : ...
  549. Outputs :
  550. Return :
  551. ----------------------------------------------------------------------------*/
  552. static BOOL WINAPI rinEnumPrimary_cb(
  553. GUID FAR* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext)
  554. {
  555. LPDIRECTDRAW ddraw;
  556. //only want primary
  557. if (lpGUID != NULL)
  558. {
  559. return D3DENUMRET_OK;
  560. }
  561. if (FAILED(DirectDrawCreate(lpGUID, &ddraw, NULL)))
  562. {
  563. return D3DENUMRET_OK;
  564. }
  565. ddraw->EnumDisplayModes(0, NULL, lpContext, rinEnumPrimaryDisplayModes_cb);
  566. return D3DENUMRET_OK;
  567. }
  568. static BOOL WINAPI rinEnum3Dfx_cb(
  569. GUID FAR* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext)
  570. {
  571. LPDIRECTDRAW ddraw;
  572. if (lpGUID == NULL)
  573. {
  574. //not interested in primary devices
  575. return D3DENUMRET_OK;
  576. }
  577. if (FAILED(DirectDrawCreate(lpGUID, &ddraw, NULL)))
  578. {
  579. //broken DirectDraw
  580. return D3DENUMRET_OK;
  581. }
  582. //enumerate display modes on this secondary device
  583. ddraw->EnumDisplayModes(0, NULL, lpContext, rinEnumPrimaryDisplayModes_cb);
  584. rdevice* dev = (rdevice*)lpContext;
  585. if (dev != NULL)
  586. {
  587. //setup 3dfx OpenGL device info
  588. dev->type = RIN_TYPE_OPENGL;
  589. strncpy(dev->data, lpDriverName, 63);
  590. strncpy(dev->name, lpDriverDescription, 63);
  591. dev->data[63] = '\0';
  592. dev->name[63] = '\0';
  593. }
  594. return D3DENUMRET_CANCEL;
  595. }
  596. void rinRemoveDriverFromName(char* name)
  597. {
  598. int pos;
  599. char buf[64];
  600. char* pdest;
  601. if (strlen(name) < 7)
  602. {
  603. return;
  604. }
  605. strncpy(buf, name, 63);
  606. buf[63] = '\0';
  607. _strlwr(buf);
  608. pdest = strstr(buf, "driver");
  609. if (pdest != NULL && pdest != name)
  610. {
  611. if (name[pdest - buf - 1] == ' ')
  612. {
  613. name[pdest - buf - 1] = '\0';
  614. }
  615. }
  616. }
  617. /*-----------------------------------------------------------------------------
  618. Name : rinFindDevCaps
  619. Description : find a given device's eliminated caps in the devTable
  620. Inputs : crc0 - crc of driver's caps
  621. crc1 - crc of device type
  622. cap[01] - where the cap flags go
  623. Outputs : cap[01] holds cap flags, or 0
  624. Return :
  625. ----------------------------------------------------------------------------*/
  626. static void rinFindDevCaps(unsigned int crc0, unsigned int crc1, unsigned int* cap0, unsigned int* cap1)
  627. {
  628. int index;
  629. if (cap0 == NULL || cap1 == NULL)
  630. {
  631. return;
  632. }
  633. if (crc1 != 0x00000000)
  634. {
  635. //try device-specific crclist first
  636. for (index = 0; index < (4*devTableLength); index += 4)
  637. {
  638. if (devTable[index+2] == crc1)
  639. {
  640. *cap0 = devTable[index+1];
  641. *cap1 = devTable[index+3];
  642. return;
  643. }
  644. }
  645. }
  646. //try driver-specific crclist next
  647. for (index = 0; index < (4*devTableLength); index += 4)
  648. {
  649. if (devTable[index] == crc0)
  650. {
  651. *cap0 = devTable[index+1];
  652. *cap1 = devTable[index+3];
  653. return;
  654. }
  655. }
  656. *cap0 = 0;
  657. *cap1 = 0;
  658. }
  659. typedef struct
  660. {
  661. DWORD vendor;
  662. WORD product;
  663. DWORD device;
  664. } hwDat;
  665. /*-----------------------------------------------------------------------------
  666. Name : rinEnumDirectDraw_cb
  667. Description : callback during DirectDraw device enumeration
  668. Inputs : ...
  669. Outputs :
  670. Return :
  671. ----------------------------------------------------------------------------*/
  672. static BOOL WINAPI rinEnumDirectDraw_cb(
  673. GUID FAR* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext)
  674. {
  675. LPDIRECTDRAW ddraw1;
  676. LPDIRECTDRAW4 ddraw4;
  677. LPDIRECT3D3 d3dObject;
  678. DDCAPS hal, hel;
  679. HRESULT hr;
  680. rdevice* dev;
  681. unsigned int cap0, cap1;
  682. DDDEVICEIDENTIFIER dddi;
  683. hwDat dat;
  684. gDescription = lpDriverDescription;
  685. gDriverName = lpDriverName;
  686. if (FAILED(DirectDrawCreate(lpGUID, &ddraw1, NULL)))
  687. {
  688. return D3DENUMRET_OK;
  689. }
  690. hr = ddraw1->QueryInterface(IID_IDirectDraw4, (void**)&ddraw4);
  691. if (FAILED(hr))
  692. {
  693. ddraw1->Release();
  694. return D3DENUMRET_OK;
  695. }
  696. hr = ddraw4->QueryInterface(IID_IDirect3D3, (void**)&d3dObject);
  697. if (FAILED(hr))
  698. {
  699. ddraw4->Release();
  700. ddraw1->Release();
  701. return D3DENUMRET_OK;
  702. }
  703. //query caps for fullscreen-only-ness
  704. ZeroMemory(&hal, sizeof(DDCAPS));
  705. ZeroMemory(&hel, sizeof(DDCAPS));
  706. hal.dwSize = sizeof(DDCAPS);
  707. hel.dwSize = sizeof(DDCAPS);
  708. hr = ddraw4->GetCaps(&hal, &hel);
  709. if (FAILED(hr))
  710. {
  711. d3dObject->Release();
  712. ddraw4->Release();
  713. ddraw1->Release();
  714. return D3DENUMRET_OK;
  715. }
  716. D3Ddevs = 0;
  717. d3dObject->EnumDevices(rinEnumDirect3DDevices_cb, NULL);
  718. if (D3Ddevs == 0)
  719. {
  720. d3dObject->Release();
  721. ddraw4->Release();
  722. ddraw1->Release();
  723. return D3DENUMRET_OK;
  724. }
  725. d3dObject->Release();
  726. if (!(hal.dwCaps2 & DDCAPS2_CANRENDERWINDOWED))
  727. {
  728. //no 3dfx fullscreen devices
  729. // ddraw4->Release();
  730. // ddraw1->Release();
  731. bFullscreenDevice = true;
  732. // return D3DENUMRET_OK;
  733. }
  734. memset(&dat, 0, sizeof(hwDat));
  735. if (FAILED(ddraw4->GetDeviceIdentifier(&dddi, 0)))
  736. {
  737. ddraw4->Release();
  738. ddraw1->Release();
  739. return D3DENUMRET_OK;
  740. }
  741. dat.vendor = dddi.dwVendorId;
  742. dat.product = 4;//HIWORD(dddi.liDriverVersion.HighPart);
  743. dat.device = dddi.dwDeviceId;
  744. dev = (rdevice*)memAlloc(sizeof(rdevice));
  745. dev->type = RIN_TYPE_DIRECT3D;
  746. rinFindDevCaps(crc32Compute((void*)&_caps, sizeof(D3DDEVICEDESC)),
  747. crc32Compute((void*)&dat, sizeof(hwDat)),
  748. &cap0, &cap1);
  749. if (mainOutputCRC)
  750. {
  751. rinOutputCRC(dddi.szDescription,
  752. dddi.szDriver,
  753. crc32Compute((void*)&dat, sizeof(hwDat)));
  754. }
  755. dev->devcaps = cap0;
  756. dev->devcaps2 = cap1;
  757. if (gDevcaps == 0xFFFFFFFF)
  758. {
  759. //only update global devcaps for primary
  760. gDevcaps = dev->devcaps;
  761. gDevcaps2 = dev->devcaps2;
  762. }
  763. strncpy(dev->data, lpDriverName, 63);
  764. strncpy(dev->name, lpDriverDescription, 63);
  765. dev->data[63] = '\0';
  766. dev->name[63] = '\0';
  767. rinRemoveDriverFromName(dev->name);
  768. if (lpGUID == NULL)
  769. {
  770. dev->data[0] = '\0';
  771. }
  772. dev->modes = NULL;
  773. ddraw4->EnumDisplayModes(0, NULL, (LPVOID)dev, rinEnumDisplayModes_cb);
  774. ddraw4->Release();
  775. ddraw1->Release();
  776. if (!(dev->devcaps & DEVSTAT_NOD3D_9X))
  777. {
  778. if (gl95)
  779. {
  780. if (dev->devcaps2 & DEVSTAT2_NOD3D_95)
  781. {
  782. return D3DENUMRET_OK;
  783. }
  784. }
  785. //only add device if Direct3D allowed for it
  786. rinAddDevice(dev);
  787. rinSortModes(dev);
  788. numD3Ddevs++;
  789. D3Ddevs++;
  790. }
  791. return D3DENUMRET_OK;
  792. }
  793. /*-----------------------------------------------------------------------------
  794. Name : rinEnumerateDirect3D
  795. Description : enumerate available Direct3D devices and populate the device list
  796. Inputs :
  797. Outputs : rDeviceList is added to, if any compatible devices exist
  798. Return : number of D3D devices found
  799. ----------------------------------------------------------------------------*/
  800. int rinEnumerateDirect3D(void)
  801. {
  802. numD3Ddevs = 0;
  803. HRESULT hr = DirectDrawEnumerate(rinEnumDirectDraw_cb, NULL);
  804. if (FAILED(hr))
  805. {
  806. return 0;
  807. }
  808. return numD3Ddevs;
  809. }
  810. /*-----------------------------------------------------------------------------
  811. Name : rinEnumeratePrimary
  812. Description : enumerate available display modes on the primary display
  813. Inputs : dev - the device whose modes are to be filled
  814. Outputs :
  815. Return : true or false (could or couldn't enumerate)
  816. ----------------------------------------------------------------------------*/
  817. bool rinEnumeratePrimary(rdevice* dev)
  818. {
  819. HRESULT hr = DirectDrawEnumerate(rinEnumPrimary_cb, dev);
  820. if (FAILED(hr))
  821. {
  822. return false;
  823. }
  824. if (dev == NULL)
  825. {
  826. return false;
  827. }
  828. return (dev->modes == NULL) ? false : true;
  829. }
  830. /*-----------------------------------------------------------------------------
  831. Name : rinEnumerate3Dfx
  832. Description : enumerate available display modes on possible 3Dfx display
  833. Inputs : dev - the device whose modes are to be filled
  834. Outputs :
  835. Return : true or false (could or couldn't enumerate)
  836. ----------------------------------------------------------------------------*/
  837. bool rinEnumerate3Dfx(rdevice* dev)
  838. {
  839. HRESULT hr = DirectDrawEnumerate(rinEnum3Dfx_cb, dev);
  840. if (FAILED(hr))
  841. {
  842. return false;
  843. }
  844. if (dev == NULL)
  845. {
  846. return false;
  847. }
  848. return (dev->modes == NULL) ? false : true;
  849. }
  850. /*-----------------------------------------------------------------------------
  851. Name : rinMaxWidth
  852. Description : return max width from all modes of all devices
  853. Inputs :
  854. Outputs :
  855. Return : max available width, or 9999 if no devices available
  856. ----------------------------------------------------------------------------*/
  857. int rinMaxWidth(void)
  858. {
  859. rdevice* cdev;
  860. rmode* cmode;
  861. int maxWidth;
  862. if (nDevices == 0)
  863. {
  864. return 9999;
  865. }
  866. cdev = rDeviceList;
  867. maxWidth = 0;
  868. while (cdev != NULL)
  869. {
  870. cmode = cdev->modes;
  871. while (cmode != NULL)
  872. {
  873. if (cmode->width > maxWidth)
  874. {
  875. maxWidth = cmode->width;
  876. }
  877. cmode = cmode->next;
  878. }
  879. cdev = cdev->next;
  880. }
  881. return (maxWidth == 0) ? 9999 : maxWidth;
  882. }
  883. /*-----------------------------------------------------------------------------
  884. Name : rinEnumerateDevices
  885. Description : populate the device list by enumerating available renderers
  886. Inputs :
  887. Outputs : rDeviceList is filled
  888. Return :
  889. ----------------------------------------------------------------------------*/
  890. int rinEnumerateDevices(void)
  891. {
  892. rdevice* dev;
  893. rdevice* gldev;
  894. rdevice primaryDev;
  895. bool primaryVal;
  896. int voodoo, maxWidth;
  897. if (mainOutputCRC)
  898. {
  899. rinResetCRCLog();
  900. }
  901. rDeviceList = NULL;
  902. nDevices = 0;
  903. gDevcaps = 0xFFFFFFFF;
  904. gDevcaps2 = 0x00000000;
  905. bFullscreenDevice = false;
  906. //add Direct3D devices
  907. nDevices += rinEnumerateDirect3D();
  908. //add OpenGL device
  909. dev = (rdevice*)memAlloc(sizeof(rdevice));
  910. if (nDevices == 1)
  911. {
  912. dev->devcaps = rDeviceList->devcaps;
  913. dev->devcaps2 = rDeviceList->devcaps2;
  914. }
  915. else if (nDevices == 2)
  916. {
  917. dev->devcaps = rDeviceList->next->devcaps;
  918. dev->devcaps2 = rDeviceList->next->devcaps2;
  919. }
  920. else if (gDevcaps != 0xFFFFFFFF)
  921. {
  922. dev->devcaps = gDevcaps;
  923. dev->devcaps2 = gDevcaps2;
  924. }
  925. else
  926. {
  927. dev->devcaps = gDevcaps = 0;
  928. dev->devcaps2 = gDevcaps2 = 0;
  929. }
  930. if (dev->devcaps & DEVSTAT_NO_DDRAWSW)
  931. {
  932. mainSoftwareDirectDraw = FALSE;
  933. }
  934. dev->type = RIN_TYPE_OPENGL;
  935. dev->data[0] = '\0';
  936. if (strCurLanguage == 1)
  937. {
  938. strncpy(dev->name, "OpenGL Standard", 63);
  939. }
  940. else if (strCurLanguage == 2)
  941. {
  942. strncpy(dev->name, "Standard-OpenGL", 63);
  943. }
  944. if (strCurLanguage == 3)
  945. {
  946. strncpy(dev->name, "OpenGL predeterminado", 63);
  947. }
  948. else if (strCurLanguage == 4)
  949. {
  950. strncpy(dev->name, "OpenGL di Default", 63);
  951. }
  952. else
  953. {
  954. strncpy(dev->name, "Default OpenGL", 63);
  955. }
  956. dev->modes = NULL;
  957. //try good old DirectDraw <= 3 enumeration
  958. memset(&primaryDev, 0, sizeof(rdevice));
  959. primaryVal = rinEnumeratePrimary(&primaryDev);
  960. if (primaryVal)
  961. {
  962. rinCopyModes(dev, &primaryDev);
  963. }
  964. else
  965. {
  966. //assume these are supported
  967. rinAddMode(dev, 640, 480, 16);
  968. rinAddMode(dev, 800, 600, 16);
  969. rinAddMode(dev, 1024, 768, 16);
  970. }
  971. rinSortModes(dev);
  972. gldev = dev;
  973. nDevices++;
  974. //add possible 3dfx OpenGL device
  975. voodoo = SST_VOODOO2; //sane default if sstHardwareExists doesn't get called
  976. if (!(gDevcaps & DEVSTAT_NO_3DFXGL) &&
  977. (bFullscreenDevice || sstHardwareExists(&voodoo)))
  978. {
  979. rdevice* odev = dev;
  980. dev = (rdevice*)memAlloc(sizeof(rdevice));
  981. dev->devcaps = 0;
  982. dev->type = RIN_TYPE_OPENGL;
  983. dev->data[0] = '\0';
  984. dev->modes = NULL;
  985. (void)rinEnumerate3Dfx(dev);
  986. strncpy(dev->name, "3dfx OpenGL", 63);
  987. if (dev->modes == NULL)
  988. {
  989. switch (voodoo)
  990. {
  991. case SST_VOODOO:
  992. maxWidth = 800;
  993. break;
  994. case SST_VOODOO2:
  995. maxWidth = 1024;
  996. break;
  997. default:
  998. maxWidth = 0;
  999. }
  1000. rinCopyModesSelectively(dev, odev, 16, maxWidth);
  1001. }
  1002. rinAddDevice(dev);
  1003. rinSortModes(dev);
  1004. nDevices++;
  1005. }
  1006. if (!(gDevcaps & DEVSTAT_NOGL_9X))
  1007. {
  1008. if (gl95)
  1009. {
  1010. if (!(gDevcaps2 & DEVSTAT2_NOGL_95))
  1011. {
  1012. rinAddDevice(gldev);
  1013. }
  1014. }
  1015. else
  1016. {
  1017. rinAddDevice(gldev);
  1018. }
  1019. }
  1020. //add software renderer, an explicitly known device
  1021. dev = (rdevice*)memAlloc(sizeof(rdevice));
  1022. dev->devcaps = 0;
  1023. dev->type = RIN_TYPE_SOFTWARE;
  1024. dev->data[0] = '\0';
  1025. strncpy(dev->name, "Software", 63);
  1026. dev->modes = NULL;
  1027. if (primaryVal)
  1028. {
  1029. if (gDevcaps & DEVSTAT_DISABLE_SW)
  1030. {
  1031. primaryDev.devcaps = gDevcaps;
  1032. rinSortModes(&primaryDev);
  1033. }
  1034. rinCopyModesSelectively(dev, &primaryDev, 16, 1600);
  1035. }
  1036. else
  1037. {
  1038. maxWidth = rinMaxWidth();
  1039. rinAddMode(dev, 640, 480, 16);
  1040. rinAddMode(dev, 800, 600, 16);
  1041. rinAddMode(dev, 1024, 768, 16);
  1042. if (maxWidth >= 1280)
  1043. {
  1044. rinAddMode(dev, 1280, 1024, 16);
  1045. }
  1046. if (maxWidth >= 1600)
  1047. {
  1048. rinAddMode(dev, 1600, 1200, 16);
  1049. }
  1050. }
  1051. rinSortModes(dev);
  1052. rinAddDevice(dev);
  1053. nDevices++;
  1054. if (mainOutputCRC)
  1055. {
  1056. rinCloseCRCLog();
  1057. }
  1058. //success
  1059. return 1;
  1060. }