Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
9.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: .360 file creation of miscellaneous resource and data files
  4. //
  5. //=====================================================================================//
  6. #include "MakeGameData.h"
  7. #include "captioncompiler.h"
  8. //-----------------------------------------------------------------------------
  9. // Purpose: Generate .360 compiled caption files
  10. //-----------------------------------------------------------------------------
  11. bool CreateTargetFile_CCDAT( const char *pSourceName, const char *pTargetName, bool bWriteToZip )
  12. {
  13. CUtlBuffer targetBuffer;
  14. bool bOk = false;
  15. if ( !scriptlib->ReadFileToBuffer( pSourceName, targetBuffer ) )
  16. {
  17. return false;
  18. }
  19. if ( SwapClosecaptionFile( targetBuffer.Base() ) )
  20. {
  21. bOk = WriteBufferToFile( pTargetName, targetBuffer, bWriteToZip, g_WriteModeForConversions );
  22. }
  23. return bOk;
  24. }
  25. static bool ReslistLessFunc( CUtlString const &pLHS, CUtlString const &pRHS )
  26. {
  27. return CaselessStringLessThan( pLHS.Get(), pRHS.Get() );
  28. }
  29. //-----------------------------------------------------------------------------
  30. // Find or Add, prevents duplicates. Returns TRUE if found.
  31. //-----------------------------------------------------------------------------
  32. bool FindOrAddFileToResourceList( const char *pFilename, CUtlRBTree< CUtlString, int > *pTree, bool bAdd = true )
  33. {
  34. char szOutName[MAX_PATH];
  35. char *pOutName;
  36. V_strncpy( szOutName, pFilename, sizeof( szOutName ) );
  37. V_FixSlashes( szOutName );
  38. V_RemoveDotSlashes( szOutName );
  39. V_strlower( szOutName );
  40. pOutName = szOutName;
  41. // strip any prefixed game name
  42. for ( int i = 0; g_GameNames[i] != NULL; i++ )
  43. {
  44. size_t len = strlen( g_GameNames[i] );
  45. if ( !V_strnicmp( pOutName, g_GameNames[i], len ) && pOutName[len] == '\\' )
  46. {
  47. // skip past game name and slash
  48. pOutName += len+1;
  49. break;
  50. }
  51. }
  52. if ( pTree->Find( pOutName ) != pTree->InvalidIndex() )
  53. {
  54. // found
  55. return true;
  56. }
  57. if ( bAdd )
  58. {
  59. pTree->Insert( pOutName );
  60. }
  61. return false;
  62. }
  63. //-----------------------------------------------------------------------------
  64. // Remove entry from dictionary, Returns TRUE if removed.
  65. //-----------------------------------------------------------------------------
  66. bool RemoveFileFromResourceList( const char *pFilename, CUtlRBTree< CUtlString, int > *pTree )
  67. {
  68. char szOutName[MAX_PATH];
  69. char *pOutName;
  70. V_strncpy( szOutName, pFilename, sizeof( szOutName ) );
  71. V_FixSlashes( szOutName );
  72. V_RemoveDotSlashes( szOutName );
  73. V_strlower( szOutName );
  74. pOutName = szOutName;
  75. // strip any prefixed game name
  76. for ( int i = 0; g_GameNames[i] != NULL; i++ )
  77. {
  78. size_t len = strlen( g_GameNames[i] );
  79. if ( !V_strnicmp( pOutName, g_GameNames[i], len ) && pOutName[len] == '\\' )
  80. {
  81. // skip past game name and slash
  82. pOutName += len+1;
  83. break;
  84. }
  85. }
  86. if ( pTree->Find( pOutName ) != pTree->InvalidIndex() )
  87. {
  88. pTree->Remove( pOutName );
  89. return true;
  90. }
  91. return false;
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Generate a tree containing files from a reslist. Returns TRUE if successful.
  95. //-----------------------------------------------------------------------------
  96. bool LoadReslist( const char *pReslistName, CUtlRBTree< CUtlString, int > *pTree )
  97. {
  98. CUtlBuffer buffer;
  99. if ( !scriptlib->ReadFileToBuffer( pReslistName, buffer, true ) )
  100. {
  101. return false;
  102. }
  103. char szBasename[MAX_PATH];
  104. V_FileBase( pReslistName, szBasename, sizeof( szBasename ) );
  105. characterset_t breakSet;
  106. CharacterSetBuild( &breakSet, "" );
  107. // parse reslist
  108. char szToken[MAX_PATH];
  109. char szBspName[MAX_PATH];
  110. szBspName[0] = '\0';
  111. for ( ;; )
  112. {
  113. int nTokenSize = buffer.ParseToken( &breakSet, szToken, sizeof( szToken ) );
  114. if ( nTokenSize <= 0 )
  115. {
  116. break;
  117. }
  118. // reslists are pc built, filenames can be sloppy
  119. V_strlower( szToken );
  120. V_FixSlashes( szToken );
  121. V_RemoveDotSlashes( szToken );
  122. // can safely cull filetypes that are ignored by queued loader at runtime
  123. bool bKeep = false;
  124. const char *pExt = V_GetFileExtension( szToken );
  125. if ( !pExt )
  126. {
  127. // unknown
  128. continue;
  129. }
  130. else if ( !V_stricmp( pExt, "vmt" ) ||
  131. !V_stricmp( pExt, "vhv" ) ||
  132. !V_stricmp( pExt, "mdl" ) ||
  133. !V_stricmp( pExt, "raw" ) ||
  134. !V_stricmp( pExt, "wav" ) )
  135. {
  136. bKeep = true;
  137. }
  138. else if ( !V_stricmp( pExt, "mp3" ) )
  139. {
  140. // change to .wav
  141. V_SetExtension( szToken, ".wav", sizeof( szToken ) );
  142. bKeep = true;
  143. }
  144. else if ( !V_stricmp( pExt, "bsp" ) )
  145. {
  146. // reslists erroneously have multiple bsps
  147. if ( !V_stristr( szToken, szBasename ) )
  148. {
  149. // wrong one, cull it
  150. continue;
  151. }
  152. else
  153. {
  154. // right one, save it
  155. strcpy( szBspName, szToken );
  156. bKeep = true;
  157. }
  158. }
  159. if ( bKeep )
  160. {
  161. FindOrAddFileToResourceList( szToken, pTree );
  162. }
  163. }
  164. if ( !szBspName[0] )
  165. {
  166. // reslist is not bsp derived, nothing more to do
  167. return true;
  168. }
  169. CUtlVector< CUtlString > bspList;
  170. bool bOK = GetDependants_BSP( szBspName, &bspList );
  171. if ( !bOK )
  172. {
  173. return false;
  174. }
  175. // add all the bsp dependants to the resource list
  176. for ( int i=0; i<bspList.Count(); i++ )
  177. {
  178. FindOrAddFileToResourceList( bspList[i].String(), pTree );
  179. }
  180. // iterate all the models in the resource list, get all their dependents
  181. CUtlVector< CUtlString > modelList;
  182. for ( int i = pTree->FirstInorder(); i != pTree->InvalidIndex(); i = pTree->NextInorder( i ) )
  183. {
  184. const char *pExt = V_GetFileExtension( pTree->Element( i ).String() );
  185. if ( !pExt || V_stricmp( pExt, "mdl" ) )
  186. {
  187. continue;
  188. }
  189. if ( !GetDependants_MDL( pTree->Element( i ).String(), &modelList ) )
  190. {
  191. return false;
  192. }
  193. }
  194. // add all the model dependents to the resource list
  195. for ( int i=0; i<modelList.Count(); i++ )
  196. {
  197. FindOrAddFileToResourceList( modelList[i].String(), pTree );
  198. }
  199. // check for optional commentary, include wav dependencies
  200. char szCommentaryName[MAX_PATH];
  201. V_ComposeFileName( g_szGamePath, szBspName, szCommentaryName, sizeof( szCommentaryName ) );
  202. V_StripExtension( szCommentaryName, szCommentaryName, sizeof( szCommentaryName ) );
  203. V_strncat( szCommentaryName, "_commentary.txt", sizeof( szCommentaryName ) );
  204. CUtlBuffer commentaryBuffer;
  205. if ( ReadFileToBuffer( szCommentaryName, commentaryBuffer, true, true ) )
  206. {
  207. // any single token may be quite large to due to text
  208. char szCommentaryToken[8192];
  209. for ( ;; )
  210. {
  211. int nTokenSize = commentaryBuffer.ParseToken( &breakSet, szCommentaryToken, sizeof( szCommentaryToken ) );
  212. if ( nTokenSize < 0 )
  213. {
  214. break;
  215. }
  216. if ( nTokenSize > 0 && !V_stricmp( szCommentaryToken, "commentaryfile" ) )
  217. {
  218. // get the commentary file
  219. nTokenSize = commentaryBuffer.ParseToken( &breakSet, szCommentaryToken, sizeof( szCommentaryToken ) );
  220. if ( nTokenSize > 0 )
  221. {
  222. // skip past sound chars
  223. char *pName = szCommentaryToken;
  224. while ( *pName && IsSoundChar( *pName ) )
  225. {
  226. pName++;
  227. }
  228. char szWavFile[MAX_PATH];
  229. V_snprintf( szWavFile, sizeof( szWavFile ), "sound/%s", pName );
  230. FindOrAddFileToResourceList( szWavFile, pTree );
  231. }
  232. }
  233. }
  234. }
  235. // check for optional blacklist
  236. char szBlacklist[MAX_PATH];
  237. V_ComposeFileName( g_szGamePath, "reslistfixes_xbox.xsc", szBlacklist, sizeof( szBlacklist ) );
  238. CUtlBuffer blacklistBuffer;
  239. if ( ReadFileToBuffer( szBlacklist, blacklistBuffer, true, true ) )
  240. {
  241. for ( ;; )
  242. {
  243. int nTokenSize = blacklistBuffer.ParseToken( &breakSet, szToken, sizeof( szToken ) );
  244. if ( nTokenSize <= 0 )
  245. {
  246. break;
  247. }
  248. bool bAdd;
  249. if ( !V_stricmp( szToken, "-" ) )
  250. {
  251. bAdd = false;
  252. }
  253. else if ( !V_stricmp( szToken, "+" ) )
  254. {
  255. bAdd = true;
  256. }
  257. else
  258. {
  259. // bad syntax, skip line
  260. Msg( "Bad Syntax, expecting '+' or '-' as first token in reslist fixup file '%s'.\n", szBlacklist );
  261. continue;
  262. }
  263. // get entry
  264. nTokenSize = blacklistBuffer.ParseToken( &breakSet, szToken, sizeof( szToken ) );
  265. if ( nTokenSize <= 0 )
  266. {
  267. break;
  268. }
  269. if ( bAdd )
  270. {
  271. FindOrAddFileToResourceList( szToken, pTree );
  272. }
  273. else
  274. {
  275. RemoveFileFromResourceList( szToken, pTree );
  276. }
  277. }
  278. }
  279. return true;
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Purpose: Generate .360 compiled reslist files
  283. // Reslist files are processed for the unique consumption of Queued Loading.
  284. //-----------------------------------------------------------------------------
  285. bool CreateTargetFile_RESLST( const char *pSourceName, const char *pTargetName, bool bWriteToZip )
  286. {
  287. bool bOK = false;
  288. // parse reslist
  289. CUtlRBTree< CUtlString, int > rbTree( 0, 0, ReslistLessFunc );
  290. if ( !LoadReslist( pSourceName, &rbTree ) )
  291. {
  292. return false;
  293. }
  294. CUtlBuffer targetBuffer( 0, 0, CUtlBuffer::TEXT_BUFFER );
  295. for ( int iIndex = rbTree.FirstInorder(); iIndex != rbTree.InvalidIndex(); iIndex = rbTree.NextInorder( iIndex ) )
  296. {
  297. targetBuffer.PutChar( '\"' );
  298. targetBuffer.PutString( rbTree[iIndex].String() );
  299. targetBuffer.PutChar( '\"' );
  300. targetBuffer.PutString( "\n" );
  301. }
  302. bOK = WriteBufferToFile( pTargetName, targetBuffer, bWriteToZip, g_WriteModeForConversions );
  303. return bOK;
  304. }