ramfile.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Command & Conquer *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/ramfile.cpp $*
  25. * *
  26. * $Author:: Ian_l $*
  27. * *
  28. * $Modtime:: 10/31/01 2:36p $*
  29. * *
  30. * $Revision:: 2 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * RAMFileClass::Close -- This will 'close' the ram file. *
  35. * RAMFileClass::Create -- Effectively clears the buffer of data. *
  36. * RAMFileClass::Delete -- Effectively clears the buffer of data. *
  37. * RAMFileClass::Is_Available -- Determines if the "file" is available. *
  38. * RAMFileClass::Is_Open -- Is the file open? *
  39. * RAMFileClass::Open -- Opens a RAM based file for read or write. *
  40. * RAMFileClass::Open -- Opens the RAM based file. *
  41. * RAMFileClass::RAMFileClass -- Construct a RAM buffer based "file" object. *
  42. * RAMFileClass::Read -- Read data from the file. *
  43. * RAMFileClass::Seek -- Controls the ram file virtual read position. *
  44. * RAMFileClass::Size -- Returns with the size of the ram file. *
  45. * RAMFileClass::Write -- Copies data to the ram file. *
  46. * RAMFileClass::~RAMFileClass -- Destructor for the RAM file class. *
  47. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  48. #include "always.h"
  49. #include "ramfile.h"
  50. #include <string.h>
  51. /***********************************************************************************************
  52. * RAMFileClass::RAMFileClass -- Construct a RAM buffer based "file" object. *
  53. * *
  54. * This routine will construct a "file" object that actually is just a front end processor *
  55. * for a buffer. Access to the buffer will appear as if it was accessing a file. This *
  56. * is different from the caching ability of the buffered file class in that this file *
  57. * class has no real file counterpart. Typical use of this is for algorithms that were *
  58. * originally designed for file processing, but are now desired to work with a buffer. *
  59. * *
  60. * INPUT: buffer -- Pointer to the buffer to use for this file. The buffer will already *
  61. * contain data if the file is opened for READ. It will be considered *
  62. * a scratch buffer if opened for WRITE. If the buffer pointer is NULL *
  63. * but the length parameter is not, then a buffer will be allocated *
  64. * of the specified length. This case is only useful for opening the *
  65. * file for WRITE. *
  66. * *
  67. * length -- The length of the buffer submitted to this routine. *
  68. * *
  69. * OUTPUT: none *
  70. * *
  71. * WARNINGS: none *
  72. * *
  73. * HISTORY: *
  74. * 07/03/1996 JLB : Created. *
  75. *=============================================================================================*/
  76. RAMFileClass::RAMFileClass(void * buffer, int len) :
  77. Buffer((char *)buffer),
  78. MaxLength(len),
  79. Length(len),
  80. Offset(0),
  81. Access(READ),
  82. IsOpen(false),
  83. IsAllocated(false)
  84. {
  85. if (buffer == NULL && len > 0) {
  86. Buffer = new char[len];
  87. IsAllocated = true;
  88. }
  89. }
  90. /***********************************************************************************************
  91. * RAMFileClass::~RAMFileClass -- Destructor for the RAM file class. *
  92. * *
  93. * The destructor will deallocate any buffer that it allocated. Otherwise it does nothing. *
  94. * *
  95. * INPUT: none *
  96. * *
  97. * OUTPUT: none *
  98. * *
  99. * WARNINGS: none *
  100. * *
  101. * HISTORY: *
  102. * 07/03/1996 JLB : Created. *
  103. *=============================================================================================*/
  104. RAMFileClass::~RAMFileClass(void)
  105. {
  106. Close();
  107. if (IsAllocated) {
  108. delete [] Buffer;
  109. Buffer = NULL;
  110. IsAllocated = false;
  111. }
  112. }
  113. /***********************************************************************************************
  114. * RAMFileClass::Create -- Effectively clears the buffer of data. *
  115. * *
  116. * This routine "clears" the buffer of data. It only makes the buffer appear empty by *
  117. * resetting the internal length to zero. *
  118. * *
  119. * INPUT: none *
  120. * *
  121. * OUTPUT: Was the file reset in this fashion? *
  122. * *
  123. * WARNINGS: If the file was open, then resetting by this routine is not allowed. *
  124. * *
  125. * HISTORY: *
  126. * 07/03/1996 JLB : Created. *
  127. *=============================================================================================*/
  128. int RAMFileClass::Create(void)
  129. {
  130. if (!Is_Open()) {
  131. Length = 0;
  132. return(true);
  133. }
  134. return(false);
  135. }
  136. /***********************************************************************************************
  137. * RAMFileClass::Delete -- Effectively clears the buffer of data. *
  138. * *
  139. * This routine "clears" the buffer of data. It only makes the buffer appear empty by *
  140. * resetting the internal length to zero. *
  141. * *
  142. * INPUT: none *
  143. * *
  144. * OUTPUT: Was the file reset in this fashion? *
  145. * *
  146. * WARNINGS: If the file was open, then resetting by this routine is not allowed. *
  147. * *
  148. * HISTORY: *
  149. * 07/03/1996 JLB : Created. *
  150. *=============================================================================================*/
  151. int RAMFileClass::Delete(void)
  152. {
  153. if (!Is_Open()) {
  154. Length = 0;
  155. return(true);
  156. }
  157. return(false);
  158. }
  159. /***********************************************************************************************
  160. * RAMFileClass::Is_Available -- Determines if the "file" is available. *
  161. * *
  162. * RAM files are always available. *
  163. * *
  164. * INPUT: none *
  165. * *
  166. * OUTPUT: TRUE *
  167. * *
  168. * WARNINGS: none *
  169. * *
  170. * HISTORY: *
  171. * 07/03/1996 JLB : Created. *
  172. *=============================================================================================*/
  173. bool RAMFileClass::Is_Available(int )
  174. {
  175. return(true);
  176. }
  177. /***********************************************************************************************
  178. * RAMFileClass::Is_Open -- Is the file open? *
  179. * *
  180. * This answers the question whether the file is open or not. *
  181. * *
  182. * INPUT: none *
  183. * *
  184. * OUTPUT: bool; Is the file open? *
  185. * *
  186. * WARNINGS: none *
  187. * *
  188. * HISTORY: *
  189. * 07/03/1996 JLB : Created. *
  190. *=============================================================================================*/
  191. bool RAMFileClass::Is_Open(void) const
  192. {
  193. return(IsOpen);
  194. }
  195. /***********************************************************************************************
  196. * RAMFileClass::Open -- Opens a RAM based file for read or write. *
  197. * *
  198. * This routine will open the ram file. The name is meaningless so that parameter is *
  199. * ignored. If the access mode is for write, then the pseudo-file can be written until the *
  200. * buffer is full. If the file is opened for read, then the buffer is presumed to be full *
  201. * of the data to be read. *
  202. * *
  203. * INPUT: name -- ignored. *
  204. * *
  205. * access-- The access method to use for the data buffer -- either READ or WRITE. *
  206. * *
  207. * OUTPUT: bool; Was the open successful? *
  208. * *
  209. * WARNINGS: none *
  210. * *
  211. * HISTORY: *
  212. * 07/03/1996 JLB : Created. *
  213. *=============================================================================================*/
  214. int RAMFileClass::Open(char const *, int access)
  215. {
  216. return(Open(access));
  217. }
  218. /***********************************************************************************************
  219. * RAMFileClass::Open -- Opens the RAM based file. *
  220. * *
  221. * This will open the ram based file for read or write. If the file is opened for write, *
  222. * the the 'file' can be written up to the limit of the buffer's size. If the file is *
  223. * opened for read, then the buffer is presumed to hold the data to be read. *
  224. * *
  225. * INPUT: *
  226. * *
  227. * OUTPUT: *
  228. * *
  229. * WARNINGS: *
  230. * *
  231. * HISTORY: *
  232. * 07/03/1996 JLB : Created. *
  233. *=============================================================================================*/
  234. int RAMFileClass::Open(int access)
  235. {
  236. if (Buffer == NULL || Is_Open()) {
  237. return(false);
  238. }
  239. Offset = 0;
  240. Access = access;
  241. IsOpen = true;
  242. switch (access) {
  243. default:
  244. case READ:
  245. break;
  246. case WRITE:
  247. Length = 0;
  248. break;
  249. case READ|WRITE:
  250. break;
  251. }
  252. return(Is_Open());
  253. }
  254. /***********************************************************************************************
  255. * RAMFileClass::Read -- Read data from the file. *
  256. * *
  257. * Use this routine just like a normal file read. It will copy the bytes from the ram *
  258. * buffer to the destination specified. When the ram buffer is exhausted, less bytes than *
  259. * requested will be read. *
  260. * *
  261. * INPUT: buffer -- Pointer to the buffer to store the data to. *
  262. * *
  263. * size -- The number of bytes to 'read' into the specified buffer. *
  264. * *
  265. * OUTPUT: Returns with the number of bytes copied to the destination buffer. If the number *
  266. * of bytes returned is less than requested, then this indicates that the source *
  267. * buffer is exhausted. *
  268. * *
  269. * WARNINGS: The read function only applies to ram 'files' opened for read access. *
  270. * *
  271. * HISTORY: *
  272. * 07/03/1996 JLB : Created. *
  273. *=============================================================================================*/
  274. int RAMFileClass::Read(void * buffer, int size)
  275. {
  276. if (Buffer == NULL || buffer == NULL || size == 0) {
  277. return(0);
  278. }
  279. bool hasopened = false;
  280. if (!Is_Open()) {
  281. Open(READ);
  282. hasopened = true;
  283. } else {
  284. if ((Access & READ) == 0) {
  285. return(0);
  286. }
  287. }
  288. int tocopy = (size < (Length-Offset)) ? size : (Length-Offset);
  289. memmove(buffer, &Buffer[Offset], tocopy);
  290. Offset += tocopy;
  291. if (hasopened) {
  292. Close();
  293. }
  294. return(tocopy);
  295. }
  296. /***********************************************************************************************
  297. * RAMFileClass::Seek -- Controls the ram file virtual read position. *
  298. * *
  299. * This routine will move the read/write position of the ram file to the location specified *
  300. * by the offset and direction parameters. It functions similarly to the regular file *
  301. * seek method. *
  302. * *
  303. * INPUT: pos -- The signed offset from the home position specified by the "dir" *
  304. * parameter. *
  305. * *
  306. * dir -- The home position to base the position offset on. This will either be *
  307. * the start of the file, the end of the file, or the current read/write *
  308. * position. *
  309. * *
  310. * OUTPUT: Returns with the new file position. *
  311. * *
  312. * WARNINGS: none *
  313. * *
  314. * HISTORY: *
  315. * 07/03/1996 JLB : Created. *
  316. *=============================================================================================*/
  317. int RAMFileClass::Seek(int pos, int dir)
  318. {
  319. if (Buffer == NULL || !Is_Open()) {
  320. return(Offset);
  321. }
  322. int maxoffset = Length;
  323. if ((Access & WRITE) != 0) {
  324. maxoffset = MaxLength;
  325. }
  326. switch (dir) {
  327. case SEEK_CUR:
  328. Offset += pos;
  329. break;
  330. case SEEK_SET:
  331. Offset = 0 + pos;
  332. break;
  333. case SEEK_END:
  334. Offset = maxoffset + pos;
  335. break;
  336. }
  337. if (Offset < 0) Offset = 0;
  338. if (Offset > maxoffset) Offset = maxoffset;
  339. if (Offset > Length) {
  340. Length = Offset;
  341. }
  342. return(Offset);
  343. }
  344. /***********************************************************************************************
  345. * RAMFileClass::Size -- Returns with the size of the ram file. *
  346. * *
  347. * This will return the size of the 'real' data in the ram file. The real data is either *
  348. * the entire buffer, if opened for READ, or just the written data if opened for WRITE. *
  349. * *
  350. * INPUT: none *
  351. * *
  352. * OUTPUT: Returns with the number of bytes that the ram file system considers to be valid *
  353. * data of the 'file'. *
  354. * *
  355. * WARNINGS: none *
  356. * *
  357. * HISTORY: *
  358. * 07/03/1996 JLB : Created. *
  359. *=============================================================================================*/
  360. int RAMFileClass::Size(void)
  361. {
  362. return(Length);
  363. }
  364. /***********************************************************************************************
  365. * RAMFileClass::Write -- Copies data to the ram file. *
  366. * *
  367. * This function similarly to the regular write operation supported for files. It copies *
  368. * the data specified to the current write position in the ram file. *
  369. * *
  370. * INPUT: buffer -- Pointer to the data to be written. *
  371. * *
  372. * size -- The number of bytes to write to the file. *
  373. * *
  374. * OUTPUT: Returns with the actual number of bytes written. This will be less than requested *
  375. * if the buffer is exhausted of space prematurely. *
  376. * *
  377. * WARNINGS: none *
  378. * *
  379. * HISTORY: *
  380. * 07/03/1996 JLB : Created. *
  381. *=============================================================================================*/
  382. int RAMFileClass::Write(void const * buffer, int size)
  383. {
  384. if (Buffer == NULL || buffer == NULL || size == 0) {
  385. return(0);
  386. }
  387. bool hasopened = false;
  388. if (!Is_Open()) {
  389. Open(WRITE);
  390. hasopened = true;
  391. } else {
  392. if ((Access & WRITE) == 0) {
  393. return(0);
  394. }
  395. }
  396. int maxwrite = MaxLength - Offset;
  397. int towrite = (size < maxwrite) ? size : maxwrite;
  398. memmove(&Buffer[Offset], buffer, towrite);
  399. Offset += towrite;
  400. if (Offset > Length) {
  401. Length = Offset;
  402. }
  403. if (hasopened) {
  404. Close();
  405. }
  406. return(towrite);
  407. }
  408. /***********************************************************************************************
  409. * RAMFileClass::Close -- This will 'close' the ram file. *
  410. * *
  411. * Closing a ram file actually does nothing but record that it is now closed. *
  412. * *
  413. * INPUT: none *
  414. * *
  415. * OUTPUT: none *
  416. * *
  417. * WARNINGS: none *
  418. * *
  419. * HISTORY: *
  420. * 07/03/1996 JLB : Created. *
  421. *=============================================================================================*/
  422. void RAMFileClass::Close(void)
  423. {
  424. IsOpen = false;
  425. }
  426. /***********************************************************************************************
  427. * RAMFileClass::Bias -- *
  428. * *
  429. * *
  430. * INPUT: none *
  431. * *
  432. * OUTPUT: none *
  433. * *
  434. * WARNINGS: none *
  435. * *
  436. * HISTORY: *
  437. * 10/31/2001 IML : Created. *
  438. *=============================================================================================*/
  439. void RAMFileClass::Bias (int start, int length)
  440. {
  441. Buffer = Buffer + start;
  442. Length = MIN (Length, start + length) - start;
  443. MaxLength = MIN (MaxLength, start + length) - start;
  444. if (Is_Open()) {
  445. Seek (0, SEEK_SET);
  446. }
  447. }