txmmgr.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. //---------------------------------------------------------------------
  2. //
  3. //
  4. // This class will manage the texture memory provided by GOS
  5. // GOS gives me a maximum of 256 256x256 pixel texture pages.
  6. // I want GOS to think I only use 256x256 textures. This class
  7. // will insure that GOS believes that completely and provided
  8. // smaller texture surfaces out of the main surface if necessary
  9. // as well as returning the necessary UVs to get to the other surface.
  10. //
  11. //---------------------------------------------------------------------------//
  12. // Copyright (C) Microsoft Corporation. All rights reserved. //
  13. //===========================================================================//
  14. #ifndef TXMMGR_H
  15. #include "txmmgr.h"
  16. #endif
  17. #ifndef TGAINFO_H
  18. #include "tgainfo.h"
  19. #endif
  20. #ifndef FILE_H
  21. #include "file.h"
  22. #endif
  23. #ifndef TIMING_H
  24. #include "timing.h"
  25. #endif
  26. #ifndef CAMERA_H
  27. #include "camera.h"
  28. #endif
  29. #ifndef LZ_H
  30. #include "lz.h"
  31. #endif
  32. #ifndef CIDENT_H
  33. #include "cident.h"
  34. #endif
  35. #ifndef PATHS_H
  36. #include "paths.h"
  37. #endif
  38. #include <gameos.hpp>
  39. #include <MLR\MLR.hpp>
  40. #include <GosFX\gosfxheaders.hpp>
  41. //---------------------------------------------------------------------------
  42. // static globals
  43. MC_TextureManager *mcTextureManager = NULL;
  44. gos_VERTEXManager *MC_TextureManager::gvManager = NULL;
  45. MemoryPtr MC_TextureManager::lzBuffer1 = NULL;
  46. MemoryPtr MC_TextureManager::lzBuffer2 = NULL;
  47. int MC_TextureManager::iBufferRefCount = 0;
  48. bool MLRVertexLimitReached = false;
  49. extern bool useFog;
  50. DWORD actualTextureSize = 0;
  51. DWORD compressedTextureSize = 0;
  52. #define MAX_SENDDOWN 10002
  53. //------------------------------------------------------
  54. // Frees up gos_VERTEX manager memory
  55. void MC_TextureManager::freeVertices (void)
  56. {
  57. if (gvManager)
  58. {
  59. gvManager->destroy();
  60. delete gvManager;
  61. gvManager = NULL;
  62. }
  63. }
  64. //------------------------------------------------------
  65. // Creates gos_VERTEX Manager and allocates RAM. Will not allocate if already done!
  66. void MC_TextureManager::startVertices (long maxVertices)
  67. {
  68. if (gvManager == NULL)
  69. {
  70. gvManager = new gos_VERTEXManager;
  71. gvManager->init(maxVertices);
  72. gvManager->reset();
  73. }
  74. }
  75. //----------------------------------------------------------------------
  76. // Class MC_TextureManager
  77. void MC_TextureManager::start (void)
  78. {
  79. init();
  80. //------------------------------------------
  81. // Create nodes from systemHeap.
  82. long nodeRAM = MC_MAXTEXTURES * sizeof(MC_TextureNode);
  83. masterTextureNodes = (MC_TextureNode *)systemHeap->Malloc(nodeRAM);
  84. gosASSERT(masterTextureNodes != NULL);
  85. for (long i=0;i<MC_MAXTEXTURES;i++)
  86. masterTextureNodes[i].init();
  87. //-------------------------------------------
  88. // Create VertexNodes from systemHeap
  89. nodeRAM = MC_MAXTEXTURES * sizeof(MC_VertexArrayNode);
  90. masterVertexNodes = (MC_VertexArrayNode *)systemHeap->Malloc(nodeRAM);
  91. gosASSERT(masterVertexNodes != NULL);
  92. memset(masterVertexNodes,0,nodeRAM);
  93. textureCacheHeap = new UserHeap;
  94. textureCacheHeap->init(TEXTURE_CACHE_SIZE,"TXMCache");
  95. textureCacheHeap->setMallocFatals(false);
  96. textureStringHeap = new UserHeap;
  97. textureStringHeap->init(512000,"TXMString");
  98. if (!textureManagerInstrumented)
  99. {
  100. StatisticFormat( "" );
  101. StatisticFormat( "MechCommander 2 Texture Manager" );
  102. StatisticFormat( "===============================" );
  103. StatisticFormat( "" );
  104. AddStatistic("Handles Used","Handles",gos_DWORD, &(currentUsedTextures), Stat_Total);
  105. AddStatistic("Cache Misses","",gos_DWORD, &(totalCacheMisses), Stat_Total);
  106. StatisticFormat( "" );
  107. StatisticFormat( "" );
  108. textureManagerInstrumented = true;
  109. }
  110. indexArray = (WORD *)systemHeap->Malloc(sizeof(WORD) * MC_MAXFACES);
  111. for (i=0;i<MC_MAXFACES;i++)
  112. indexArray[i] = i;
  113. //Add an Empty Texture node for all untextured triangles to go down into.
  114. masterTextureNodes[0].gosTextureHandle = 0;
  115. masterTextureNodes[0].nodeName = NULL;
  116. masterTextureNodes[0].uniqueInstance = false;
  117. masterTextureNodes[0].neverFLUSH = 0x1;
  118. masterTextureNodes[0].numUsers = 0;
  119. masterTextureNodes[0].key = gos_Texture_Solid;
  120. masterTextureNodes[0].hints = 0;
  121. masterTextureNodes[0].width = 0;
  122. masterTextureNodes[0].lastUsed = -1;
  123. masterTextureNodes[0].textureData = NULL;
  124. }
  125. extern Stuff::MemoryStream *effectStream;
  126. extern MidLevelRenderer::MLRClipper * theClipper;
  127. //----------------------------------------------------------------------
  128. void MC_TextureManager::destroy (void)
  129. {
  130. if (masterTextureNodes)
  131. {
  132. //-----------------------------------------------------
  133. // Traverses list of texture nodes and frees each one.
  134. long usedCount = 0;
  135. for (long i=0;i<MC_MAXTEXTURES;i++)
  136. masterTextureNodes[i].destroy(); // Destroy for nodes whacks GOS Handle
  137. currentUsedTextures = usedCount; //Can this have been the damned bug all along!?
  138. }
  139. gos_PushCurrentHeap(MidLevelRenderer::Heap);
  140. delete MidLevelRenderer::MLRTexturePool::Instance;
  141. MidLevelRenderer::MLRTexturePool::Instance = NULL;
  142. delete theClipper;
  143. theClipper = NULL;
  144. gos_PopCurrentHeap();
  145. //------------------------------------------------------
  146. // Shutdown the GOS FX and MLR.
  147. gos_PushCurrentHeap(gosFX::Heap);
  148. delete gosFX::EffectLibrary::Instance;
  149. gosFX::EffectLibrary::Instance = NULL;
  150. delete effectStream;
  151. effectStream = NULL;
  152. delete gosFX::LightManager::Instance;
  153. gosFX::LightManager::Instance = NULL;
  154. gos_PopCurrentHeap();
  155. //------------------------------------------
  156. // free SystemHeap Memory
  157. systemHeap->Free(masterTextureNodes);
  158. masterTextureNodes = NULL;
  159. systemHeap->Free(masterVertexNodes);
  160. masterVertexNodes = NULL;
  161. delete textureCacheHeap;
  162. textureCacheHeap = NULL;
  163. delete textureStringHeap;
  164. textureStringHeap = NULL;
  165. }
  166. //----------------------------------------------------------------------
  167. MC_TextureManager::~MC_TextureManager (void)
  168. {
  169. MC_TextureManager::iBufferRefCount--;
  170. if (0 == MC_TextureManager::iBufferRefCount)
  171. {
  172. if (lzBuffer1)
  173. {
  174. gosASSERT(lzBuffer2 != NULL);
  175. if (textureCacheHeap)
  176. {
  177. textureCacheHeap->Free(lzBuffer1);
  178. textureCacheHeap->Free(lzBuffer2);
  179. }
  180. lzBuffer1 = NULL;
  181. lzBuffer2 = NULL;
  182. }
  183. }
  184. destroy();
  185. }
  186. //----------------------------------------------------------------------
  187. void MC_TextureManager::flush (bool justTextures)
  188. {
  189. if (masterTextureNodes)
  190. {
  191. //-----------------------------------------------------
  192. // Traverses list of texture nodes and frees each one.
  193. long usedCount = 0;
  194. for (long i=0;i<MC_MAXTEXTURES;i++)
  195. {
  196. if (!masterTextureNodes[i].neverFLUSH)
  197. masterTextureNodes[i].destroy(); // Destroy for nodes whacks GOS Handle
  198. }
  199. currentUsedTextures = usedCount; //Can this have been the damned bug all along!?
  200. }
  201. //If we just wanted to free up RAM, just return and let the MUNGA stuff go later.
  202. if (justTextures)
  203. return;
  204. gos_PushCurrentHeap(MidLevelRenderer::Heap);
  205. delete MidLevelRenderer::MLRTexturePool::Instance;
  206. MidLevelRenderer::MLRTexturePool::Instance = NULL;
  207. delete theClipper;
  208. theClipper = NULL;
  209. gos_PopCurrentHeap();
  210. //------------------------------------------------------
  211. // Shutdown the GOS FX and MLR.
  212. gos_PushCurrentHeap(gosFX::Heap);
  213. delete gosFX::EffectLibrary::Instance;
  214. gosFX::EffectLibrary::Instance = NULL;
  215. delete effectStream;
  216. effectStream = NULL;
  217. delete gosFX::LightManager::Instance;
  218. gosFX::LightManager::Instance = NULL;
  219. gos_PopCurrentHeap();
  220. //------------------------------------------------------
  221. //Restart MLR and the GOSFx
  222. gos_PushCurrentHeap(MidLevelRenderer::Heap);
  223. MidLevelRenderer::TGAFilePool *pool = new MidLevelRenderer::TGAFilePool("data\\tgl\\128\\");
  224. MidLevelRenderer::MLRTexturePool::Instance = new MidLevelRenderer::MLRTexturePool(pool);
  225. MidLevelRenderer::MLRSortByOrder *cameraSorter = new MidLevelRenderer::MLRSortByOrder(MidLevelRenderer::MLRTexturePool::Instance);
  226. theClipper = new MidLevelRenderer::MLRClipper(0, cameraSorter);
  227. gos_PopCurrentHeap();
  228. //------------------------------------------------------
  229. // ReStart the GOS FX.
  230. gos_PushCurrentHeap(gosFX::Heap);
  231. gosFX::EffectLibrary::Instance = new gosFX::EffectLibrary();
  232. Check_Object(gosFX::EffectLibrary::Instance);
  233. FullPathFileName effectsName;
  234. effectsName.init(effectsPath,"mc2.fx","");
  235. File effectFile;
  236. long result = effectFile.open(effectsName);
  237. if (result != NO_ERR)
  238. STOP(("Could not find MC2.fx"));
  239. long effectsSize = effectFile.fileSize();
  240. MemoryPtr effectsData = (MemoryPtr)systemHeap->Malloc(effectsSize);
  241. effectFile.read(effectsData,effectsSize);
  242. effectFile.close();
  243. effectStream = new Stuff::MemoryStream(effectsData,effectsSize);
  244. gosFX::EffectLibrary::Instance->Load(effectStream);
  245. gosFX::LightManager::Instance = new gosFX::LightManager();
  246. gos_PopCurrentHeap();
  247. systemHeap->Free(effectsData);
  248. }
  249. //----------------------------------------------------------------------
  250. void MC_TextureManager::removeTextureNode (DWORD textureNode)
  251. {
  252. if (textureNode != 0xffffffff)
  253. {
  254. //-----------------------------------------------------------
  255. masterTextureNodes[textureNode].destroy();
  256. if (masterTextureNodes[textureNode].textureData)
  257. {
  258. textureCacheHeap->Free(masterTextureNodes[textureNode].textureData);
  259. masterTextureNodes[textureNode].textureData = NULL;
  260. if (masterTextureNodes[textureNode].nodeName)
  261. {
  262. textureStringHeap->Free(masterTextureNodes[textureNode].nodeName);
  263. masterTextureNodes[textureNode].nodeName = NULL;
  264. }
  265. }
  266. }
  267. }
  268. //----------------------------------------------------------------------
  269. void MC_TextureManager::removeTexture (DWORD gosHandle)
  270. {
  271. //-----------------------------------------------------------
  272. for (long i=0;i<MC_MAXTEXTURES;i++)
  273. {
  274. if ((masterTextureNodes[i].gosTextureHandle == gosHandle))
  275. {
  276. masterTextureNodes[i].numUsers--;
  277. break;
  278. }
  279. }
  280. if ( i < MC_MAXTEXTURES && masterTextureNodes[i].numUsers == 0)
  281. {
  282. masterTextureNodes[i].destroy();
  283. if (masterTextureNodes[i].textureData)
  284. {
  285. textureCacheHeap->Free(masterTextureNodes[i].textureData);
  286. masterTextureNodes[i].textureData = NULL;
  287. if (masterTextureNodes[i].nodeName)
  288. {
  289. textureStringHeap->Free(masterTextureNodes[i].nodeName);
  290. masterTextureNodes[i].nodeName = NULL;
  291. }
  292. }
  293. }
  294. }
  295. #define cache_Threshold 150
  296. //----------------------------------------------------------------------
  297. bool MC_TextureManager::flushCache (void)
  298. {
  299. bool cacheNotFull = false;
  300. totalCacheMisses++;
  301. currentUsedTextures = 0;
  302. //Count ACTUAL number of textures being used.
  303. // ALSO can't count on turn being right. Logistics does not update unless simple Camera is up!!
  304. for (long i=0;i<MC_MAXTEXTURES;i++)
  305. {
  306. if ((masterTextureNodes[i].gosTextureHandle != CACHED_OUT_HANDLE) &&
  307. (masterTextureNodes[i].gosTextureHandle != 0xffffffff))
  308. {
  309. currentUsedTextures++;
  310. }
  311. }
  312. //If we are now below the magic number, return that the cache is NOT full.
  313. if (currentUsedTextures < MAX_MC2_GOS_TEXTURES)
  314. return true;
  315. for (i=0;i<MC_MAXTEXTURES;i++)
  316. {
  317. if ((masterTextureNodes[i].gosTextureHandle != CACHED_OUT_HANDLE) &&
  318. (masterTextureNodes[i].gosTextureHandle != 0xffffffff) &&
  319. (!masterTextureNodes[i].uniqueInstance))
  320. {
  321. if (masterTextureNodes[i].lastUsed <= (turn-cache_Threshold))
  322. {
  323. //----------------------------------------------------------------
  324. // Cache this badboy out. Textures don't change. Just Destroy!
  325. if (masterTextureNodes[i].gosTextureHandle)
  326. gos_DestroyTexture(masterTextureNodes[i].gosTextureHandle);
  327. masterTextureNodes[i].gosTextureHandle = CACHED_OUT_HANDLE;
  328. currentUsedTextures--;
  329. cacheNotFull = true;
  330. return cacheNotFull;
  331. }
  332. }
  333. }
  334. for (i=0;i<MC_MAXTEXTURES;i++)
  335. {
  336. if ((masterTextureNodes[i].gosTextureHandle != CACHED_OUT_HANDLE) &&
  337. (masterTextureNodes[i].gosTextureHandle != 0xffffffff) &&
  338. (masterTextureNodes[i].gosTextureHandle) &&
  339. (!masterTextureNodes[i].uniqueInstance))
  340. {
  341. if (masterTextureNodes[i].lastUsed <= (turn-30))
  342. {
  343. //----------------------------------------------------------------
  344. // Cache this badboy out. Textures don't change. Just Destroy!
  345. if (masterTextureNodes[i].gosTextureHandle)
  346. gos_DestroyTexture(masterTextureNodes[i].gosTextureHandle);
  347. masterTextureNodes[i].gosTextureHandle = CACHED_OUT_HANDLE;
  348. currentUsedTextures--;
  349. cacheNotFull = true;
  350. return cacheNotFull;
  351. }
  352. }
  353. }
  354. for (i=0;i<MC_MAXTEXTURES;i++)
  355. {
  356. if ((masterTextureNodes[i].gosTextureHandle != CACHED_OUT_HANDLE) &&
  357. (masterTextureNodes[i].gosTextureHandle != 0xffffffff) &&
  358. (!masterTextureNodes[i].uniqueInstance))
  359. {
  360. if (masterTextureNodes[i].lastUsed <= (turn-1))
  361. {
  362. //----------------------------------------------------------------
  363. // Cache this badboy out. Textures don't change. Just Destroy!
  364. if (masterTextureNodes[i].gosTextureHandle)
  365. gos_DestroyTexture(masterTextureNodes[i].gosTextureHandle);
  366. masterTextureNodes[i].gosTextureHandle = CACHED_OUT_HANDLE;
  367. currentUsedTextures--;
  368. cacheNotFull = true;
  369. return cacheNotFull;
  370. }
  371. }
  372. }
  373. //gosASSERT(cacheNotFull);
  374. return cacheNotFull;
  375. }
  376. //----------------------------------------------------------------------
  377. // Draws all textures with isTerrain set that are solid first,
  378. // then draws all alpha with isTerrain set.
  379. void MC_TextureManager::renderLists (void)
  380. {
  381. if (Environment.Renderer == 3)
  382. {
  383. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneZero);
  384. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeFlat);
  385. gos_SetRenderState( gos_State_MonoEnable, 1);
  386. gos_SetRenderState( gos_State_Perspective, 0);
  387. gos_SetRenderState( gos_State_Clipping, 1);
  388. gos_SetRenderState( gos_State_AlphaTest, 0);
  389. gos_SetRenderState( gos_State_Specular, 0);
  390. gos_SetRenderState( gos_State_Dither, 0);
  391. gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendDecal);
  392. gos_SetRenderState( gos_State_Filter, gos_FilterNone);
  393. gos_SetRenderState( gos_State_TextureAddress, gos_TextureClamp );
  394. gos_SetRenderState( gos_State_ZCompare, 1);
  395. gos_SetRenderState( gos_State_ZWrite, 1);
  396. }
  397. else
  398. {
  399. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneZero);
  400. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud);
  401. gos_SetRenderState( gos_State_MonoEnable, 0);
  402. gos_SetRenderState( gos_State_Perspective, 1);
  403. gos_SetRenderState( gos_State_Clipping, 1);
  404. gos_SetRenderState( gos_State_AlphaTest, 0);
  405. gos_SetRenderState( gos_State_Specular, 1);
  406. gos_SetRenderState( gos_State_Dither, 1);
  407. gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulate);
  408. gos_SetRenderState( gos_State_Filter, gos_FilterBiLinear);
  409. gos_SetRenderState( gos_State_TextureAddress, gos_TextureClamp );
  410. gos_SetRenderState( gos_State_ZCompare, 1);
  411. gos_SetRenderState( gos_State_ZWrite, 1);
  412. }
  413. DWORD fogColor = eye->fogColor;
  414. //-----------------------------------------------------
  415. // FOG time. Set Render state to FOG on!
  416. if (useFog)
  417. {
  418. gos_SetRenderState( gos_State_Fog, (int)&fogColor);
  419. }
  420. else
  421. {
  422. gos_SetRenderState( gos_State_Fog, 0);
  423. }
  424. for (long i=0;i<nextAvailableVertexNode;i++)
  425. {
  426. if ((masterVertexNodes[i].flags & MC2_DRAWSOLID) &&
  427. (masterVertexNodes[i].vertices))
  428. {
  429. if (masterVertexNodes[i].flags & MC2_ISTERRAIN)
  430. gos_SetRenderState( gos_State_TextureAddress, gos_TextureClamp );
  431. else
  432. gos_SetRenderState( gos_State_TextureAddress, gos_TextureWrap );
  433. DWORD totalVertices = masterVertexNodes[i].numVertices;
  434. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  435. {
  436. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  437. }
  438. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  439. {
  440. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  441. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  442. }
  443. else if (totalVertices > MAX_SENDDOWN)
  444. {
  445. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  446. //Must divide up vertices into batches of 10,000 each to send down.
  447. // Somewhere around 20000 to 30000 it really gets screwy!!!
  448. long currentVertices = 0;
  449. while (currentVertices < totalVertices)
  450. {
  451. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  452. long tVertices = totalVertices - currentVertices;
  453. if (tVertices > MAX_SENDDOWN)
  454. tVertices = MAX_SENDDOWN;
  455. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  456. currentVertices += tVertices;
  457. }
  458. }
  459. //Reset the list to zero length to avoid drawing more then once!
  460. //Also comes in handy if gameLogic is not called.
  461. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  462. }
  463. }
  464. if (Environment.Renderer == 3)
  465. {
  466. //Do NOT draw the water as transparent in software
  467. gos_SetRenderState( gos_State_TextureAddress, gos_TextureWrap );
  468. }
  469. else
  470. {
  471. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha);
  472. gos_SetRenderState( gos_State_AlphaTest, 1);
  473. gos_SetRenderState( gos_State_TextureAddress, gos_TextureWrap );
  474. }
  475. for (i=0;i<nextAvailableVertexNode;i++)
  476. {
  477. if ((masterVertexNodes[i].flags & MC2_ISTERRAIN) &&
  478. (masterVertexNodes[i].flags & MC2_DRAWALPHA) &&
  479. !(masterVertexNodes[i].flags & MC2_ISCRATERS) &&
  480. (masterVertexNodes[i].vertices))
  481. {
  482. DWORD totalVertices = masterVertexNodes[i].numVertices;
  483. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  484. {
  485. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  486. }
  487. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  488. {
  489. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  490. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  491. }
  492. else if (totalVertices > MAX_SENDDOWN)
  493. {
  494. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  495. //Must divide up vertices into batches of 10,000 each to send down.
  496. // Somewhere around 20000 to 30000 it really gets screwy!!!
  497. long currentVertices = 0;
  498. while (currentVertices < totalVertices)
  499. {
  500. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  501. long tVertices = totalVertices - currentVertices;
  502. if (tVertices > MAX_SENDDOWN)
  503. tVertices = MAX_SENDDOWN;
  504. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  505. currentVertices += tVertices;
  506. }
  507. }
  508. //Reset the list to zero length to avoid drawing more then once!
  509. //Also comes in handy if gameLogic is not called.
  510. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  511. }
  512. }
  513. if (Environment.Renderer == 3)
  514. {
  515. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha);
  516. gos_SetRenderState( gos_State_AlphaTest, 1);
  517. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeFlat);
  518. }
  519. gos_SetRenderState( gos_State_TextureAddress, gos_TextureClamp );
  520. gos_SetRenderState( gos_State_ZWrite, 0);
  521. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeFlat);
  522. //Draw the Craters after the detail textures on the terrain. There should never be anything here in the OLD universe.
  523. // DO NOT draw craters or footprints in software
  524. if (Environment.Renderer != 3)
  525. {
  526. for (i=0;i<nextAvailableVertexNode;i++)
  527. {
  528. if (!(masterVertexNodes[i].flags & MC2_ISTERRAIN) &&
  529. (masterVertexNodes[i].flags & MC2_DRAWALPHA) &&
  530. (masterVertexNodes[i].flags & MC2_ISCRATERS) &&
  531. (masterVertexNodes[i].vertices))
  532. {
  533. DWORD totalVertices = masterVertexNodes[i].numVertices;
  534. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  535. {
  536. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  537. }
  538. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  539. {
  540. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  541. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  542. }
  543. else if (totalVertices > MAX_SENDDOWN)
  544. {
  545. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  546. //Must divide up vertices into batches of 10,000 each to send down.
  547. // Somewhere around 20000 to 30000 it really gets screwy!!!
  548. long currentVertices = 0;
  549. while (currentVertices < totalVertices)
  550. {
  551. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  552. long tVertices = totalVertices - currentVertices;
  553. if (tVertices > MAX_SENDDOWN)
  554. tVertices = MAX_SENDDOWN;
  555. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  556. currentVertices += tVertices;
  557. }
  558. }
  559. //Reset the list to zero length to avoid drawing more then once!
  560. //Also comes in handy if gameLogic is not called.
  561. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  562. }
  563. }
  564. }
  565. if (Environment.Renderer != 3)
  566. {
  567. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud);
  568. gos_SetRenderState( gos_State_ZWrite, 1);
  569. }
  570. //Draw the Overlays after the detail textures on the terrain. There should never be anything here in the OLD universe.
  571. for (i=0;i<nextAvailableVertexNode;i++)
  572. {
  573. if ((masterVertexNodes[i].flags & MC2_ISTERRAIN) &&
  574. (masterVertexNodes[i].flags & MC2_DRAWALPHA) &&
  575. (masterVertexNodes[i].flags & MC2_ISCRATERS) &&
  576. (masterVertexNodes[i].vertices))
  577. {
  578. DWORD totalVertices = masterVertexNodes[i].numVertices;
  579. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  580. {
  581. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  582. }
  583. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  584. {
  585. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  586. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  587. }
  588. else if (totalVertices > MAX_SENDDOWN)
  589. {
  590. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  591. //Must divide up vertices into batches of 10,000 each to send down.
  592. // Somewhere around 20000 to 30000 it really gets screwy!!!
  593. long currentVertices = 0;
  594. while (currentVertices < totalVertices)
  595. {
  596. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  597. long tVertices = totalVertices - currentVertices;
  598. if (tVertices > MAX_SENDDOWN)
  599. tVertices = MAX_SENDDOWN;
  600. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  601. currentVertices += tVertices;
  602. }
  603. }
  604. //Reset the list to zero length to avoid drawing more then once!
  605. //Also comes in handy if gameLogic is not called.
  606. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  607. }
  608. }
  609. if (Environment.Renderer == 3)
  610. {
  611. gos_SetRenderState( gos_State_TextureAddress, gos_TextureWrap );
  612. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeFlat);
  613. gos_SetRenderState( gos_State_ZWrite, 1);
  614. gos_SetRenderState( gos_State_ZCompare, 2);
  615. }
  616. else
  617. {
  618. gos_SetRenderState( gos_State_TextureAddress, gos_TextureWrap );
  619. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeFlat);
  620. gos_SetRenderState( gos_State_MonoEnable, 1);
  621. gos_SetRenderState( gos_State_Perspective, 0);
  622. gos_SetRenderState( gos_State_Specular, 1);
  623. gos_SetRenderState( gos_State_ZWrite, 1);
  624. gos_SetRenderState( gos_State_ZCompare, 2);
  625. }
  626. //NEVER draw shadows in Software.
  627. if (Environment.Renderer != 3)
  628. {
  629. for (i=0;i<nextAvailableVertexNode;i++)
  630. {
  631. if ((masterVertexNodes[i].flags & MC2_ISSHADOWS) &&
  632. (masterVertexNodes[i].flags & MC2_DRAWALPHA) &&
  633. (masterVertexNodes[i].vertices))
  634. {
  635. DWORD totalVertices = masterVertexNodes[i].numVertices;
  636. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  637. {
  638. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  639. }
  640. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  641. {
  642. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  643. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  644. }
  645. else if (totalVertices > MAX_SENDDOWN)
  646. {
  647. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  648. //Must divide up vertices into batches of 10,000 each to send down.
  649. // Somewhere around 20000 to 30000 it really gets screwy!!!
  650. long currentVertices = 0;
  651. while (currentVertices < totalVertices)
  652. {
  653. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  654. long tVertices = totalVertices - currentVertices;
  655. if (tVertices > MAX_SENDDOWN)
  656. tVertices = MAX_SENDDOWN;
  657. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  658. currentVertices += tVertices;
  659. }
  660. }
  661. //Reset the list to zero length to avoid drawing more then once!
  662. //Also comes in handy if gameLogic is not called.
  663. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  664. }
  665. }
  666. }
  667. gos_SetRenderState( gos_State_ZCompare, 1);
  668. if (Environment.Renderer != 3)
  669. {
  670. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud);
  671. gos_SetRenderState( gos_State_ZWrite, 1);
  672. }
  673. for (i=0;i<nextAvailableVertexNode;i++)
  674. {
  675. if (!(masterVertexNodes[i].flags & MC2_ISTERRAIN) &&
  676. !(masterVertexNodes[i].flags & MC2_ISSHADOWS) &&
  677. !(masterVertexNodes[i].flags & MC2_ISCOMPASS) &&
  678. !(masterVertexNodes[i].flags & MC2_ISCRATERS) &&
  679. (masterVertexNodes[i].flags & MC2_DRAWALPHA) &&
  680. (masterVertexNodes[i].vertices))
  681. {
  682. DWORD totalVertices = masterVertexNodes[i].numVertices;
  683. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  684. {
  685. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  686. }
  687. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  688. {
  689. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  690. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  691. }
  692. else if (totalVertices > MAX_SENDDOWN)
  693. {
  694. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  695. //Must divide up vertices into batches of 10,000 each to send down.
  696. // Somewhere around 20000 to 30000 it really gets screwy!!!
  697. long currentVertices = 0;
  698. while (currentVertices < totalVertices)
  699. {
  700. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  701. long tVertices = totalVertices - currentVertices;
  702. if (tVertices > MAX_SENDDOWN)
  703. tVertices = MAX_SENDDOWN;
  704. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  705. currentVertices += tVertices;
  706. }
  707. }
  708. //Reset the list to zero length to avoid drawing more then once!
  709. //Also comes in handy if gameLogic is not called.
  710. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  711. }
  712. }
  713. if (Environment.Renderer == 3)
  714. {
  715. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud);
  716. gos_SetRenderState( gos_State_ZCompare, 1);
  717. gos_SetRenderState( gos_State_Fog, 0);
  718. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneOne);
  719. gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulateAlpha);
  720. gos_SetRenderState( gos_State_ZWrite, 0);
  721. gos_SetRenderState( gos_State_MonoEnable, 1);
  722. }
  723. else
  724. {
  725. gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud);
  726. gos_SetRenderState( gos_State_Perspective, 1);
  727. gos_SetRenderState( gos_State_ZCompare, 1);
  728. gos_SetRenderState( gos_State_Fog, 0);
  729. gos_SetRenderState( gos_State_Specular, 0);
  730. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneOne);
  731. gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulateAlpha);
  732. gos_SetRenderState( gos_State_ZWrite, 0);
  733. gos_SetRenderState( gos_State_MonoEnable, 0);
  734. }
  735. for (i=0;i<nextAvailableVertexNode;i++)
  736. {
  737. if ((masterVertexNodes[i].flags & MC2_ISEFFECTS) &&
  738. (masterVertexNodes[i].vertices))
  739. {
  740. DWORD totalVertices = masterVertexNodes[i].numVertices;
  741. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  742. {
  743. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  744. }
  745. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  746. {
  747. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  748. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  749. }
  750. else if (totalVertices > MAX_SENDDOWN)
  751. {
  752. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  753. //Must divide up vertices into batches of 10,000 each to send down.
  754. // Somewhere around 20000 to 30000 it really gets screwy!!!
  755. long currentVertices = 0;
  756. while (currentVertices < totalVertices)
  757. {
  758. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  759. long tVertices = totalVertices - currentVertices;
  760. if (tVertices > MAX_SENDDOWN)
  761. tVertices = MAX_SENDDOWN;
  762. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  763. currentVertices += tVertices;
  764. }
  765. }
  766. //Reset the list to zero length to avoid drawing more then once!
  767. //Also comes in handy if gameLogic is not called.
  768. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  769. }
  770. }
  771. gos_SetRenderState( gos_State_ZWrite, 1);
  772. for (i=0;i<nextAvailableVertexNode;i++)
  773. {
  774. if ((masterVertexNodes[i].flags & MC2_ISSPOTLGT) &&
  775. (masterVertexNodes[i].vertices))
  776. {
  777. DWORD totalVertices = masterVertexNodes[i].numVertices;
  778. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  779. {
  780. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  781. }
  782. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  783. {
  784. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  785. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  786. }
  787. else if (totalVertices > MAX_SENDDOWN)
  788. {
  789. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  790. //Must divide up vertices into batches of 10,000 each to send down.
  791. // Somewhere around 20000 to 30000 it really gets screwy!!!
  792. long currentVertices = 0;
  793. while (currentVertices < totalVertices)
  794. {
  795. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  796. long tVertices = totalVertices - currentVertices;
  797. if (tVertices > MAX_SENDDOWN)
  798. tVertices = MAX_SENDDOWN;
  799. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  800. currentVertices += tVertices;
  801. }
  802. }
  803. //Reset the list to zero length to avoid drawing more then once!
  804. //Also comes in handy if gameLogic is not called.
  805. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  806. }
  807. }
  808. gos_SetRenderState( gos_State_ZWrite, 0);
  809. gos_SetRenderState( gos_State_ZCompare, 0);
  810. gos_SetRenderState( gos_State_Perspective, 1);
  811. gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha);
  812. gos_SetRenderState( gos_State_AlphaTest, 1);
  813. for (i=0;i<nextAvailableVertexNode;i++)
  814. {
  815. if ((masterVertexNodes[i].flags & MC2_ISCOMPASS) &&
  816. (masterVertexNodes[i].vertices))
  817. {
  818. DWORD totalVertices = masterVertexNodes[i].numVertices;
  819. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  820. {
  821. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  822. }
  823. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  824. {
  825. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  826. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  827. }
  828. else if (totalVertices > MAX_SENDDOWN)
  829. {
  830. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  831. //Must divide up vertices into batches of 10,000 each to send down.
  832. // Somewhere around 20000 to 30000 it really gets screwy!!!
  833. long currentVertices = 0;
  834. while (currentVertices < totalVertices)
  835. {
  836. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  837. long tVertices = totalVertices - currentVertices;
  838. if (tVertices > MAX_SENDDOWN)
  839. tVertices = MAX_SENDDOWN;
  840. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  841. currentVertices += tVertices;
  842. }
  843. }
  844. //Reset the list to zero length to avoid drawing more then once!
  845. //Also comes in handy if gameLogic is not called.
  846. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  847. }
  848. }
  849. gos_SetRenderState( gos_State_Filter, gos_FilterNone);
  850. for (i=0;i<nextAvailableVertexNode;i++)
  851. {
  852. if ((masterVertexNodes[i].flags & MC2_ISHUDLMNT) &&
  853. (masterVertexNodes[i].vertices))
  854. {
  855. DWORD totalVertices = masterVertexNodes[i].numVertices;
  856. if (masterVertexNodes[i].currentVertex != (masterVertexNodes[i].vertices + masterVertexNodes[i].numVertices))
  857. {
  858. totalVertices = masterVertexNodes[i].currentVertex - masterVertexNodes[i].vertices;
  859. }
  860. if (totalVertices && (totalVertices < MAX_SENDDOWN))
  861. {
  862. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  863. gos_RenderIndexedArray( masterVertexNodes[i].vertices, totalVertices, indexArray, totalVertices );
  864. }
  865. else if (totalVertices > MAX_SENDDOWN)
  866. {
  867. gos_SetRenderState( gos_State_Texture, masterTextureNodes[masterVertexNodes[i].textureIndex].get_gosTextureHandle());
  868. //Must divide up vertices into batches of 10,000 each to send down.
  869. // Somewhere around 20000 to 30000 it really gets screwy!!!
  870. long currentVertices = 0;
  871. while (currentVertices < totalVertices)
  872. {
  873. gos_VERTEX *v = masterVertexNodes[i].vertices + currentVertices;
  874. long tVertices = totalVertices - currentVertices;
  875. if (tVertices > MAX_SENDDOWN)
  876. tVertices = MAX_SENDDOWN;
  877. gos_RenderIndexedArray(v, tVertices, indexArray, tVertices );
  878. currentVertices += tVertices;
  879. }
  880. }
  881. //Reset the list to zero length to avoid drawing more then once!
  882. //Also comes in handy if gameLogic is not called.
  883. masterVertexNodes[i].currentVertex = masterVertexNodes[i].vertices;
  884. }
  885. }
  886. //Must turn zCompare back on for FXs
  887. gos_SetRenderState( gos_State_ZCompare, 1 );
  888. }
  889. //----------------------------------------------------------------------
  890. DWORD MC_TextureManager::update (void)
  891. {
  892. DWORD numTexturesFreed = 0;
  893. currentUsedTextures = 0;
  894. for (long i=0;i<MC_MAXTEXTURES;i++)
  895. {
  896. if ((masterTextureNodes[i].gosTextureHandle != CACHED_OUT_HANDLE) &&
  897. (masterTextureNodes[i].gosTextureHandle != 0xffffffff))
  898. {
  899. if (!masterTextureNodes[i].uniqueInstance &&
  900. !(masterTextureNodes[i].neverFLUSH & 1)) //Only uncachable if BIT 1 is set, otherwise, cache 'em out!
  901. {
  902. if (masterTextureNodes[i].lastUsed <= (turn-60))
  903. {
  904. //----------------------------------------------------------------
  905. // Cache this badboy out. Textures don't change. Just Destroy!
  906. if (masterTextureNodes[i].gosTextureHandle)
  907. gos_DestroyTexture(masterTextureNodes[i].gosTextureHandle);
  908. masterTextureNodes[i].gosTextureHandle = CACHED_OUT_HANDLE;
  909. numTexturesFreed++;
  910. }
  911. }
  912. //Count ACTUAL number of textures being used.
  913. // ALSO can't count on turn being right. Logistics does not update unless simple Camera is up!!
  914. if (masterTextureNodes[i].gosTextureHandle != CACHED_OUT_HANDLE)
  915. currentUsedTextures++;
  916. }
  917. }
  918. return numTexturesFreed;
  919. }
  920. //----------------------------------------------------------------------
  921. DWORD MC_TextureManager::textureFromMemory (DWORD *data, gos_TextureFormat key, DWORD hints, DWORD width, DWORD bitDepth)
  922. {
  923. long i=0;
  924. //--------------------------------------------------------
  925. // If we called this, we KNOW the texture is NOT loaded!
  926. //
  927. // Find first empty NODE
  928. for (i=0;i<MC_MAXTEXTURES;i++)
  929. {
  930. if (masterTextureNodes[i].gosTextureHandle == 0xffffffff)
  931. {
  932. break;
  933. }
  934. }
  935. if (i == MC_MAXTEXTURES)
  936. STOP(("TOO Many textures in game. We have exceeded 4096 game handles"));
  937. //--------------------------------------------------------
  938. // New Method. Just store memory footprint of texture.
  939. // DO NOT create GOS handle until we need it.
  940. masterTextureNodes[i].gosTextureHandle = CACHED_OUT_HANDLE;
  941. masterTextureNodes[i].nodeName = NULL;
  942. masterTextureNodes[i].numUsers = 1;
  943. masterTextureNodes[i].key = key;
  944. masterTextureNodes[i].hints = hints;
  945. //------------------------------------------
  946. // Find and store the width.
  947. masterTextureNodes[i].width = width;
  948. long txmSize = width * width * bitDepth;
  949. if (!lzBuffer1)
  950. {
  951. lzBuffer1 = (MemoryPtr)textureCacheHeap->Malloc(MAX_LZ_BUFFER_SIZE);
  952. gosASSERT(lzBuffer1 != NULL);
  953. lzBuffer2 = (MemoryPtr)textureCacheHeap->Malloc(MAX_LZ_BUFFER_SIZE);
  954. gosASSERT(lzBuffer2 != NULL);
  955. }
  956. actualTextureSize += txmSize;
  957. DWORD txmCompressSize = LZCompress(lzBuffer2,(MemoryPtr)data,txmSize);
  958. compressedTextureSize += txmCompressSize;
  959. //-------------------------------------------------------
  960. // Create a block of cache memory to hold this texture.
  961. if (!masterTextureNodes[i].textureData )
  962. masterTextureNodes[i].textureData = (DWORD *)textureCacheHeap->Malloc(txmCompressSize);
  963. //No More RAM. Do not display this texture anymore.
  964. if (masterTextureNodes[i].textureData == NULL)
  965. masterTextureNodes[i].gosTextureHandle = 0;
  966. else
  967. {
  968. memcpy(masterTextureNodes[i].textureData,lzBuffer2,txmCompressSize);
  969. masterTextureNodes[i].lzCompSize = txmCompressSize;
  970. }
  971. //------------------
  972. return(i);
  973. }
  974. //----------------------------------------------------------------------
  975. DWORD MC_TextureManager::textureInstanceExists (const char *textureFullPathName, gos_TextureFormat key, DWORD hints, DWORD uniqueInstance, DWORD nFlush)
  976. {
  977. long i=0;
  978. //--------------------------------------
  979. // Is this texture already Loaded?
  980. for (i=0;i<MC_MAXTEXTURES;i++)
  981. {
  982. if (masterTextureNodes[i].nodeName)
  983. {
  984. if (stricmp(masterTextureNodes[i].nodeName,textureFullPathName) == 0)
  985. {
  986. if (uniqueInstance == masterTextureNodes[i].uniqueInstance)
  987. {
  988. masterTextureNodes[i].numUsers++;
  989. return(i); //Return the texture Node Id Now.
  990. }
  991. else
  992. {
  993. //------------------------------------------------
  994. // Copy the texture from old Handle to a new one.
  995. // Return the NEW handle.
  996. //
  997. // There should be no code here!!!
  998. }
  999. }
  1000. }
  1001. }
  1002. return 0;
  1003. }
  1004. //----------------------------------------------------------------------
  1005. DWORD MC_TextureManager::loadTexture (const char *textureFullPathName, gos_TextureFormat key, DWORD hints, DWORD uniqueInstance, DWORD nFlush)
  1006. {
  1007. long i=0;
  1008. //--------------------------------------
  1009. // Is this texture already Loaded?
  1010. for (i=0;i<MC_MAXTEXTURES;i++)
  1011. {
  1012. if (masterTextureNodes[i].nodeName && (stricmp(masterTextureNodes[i].nodeName,textureFullPathName) == 0))
  1013. {
  1014. if (uniqueInstance == masterTextureNodes[i].uniqueInstance)
  1015. {
  1016. masterTextureNodes[i].numUsers++;
  1017. return(i); //Return the texture Node Id Now.
  1018. }
  1019. else
  1020. {
  1021. //------------------------------------------------
  1022. // Copy the texture from old Handle to a new one.
  1023. // Return the NEW handle.
  1024. //
  1025. // There should be no code here!!!
  1026. }
  1027. }
  1028. }
  1029. //--------------------------------------------------
  1030. // If we get here, texture has not been loaded yet.
  1031. // Load it now!
  1032. //
  1033. // Find first empty NODE
  1034. for (i=0;i<MC_MAXTEXTURES;i++)
  1035. {
  1036. if (masterTextureNodes[i].gosTextureHandle == 0xffffffff)
  1037. {
  1038. break;
  1039. }
  1040. }
  1041. if (i == MC_MAXTEXTURES)
  1042. STOP(("TOO Many textures in game. We have exceeded 4096 game handles"));
  1043. if (key == gos_Texture_Alpha && Environment.Renderer == 3)
  1044. {
  1045. key = gos_Texture_Keyed;
  1046. }
  1047. //--------------------------------------------------------
  1048. // New Method. Just store memory footprint of texture.
  1049. // DO NOT create GOS handle until we need it.
  1050. masterTextureNodes[i].gosTextureHandle = CACHED_OUT_HANDLE;
  1051. masterTextureNodes[i].nodeName = (char *)textureStringHeap->Malloc(strlen(textureFullPathName) + 1);
  1052. gosASSERT(masterTextureNodes[i].nodeName != NULL);
  1053. strcpy(masterTextureNodes[i].nodeName,textureFullPathName);
  1054. masterTextureNodes[i].numUsers = 1;
  1055. masterTextureNodes[i].key = key;
  1056. masterTextureNodes[i].hints = hints;
  1057. masterTextureNodes[i].uniqueInstance = uniqueInstance;
  1058. masterTextureNodes[i].neverFLUSH = nFlush;
  1059. //----------------------------------------------------------------------------------------------
  1060. // Store 0xf0000000 & fileSize in width so that cache knows to create new texture from memory.
  1061. // This way, we never need to know anything about the texture AND we can store PMGs
  1062. // in memory instead of TGAs which use WAY less RAM!
  1063. File textureFile;
  1064. #ifdef _DEBUG
  1065. long textureFileOpenResult =
  1066. #endif
  1067. textureFile.open(textureFullPathName);
  1068. gosASSERT(textureFileOpenResult == NO_ERR);
  1069. long txmSize = textureFile.fileSize();
  1070. if (!lzBuffer1)
  1071. {
  1072. lzBuffer1 = (MemoryPtr)textureCacheHeap->Malloc(MAX_LZ_BUFFER_SIZE);
  1073. gosASSERT(lzBuffer1 != NULL);
  1074. lzBuffer2 = (MemoryPtr)textureCacheHeap->Malloc(MAX_LZ_BUFFER_SIZE);
  1075. gosASSERT(lzBuffer2 != NULL);
  1076. }
  1077. //Try reading the RAW data out of the fastFile.
  1078. // If it succeeds, we just saved a complete compress, decompress and two memcpys!!
  1079. //
  1080. long result = textureFile.readRAW(masterTextureNodes[i].textureData,textureCacheHeap);
  1081. if (!result)
  1082. {
  1083. textureFile.read(lzBuffer1,txmSize);
  1084. textureFile.close();
  1085. actualTextureSize += txmSize;
  1086. DWORD txmCompressSize = LZCompress(lzBuffer2,lzBuffer1,txmSize);
  1087. compressedTextureSize += txmCompressSize;
  1088. masterTextureNodes[i].textureData = (DWORD *)textureCacheHeap->Malloc(txmCompressSize);
  1089. if (masterTextureNodes[i].textureData == NULL)
  1090. masterTextureNodes[i].gosTextureHandle = 0;
  1091. else
  1092. memcpy(masterTextureNodes[i].textureData,lzBuffer2,txmCompressSize);
  1093. masterTextureNodes[i].lzCompSize = txmCompressSize;
  1094. }
  1095. else
  1096. {
  1097. masterTextureNodes[i].lzCompSize = result;
  1098. }
  1099. masterTextureNodes[i].width = 0xf0000000 + txmSize;
  1100. //-------------------
  1101. return(i);
  1102. }
  1103. //----------------------------------------------------------------------
  1104. long MC_TextureManager::saveTexture (DWORD textureIndex, const char *textureFullPathName)
  1105. {
  1106. if ((MC_MAXTEXTURES <= textureIndex) || (NULL == masterTextureNodes[textureIndex].textureData))
  1107. {
  1108. return (~NO_ERR);
  1109. }
  1110. File textureFile;
  1111. long textureFileOpenResult = textureFile.create(textureFullPathName);
  1112. if (NO_ERR != textureFileOpenResult)
  1113. {
  1114. textureFile.close();
  1115. return textureFileOpenResult;
  1116. }
  1117. {
  1118. if (masterTextureNodes[textureIndex].width == 0)
  1119. {
  1120. textureFile.close();
  1121. return (~NO_ERR); //These faces have no texture!!
  1122. }
  1123. {
  1124. //------------------------------------------
  1125. // Badboys are now LZ Compressed in texture cache.
  1126. long origSize = LZDecomp(MC_TextureManager::lzBuffer2,(MemoryPtr)masterTextureNodes[textureIndex].textureData,masterTextureNodes[textureIndex].lzCompSize);
  1127. if (origSize != (masterTextureNodes[textureIndex].width & 0x0fffffff))
  1128. STOP(("Decompressed to different size from original! Txm:%s Width:%d DecompSize:%d",masterTextureNodes[textureIndex].nodeName,(masterTextureNodes[textureIndex].width & 0x0fffffff),origSize));
  1129. if (origSize >= MAX_LZ_BUFFER_SIZE)
  1130. STOP(("Texture TOO large: %s",masterTextureNodes[textureIndex].nodeName));
  1131. textureFile.write(MC_TextureManager::lzBuffer2, origSize);
  1132. }
  1133. textureFile.close();
  1134. }
  1135. return NO_ERR;
  1136. }
  1137. DWORD MC_TextureManager::copyTexture( DWORD texNodeID )
  1138. {
  1139. gosASSERT( texNodeID < MC_MAXTEXTURES );
  1140. if ( masterTextureNodes[texNodeID].gosTextureHandle != -1 )
  1141. {
  1142. masterTextureNodes[texNodeID].numUsers++;
  1143. return texNodeID;
  1144. }
  1145. else
  1146. {
  1147. STOP(( "tried to copy an invalid texture" ));
  1148. }
  1149. return -1;
  1150. }
  1151. //----------------------------------------------------------------------
  1152. // MC_TextureNode
  1153. DWORD MC_TextureNode::get_gosTextureHandle (void) //If texture is not in VidRAM, cache a texture out and cache this one in.
  1154. {
  1155. if (gosTextureHandle == 0xffffffff)
  1156. {
  1157. //Somehow this texture is bad. Probably we are using a handle which got purged between missions.
  1158. // Just send back, NO TEXTURE and we should be able to debug from there because the tri will have no texture!!
  1159. return 0x0;
  1160. }
  1161. if (gosTextureHandle != CACHED_OUT_HANDLE)
  1162. {
  1163. lastUsed = turn;
  1164. return gosTextureHandle;
  1165. }
  1166. else
  1167. {
  1168. if ((mcTextureManager->currentUsedTextures >= MAX_MC2_GOS_TEXTURES) && !mcTextureManager->flushCache())
  1169. return 0x0; //No texture!
  1170. if (width == 0)
  1171. return 0; //These faces have no texture!!
  1172. if (!textureData)
  1173. return 0x0; //No Texture. Cache is out of RAM!!
  1174. if (width > 0xf0000000)
  1175. {
  1176. //------------------------------------------
  1177. // Cache this badboy IN.
  1178. // Badboys are now LZ Compressed in texture cache.
  1179. // Uncompress, then memcpy.
  1180. long origSize = LZDecomp(MC_TextureManager::lzBuffer2,(MemoryPtr)textureData,lzCompSize);
  1181. if (origSize != (width & 0x0fffffff))
  1182. STOP(("Decompressed to different size from original! Txm:%s Width:%d DecompSize:%d",nodeName,(width & 0x0fffffff),origSize));
  1183. if (origSize >= MAX_LZ_BUFFER_SIZE)
  1184. STOP(("Texture TOO large: %s",nodeName));
  1185. gosTextureHandle = gos_NewTextureFromMemory(key,nodeName,MC_TextureManager::lzBuffer2,(width & 0x0fffffff),hints);
  1186. mcTextureManager->currentUsedTextures++;
  1187. lastUsed = turn;
  1188. return gosTextureHandle;
  1189. }
  1190. else
  1191. {
  1192. gosTextureHandle = gos_NewEmptyTexture(key,nodeName,width,hints);
  1193. mcTextureManager->currentUsedTextures++;
  1194. //------------------------------------------
  1195. // Cache this badboy IN.
  1196. TEXTUREPTR pTextureData;
  1197. gos_LockTexture(gosTextureHandle, 0, 0, &pTextureData);
  1198. //-------------------------------------------------------
  1199. // Create a block of cache memory to hold this texture.
  1200. DWORD txmSize = pTextureData.Height * pTextureData.Height * sizeof(DWORD);
  1201. gosASSERT(textureData);
  1202. LZDecomp(MC_TextureManager::lzBuffer2,(MemoryPtr)textureData,lzCompSize);
  1203. memcpy(pTextureData.pTexture,MC_TextureManager::lzBuffer2,txmSize);
  1204. //------------------------
  1205. // Unlock the texture
  1206. gos_UnLockTexture(gosTextureHandle);
  1207. lastUsed = turn;
  1208. return gosTextureHandle;
  1209. }
  1210. }
  1211. }
  1212. //----------------------------------------------------------------------
  1213. void MC_TextureNode::destroy (void)
  1214. {
  1215. if ((gosTextureHandle != CACHED_OUT_HANDLE) && (gosTextureHandle != 0xffffffff) && (gosTextureHandle != 0x0))
  1216. {
  1217. gos_DestroyTexture(gosTextureHandle);
  1218. }
  1219. mcTextureManager->textureStringHeap->Free(nodeName);
  1220. mcTextureManager->textureCacheHeap->Free(textureData);
  1221. init();
  1222. }
  1223. //----------------------------------------------------------------------