chunkio.cpp 47 KB

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