chunkio.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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. /* $Header: /Commando/Code/wwlib/chunkio.cpp 11 7/12/01 7:44p Jani_p $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Tiberian Sun / Commando / G Library *
  24. * *
  25. * $Archive:: /Commando/Code/wwlib/chunkio.cpp $*
  26. * *
  27. * $Author:: Jani_p $*
  28. * *
  29. * $Modtime:: 7/10/01 7:38p $*
  30. * *
  31. * $Revision:: 11 $*
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * ChunkSaveClass::ChunkSaveClass -- Constructor *
  36. * ChunkSaveClass::Begin_Chunk -- Begin a new chunk in the file *
  37. * ChunkSaveClass::End_Chunk -- Close a chunk, computes the size and adds to the header *
  38. * ChunkSaveClass::Begin_Micro_Chunk -- begins a new "micro-chunk" *
  39. * ChunkSaveClass::End_Micro_Chunk -- close a micro-chunk *
  40. * ChunkSaveClass::Write -- Write data into the current chunk *
  41. * ChunkSaveClass::Write -- write an IOVector2Struct *
  42. * ChunkSaveClass::Write -- write an IOVector3Struct *
  43. * ChunkSaveClass::Write -- write an IOVector4Struct *
  44. * ChunkSaveClass::Write -- write an IOQuaternionStruct *
  45. * ChunkSaveClass::Cur_Chunk_Depth -- returns the current chunk recursion depth (debugging) *
  46. * ChunkLoadClass::ChunkLoadClass -- Constructor *
  47. * ChunkLoadClass::Open_Chunk -- Open a chunk in the file, reads in the chunk header *
  48. * ChunkLoadClass::Close_Chunk -- Close a chunk, seeks to the end if needed *
  49. * ChunkLoadClass::Cur_Chunk_ID -- Returns the ID of the current chunk *
  50. * ChunkLoadClass::Cur_Chunk_Length -- Returns the current length of the current chunk *
  51. * ChunkLoadClass::Cur_Chunk_Depth -- returns the current chunk recursion depth *
  52. * ChunkLoadClass::Contains_Chunks -- Test whether the current chunk contains chunks (or dat *
  53. * ChunkLoadClass::Open_Micro_Chunk -- reads in a micro-chunk header *
  54. * ChunkLoadClass::Close_Micro_Chunk -- closes a micro-chunk *
  55. * ChunkLoadClass::Cur_Micro_Chunk_ID -- returns the ID of the current micro-chunk (asserts *
  56. * ChunkLoadClass::Cur_Micro_Chunk_Length -- returns the size of the current micro chunk *
  57. * ChunkLoadClass::Read -- Read data from the file *
  58. * ChunkLoadClass::Read -- read an IOVector2Struct *
  59. * ChunkLoadClass::Read -- read an IOVector3Struct *
  60. * ChunkLoadClass::Read -- read an IOVector4Struct *
  61. * ChunkLoadClass::Read -- read an IOQuaternionStruct *
  62. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  63. #include "chunkio.h"
  64. #include <string.h>
  65. #include <assert.h>
  66. /***********************************************************************************************
  67. * ChunkSaveClass::ChunkSaveClass -- Constructor *
  68. * *
  69. * INPUT: *
  70. * file - pointer to a FileClass object to write to *
  71. * *
  72. * OUTPUT: *
  73. * *
  74. * WARNINGS: *
  75. * *
  76. * HISTORY: *
  77. * 07/17/1997 GH : Created. *
  78. *=============================================================================================*/
  79. ChunkSaveClass::ChunkSaveClass(FileClass * file) :
  80. File(file),
  81. StackIndex(0),
  82. InMicroChunk(false),
  83. MicroChunkPosition(0)
  84. {
  85. memset(PositionStack,0,sizeof(PositionStack));
  86. memset(HeaderStack,0,sizeof(HeaderStack));
  87. memset(&MCHeader,0,sizeof(MCHeader));
  88. }
  89. /***********************************************************************************************
  90. * ChunkSaveClass::Begin_Chunk -- Begin a new chunk in the file *
  91. * *
  92. * INPUT: *
  93. * id - id of the chunk *
  94. * *
  95. * OUTPUT: *
  96. * *
  97. * WARNINGS: *
  98. * *
  99. * HISTORY: *
  100. * 07/17/1997 GH : Created. *
  101. *=============================================================================================*/
  102. bool ChunkSaveClass::Begin_Chunk(uint32 id)
  103. {
  104. ChunkHeader chunkh;
  105. int filepos;
  106. // If we have a parent chunk, set its 'Contains_Chunks' flag
  107. if (StackIndex > 0) {
  108. HeaderStack[StackIndex-1].Set_Sub_Chunk_Flag(true);
  109. }
  110. // Save the current file position and chunk header
  111. // for the call to End_Chunk.
  112. chunkh.Set_Type(id);
  113. chunkh.Set_Size(0);
  114. filepos = File->Seek(0);
  115. PositionStack[StackIndex] = filepos;
  116. HeaderStack[StackIndex] = chunkh;
  117. StackIndex++;
  118. // write a temporary chunk header (size = 0)
  119. if (File->Write(&chunkh,sizeof(chunkh)) != sizeof(chunkh)) {
  120. return false;
  121. }
  122. return true;
  123. }
  124. /***********************************************************************************************
  125. * ChunkSaveClass::End_Chunk -- Close a chunk, computes the size and adds to the header *
  126. * *
  127. * INPUT: *
  128. * *
  129. * OUTPUT: *
  130. * *
  131. * WARNINGS: *
  132. * *
  133. * HISTORY: *
  134. * 07/17/1997 GH : Created. *
  135. *=============================================================================================*/
  136. bool ChunkSaveClass::End_Chunk(void)
  137. {
  138. // If the user didn't close his micro chunks bad things are gonna happen
  139. assert(!InMicroChunk);
  140. // Save the current position
  141. int curpos = File->Seek(0);
  142. // Pop the position and chunk header off the stacks
  143. StackIndex--;
  144. int chunkpos = PositionStack[StackIndex];
  145. ChunkHeader chunkh = HeaderStack[StackIndex];
  146. // write the completed header
  147. File->Seek(chunkpos,SEEK_SET);
  148. if (File->Write(&chunkh,sizeof(chunkh)) != sizeof(chunkh)) {
  149. return false;
  150. }
  151. // Add the total bytes written to any encompasing chunk
  152. if (StackIndex != 0) {
  153. HeaderStack[StackIndex-1].Add_Size(chunkh.Get_Size() + sizeof(chunkh));
  154. }
  155. // Go back to the end of the file
  156. File->Seek(curpos,SEEK_SET);
  157. return true;
  158. }
  159. /***********************************************************************************************
  160. * ChunkSaveClass::Begin_Micro_Chunk -- begins a new "micro-chunk" *
  161. * *
  162. * Micro chunks are used to wrap individual variables. They aren't hierarchical so if you *
  163. * attempt to open a micro chunk while already in one, an assert will occur. *
  164. * *
  165. * INPUT: *
  166. * id - 8bit id *
  167. * *
  168. * OUTPUT: *
  169. * *
  170. * WARNINGS: *
  171. * id is asserted to be between 0 and 255 *
  172. * cannot nest micro chunks so it asserts that you are currently not in another micro-chunk *
  173. * *
  174. * HISTORY: *
  175. * 9/3/99 GTH : Created. *
  176. *=============================================================================================*/
  177. bool ChunkSaveClass::Begin_Micro_Chunk(uint32 id)
  178. {
  179. assert(id < 256);
  180. assert(!InMicroChunk);
  181. // Save the current file position and chunk header
  182. // for the call to End_Micro_Chunk.
  183. MCHeader.Set_Type(id);
  184. MCHeader.Set_Size(0);
  185. MicroChunkPosition = File->Seek(0);
  186. // Write a temporary chunk header
  187. // NOTE: I'm calling the ChunkSaveClass::Write method so that the bytes for
  188. // this header are tracked in the wrapping chunk. This is because micro-chunks
  189. // are simply data inside the normal chunks...
  190. if (Write(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
  191. return false;
  192. }
  193. InMicroChunk = true;
  194. return true;
  195. }
  196. /***********************************************************************************************
  197. * ChunkSaveClass::End_Micro_Chunk -- close a micro-chunk *
  198. * *
  199. * INPUT: *
  200. * *
  201. * OUTPUT: *
  202. * *
  203. * WARNINGS: *
  204. * *
  205. * HISTORY: *
  206. * 9/3/99 GTH : Created. *
  207. *=============================================================================================*/
  208. bool ChunkSaveClass::End_Micro_Chunk(void)
  209. {
  210. assert(InMicroChunk);
  211. // Save the current position
  212. int curpos = File->Seek(0);
  213. // Seek back and write the micro chunk header
  214. File->Seek(MicroChunkPosition,SEEK_SET);
  215. if (File->Write(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
  216. return false;
  217. }
  218. // Go back to the end of the file
  219. File->Seek(curpos,SEEK_SET);
  220. InMicroChunk = false;
  221. return true;
  222. }
  223. /***********************************************************************************************
  224. * ChunkSaveClass::Write -- Write data into the current chunk *
  225. * *
  226. * INPUT: *
  227. * *
  228. * OUTPUT: *
  229. * *
  230. * WARNINGS: *
  231. * *
  232. * HISTORY: *
  233. * 07/17/1997 GH : Created. *
  234. *=============================================================================================*/
  235. uint32 ChunkSaveClass::Write(const void * buf, uint32 nbytes)
  236. {
  237. // If this assert hits, you mixed data and chunks within the same chunk NO NO!
  238. assert(HeaderStack[StackIndex-1].Get_Sub_Chunk_Flag() == 0);
  239. // If this assert hits, you didnt open any chunks yet
  240. assert(StackIndex > 0);
  241. // write the bytes into the file
  242. if (File->Write(buf,nbytes) != (int)nbytes) return 0;
  243. // track them in the wrapping chunk
  244. HeaderStack[StackIndex-1].Add_Size(nbytes);
  245. // track them if you are using a micro-chunk too.
  246. if (InMicroChunk) {
  247. assert(MCHeader.Get_Size() < 255 - nbytes); // micro chunks can only be 255 bytes
  248. MCHeader.Add_Size(nbytes);
  249. }
  250. return nbytes;
  251. }
  252. /***********************************************************************************************
  253. * ChunkSaveClass::Write -- write an IOVector2Struct *
  254. * *
  255. * INPUT: *
  256. * *
  257. * OUTPUT: *
  258. * *
  259. * WARNINGS: *
  260. * *
  261. * HISTORY: *
  262. * 1/4/99 GTH : Created. *
  263. *=============================================================================================*/
  264. uint32 ChunkSaveClass::Write(const IOVector2Struct & v)
  265. {
  266. return Write(&v,sizeof(v));
  267. }
  268. /***********************************************************************************************
  269. * ChunkSaveClass::Write -- write an IOVector3Struct *
  270. * *
  271. * INPUT: *
  272. * *
  273. * OUTPUT: *
  274. * *
  275. * WARNINGS: *
  276. * *
  277. * HISTORY: *
  278. * 1/4/99 GTH : Created. *
  279. *=============================================================================================*/
  280. uint32 ChunkSaveClass::Write(const IOVector3Struct & v)
  281. {
  282. return Write(&v,sizeof(v));
  283. }
  284. /***********************************************************************************************
  285. * ChunkSaveClass::Write -- write an IOVector4Struct *
  286. * *
  287. * INPUT: *
  288. * *
  289. * OUTPUT: *
  290. * *
  291. * WARNINGS: *
  292. * *
  293. * HISTORY: *
  294. * 1/4/99 GTH : Created. *
  295. *=============================================================================================*/
  296. uint32 ChunkSaveClass::Write(const IOVector4Struct & v)
  297. {
  298. return Write(&v,sizeof(v));
  299. }
  300. /***********************************************************************************************
  301. * ChunkSaveClass::Write -- write an IOQuaternionStruct *
  302. * *
  303. * INPUT: *
  304. * *
  305. * OUTPUT: *
  306. * *
  307. * WARNINGS: *
  308. * *
  309. * HISTORY: *
  310. * 1/4/99 GTH : Created. *
  311. *=============================================================================================*/
  312. uint32 ChunkSaveClass::Write(const IOQuaternionStruct & q)
  313. {
  314. return Write(&q,sizeof(q));
  315. }
  316. /***********************************************************************************************
  317. * ChunkSaveClass::Cur_Chunk_Depth -- returns the current chunk recursion depth (debugging) *
  318. * *
  319. * INPUT: *
  320. * *
  321. * OUTPUT: *
  322. * *
  323. * WARNINGS: *
  324. * *
  325. * HISTORY: *
  326. * 07/17/1997 GH : Created. *
  327. *=============================================================================================*/
  328. int ChunkSaveClass::Cur_Chunk_Depth(void)
  329. {
  330. return StackIndex;
  331. }
  332. /***********************************************************************************************
  333. * ChunkLoadClass::ChunkLoadClass -- Constructor *
  334. * *
  335. * INPUT: *
  336. * *
  337. * OUTPUT: *
  338. * *
  339. * WARNINGS: *
  340. * *
  341. * HISTORY: *
  342. * 07/17/1997 GH : Created. *
  343. *=============================================================================================*/
  344. ChunkLoadClass::ChunkLoadClass(FileClass * file) :
  345. File(file),
  346. StackIndex(0),
  347. InMicroChunk(false),
  348. MicroChunkPosition(0)
  349. {
  350. memset(PositionStack,0,sizeof(PositionStack));
  351. memset(HeaderStack,0,sizeof(HeaderStack));
  352. memset(&MCHeader,0,sizeof(MCHeader));
  353. }
  354. /***********************************************************************************************
  355. * ChunkLoadClass::Open_Chunk -- Open a chunk in the file, reads in the chunk header *
  356. * *
  357. * INPUT: *
  358. * *
  359. * OUTPUT: *
  360. * *
  361. * WARNINGS: *
  362. * *
  363. * HISTORY: *
  364. * 07/17/1997 GH : Created. *
  365. *=============================================================================================*/
  366. bool ChunkLoadClass::Open_Chunk()
  367. {
  368. // if user didn't close any micro chunks that he opened, bad things could happen
  369. assert(InMicroChunk == false);
  370. // check for stack overflow
  371. assert(StackIndex < MAX_STACK_DEPTH-1);
  372. // if the parent chunk has been completely eaten, return false
  373. if ((StackIndex > 0) && (PositionStack[StackIndex-1] == HeaderStack[StackIndex-1].Get_Size())) {
  374. return false;
  375. }
  376. // read the chunk header
  377. if (File->Read(&HeaderStack[StackIndex],sizeof(ChunkHeader)) != sizeof(ChunkHeader)) {
  378. return false;
  379. }
  380. PositionStack[StackIndex] = 0;
  381. StackIndex++;
  382. return true;
  383. }
  384. /***********************************************************************************************
  385. * ChunkLoadClass::Close_Chunk -- Close a chunk, seeks to the end if needed *
  386. * *
  387. * INPUT: *
  388. * *
  389. * OUTPUT: *
  390. * *
  391. * WARNINGS: *
  392. * *
  393. * HISTORY: *
  394. * 07/17/1997 GH : Created. *
  395. *=============================================================================================*/
  396. bool ChunkLoadClass::Close_Chunk()
  397. {
  398. // if user didn't close any micro chunks that he opened, bad things could happen
  399. assert(InMicroChunk == false);
  400. // check for stack overflow
  401. assert(StackIndex > 0);
  402. int csize = HeaderStack[StackIndex-1].Get_Size();
  403. int pos = PositionStack[StackIndex-1];
  404. if (pos < csize) {
  405. File->Seek(csize - pos,SEEK_CUR);
  406. }
  407. StackIndex--;
  408. if (StackIndex > 0) {
  409. PositionStack[StackIndex - 1] += csize + sizeof(ChunkHeader);
  410. }
  411. return true;
  412. }
  413. /***********************************************************************************************
  414. * ChunkLoadClass::Cur_Chunk_ID -- Returns the ID of the current chunk *
  415. * *
  416. * INPUT: *
  417. * *
  418. * OUTPUT: *
  419. * *
  420. * WARNINGS: *
  421. * *
  422. * HISTORY: *
  423. * 07/17/1997 GH : Created. *
  424. *=============================================================================================*/
  425. uint32 ChunkLoadClass::Cur_Chunk_ID()
  426. {
  427. assert(StackIndex >= 1);
  428. return HeaderStack[StackIndex-1].Get_Type();
  429. }
  430. /***********************************************************************************************
  431. * ChunkLoadClass::Cur_Chunk_Length -- Returns the current length of the current chunk *
  432. * *
  433. * INPUT: *
  434. * *
  435. * OUTPUT: *
  436. * *
  437. * WARNINGS: *
  438. * *
  439. * HISTORY: *
  440. * 07/17/1997 GH : Created. *
  441. *=============================================================================================*/
  442. uint32 ChunkLoadClass::Cur_Chunk_Length()
  443. {
  444. assert(StackIndex >= 1);
  445. return HeaderStack[StackIndex-1].Get_Size();
  446. }
  447. /***********************************************************************************************
  448. * ChunkLoadClass::Cur_Chunk_Depth -- returns the current chunk recursion depth *
  449. * *
  450. * INPUT: *
  451. * *
  452. * OUTPUT: *
  453. * *
  454. * WARNINGS: *
  455. * *
  456. * HISTORY: *
  457. * 07/17/1997 GH : Created. *
  458. *=============================================================================================*/
  459. int ChunkLoadClass::Cur_Chunk_Depth()
  460. {
  461. return StackIndex;
  462. }
  463. /***********************************************************************************************
  464. * ChunkLoadClass::Contains_Chunks -- Test whether the current chunk contains chunks (or data) *
  465. * *
  466. * INPUT: *
  467. * *
  468. * OUTPUT: *
  469. * *
  470. * WARNINGS: *
  471. * *
  472. * HISTORY: *
  473. * 9/24/99 GTH : Created. *
  474. *=============================================================================================*/
  475. int ChunkLoadClass::Contains_Chunks()
  476. {
  477. return HeaderStack[StackIndex-1].Get_Sub_Chunk_Flag();
  478. }
  479. /***********************************************************************************************
  480. * ChunkLoadClass::Open_Micro_Chunk -- reads in a micro-chunk header *
  481. * *
  482. * INPUT: *
  483. * *
  484. * OUTPUT: *
  485. * *
  486. * WARNINGS: *
  487. * *
  488. * HISTORY: *
  489. * 9/3/99 GTH : Created. *
  490. *=============================================================================================*/
  491. bool ChunkLoadClass::Open_Micro_Chunk()
  492. {
  493. assert(!InMicroChunk);
  494. // read the chunk header
  495. // calling the ChunkLoadClass::Read fn so that if we exhaust the chunk, the read will fail
  496. if (Read(&MCHeader,sizeof(MCHeader)) != sizeof(MCHeader)) {
  497. return false;
  498. }
  499. InMicroChunk = true;
  500. MicroChunkPosition = 0;
  501. return true;
  502. }
  503. /***********************************************************************************************
  504. * ChunkLoadClass::Close_Micro_Chunk -- closes a micro-chunk (seeks to end) *
  505. * *
  506. * INPUT: *
  507. * *
  508. * OUTPUT: *
  509. * *
  510. * WARNINGS: *
  511. * *
  512. * HISTORY: *
  513. * 9/3/99 GTH : Created. *
  514. *=============================================================================================*/
  515. bool ChunkLoadClass::Close_Micro_Chunk()
  516. {
  517. assert(InMicroChunk);
  518. InMicroChunk = false;
  519. int csize = MCHeader.Get_Size();
  520. int pos = MicroChunkPosition;
  521. // seek the file past this micro chunk
  522. if (pos < csize) {
  523. File->Seek(csize - pos,SEEK_CUR);
  524. // update the tracking variables for where we are in the normal chunk.
  525. if (StackIndex > 0) {
  526. PositionStack[StackIndex-1] += csize - pos;
  527. }
  528. }
  529. return true;
  530. }
  531. /***********************************************************************************************
  532. * ChunkLoadClass::Cur_Micro_Chunk_ID -- returns the ID of the current micro-chunk (asserts if *
  533. * *
  534. * INPUT: *
  535. * *
  536. * OUTPUT: *
  537. * *
  538. * WARNINGS: *
  539. * Asserts if you are not currently inside a micro-chunk *
  540. * Micro chunks have an id between 0 and 255 *
  541. * *
  542. * HISTORY: *
  543. * 9/3/99 GTH : Created. *
  544. *=============================================================================================*/
  545. uint32 ChunkLoadClass::Cur_Micro_Chunk_ID()
  546. {
  547. assert(InMicroChunk);
  548. return MCHeader.Get_Type();
  549. }
  550. /***********************************************************************************************
  551. * ChunkLoadClass::Cur_Micro_Chunk_Length -- returns the size of the current micro chunk *
  552. * *
  553. * INPUT: *
  554. * *
  555. * OUTPUT: *
  556. * *
  557. * WARNINGS: *
  558. * Asserts if you are not currently inside a micro-chunk *
  559. * Micro chunks have a maximum size of 255 bytes *
  560. * *
  561. * HISTORY: *
  562. * 9/3/99 GTH : Created. *
  563. *=============================================================================================*/
  564. uint32 ChunkLoadClass::Cur_Micro_Chunk_Length()
  565. {
  566. assert(InMicroChunk);
  567. return MCHeader.Get_Size();
  568. }
  569. // Seek over nbytes in the stream
  570. uint32 ChunkLoadClass::Seek(uint32 nbytes)
  571. {
  572. assert(StackIndex >= 1);
  573. // Don't seek if we would go past the end of the current chunk
  574. if (PositionStack[StackIndex-1] + nbytes > (int)HeaderStack[StackIndex-1].Get_Size()) {
  575. return 0;
  576. }
  577. // Don't read if we are in a micro chunk and would go past the end of it
  578. if (InMicroChunk && MicroChunkPosition + nbytes > MCHeader.Get_Size()) {
  579. return 0;
  580. }
  581. uint32 curpos=File->Tell();
  582. if (File->Seek(nbytes,SEEK_CUR)-curpos != (int)nbytes) {
  583. return 0;
  584. }
  585. // Update our position in the chunk
  586. PositionStack[StackIndex-1] += nbytes;
  587. // Update our position in the micro chunk if we are in one
  588. if (InMicroChunk) {
  589. MicroChunkPosition += nbytes;
  590. }
  591. return nbytes;
  592. }
  593. /***********************************************************************************************
  594. * ChunkLoadClass::Read -- Read data from the file *
  595. * *
  596. * INPUT: *
  597. * *
  598. * OUTPUT: *
  599. * *
  600. * WARNINGS: *
  601. * *
  602. * HISTORY: *
  603. * 07/17/1997 GH : Created. *
  604. *=============================================================================================*/
  605. uint32 ChunkLoadClass::Read(void * buf,uint32 nbytes)
  606. {
  607. assert(StackIndex >= 1);
  608. // Don't read if we would go past the end of the current chunk
  609. if (PositionStack[StackIndex-1] + nbytes > (int)HeaderStack[StackIndex-1].Get_Size()) {
  610. return 0;
  611. }
  612. // Don't read if we are in a micro chunk and would go past the end of it
  613. if (InMicroChunk && MicroChunkPosition + nbytes > MCHeader.Get_Size()) {
  614. return 0;
  615. }
  616. if (File->Read(buf,nbytes) != (int)nbytes) {
  617. return 0;
  618. }
  619. // Update our position in the chunk
  620. PositionStack[StackIndex-1] += nbytes;
  621. // Update our position in the micro chunk if we are in one
  622. if (InMicroChunk) {
  623. MicroChunkPosition += nbytes;
  624. }
  625. return nbytes;
  626. }
  627. /***********************************************************************************************
  628. * ChunkLoadClass::Read -- read an IOVector2Struct *
  629. * *
  630. * INPUT: *
  631. * *
  632. * OUTPUT: *
  633. * *
  634. * WARNINGS: *
  635. * *
  636. * HISTORY: *
  637. * 1/4/99 GTH : Created. *
  638. *=============================================================================================*/
  639. uint32 ChunkLoadClass::Read(IOVector2Struct * v)
  640. {
  641. assert(v != NULL);
  642. return Read(v,sizeof(v));
  643. }
  644. /***********************************************************************************************
  645. * ChunkLoadClass::Read -- read an IOVector3Struct *
  646. * *
  647. * INPUT: *
  648. * *
  649. * OUTPUT: *
  650. * *
  651. * WARNINGS: *
  652. * *
  653. * HISTORY: *
  654. * 1/4/99 GTH : Created. *
  655. *=============================================================================================*/
  656. uint32 ChunkLoadClass::Read(IOVector3Struct * v)
  657. {
  658. assert(v != NULL);
  659. return Read(v,sizeof(v));
  660. }
  661. /***********************************************************************************************
  662. * ChunkLoadClass::Read -- read an IOVector4Struct *
  663. * *
  664. * INPUT: *
  665. * *
  666. * OUTPUT: *
  667. * *
  668. * WARNINGS: *
  669. * *
  670. * HISTORY: *
  671. * 1/4/99 GTH : Created. *
  672. *=============================================================================================*/
  673. uint32 ChunkLoadClass::Read(IOVector4Struct * v)
  674. {
  675. assert(v != NULL);
  676. return Read(v,sizeof(v));
  677. }
  678. /***********************************************************************************************
  679. * ChunkLoadClass::Read -- read an IOQuaternionStruct *
  680. * *
  681. * INPUT: *
  682. * *
  683. * OUTPUT: *
  684. * *
  685. * WARNINGS: *
  686. * *
  687. * HISTORY: *
  688. * 1/4/99 GTH : Created. *
  689. *=============================================================================================*/
  690. uint32 ChunkLoadClass::Read(IOQuaternionStruct * q)
  691. {
  692. assert(q != NULL);
  693. return Read(q,sizeof(q));
  694. }