Isle
Loading...
Searching...
No Matches
mxio.cpp
Go to the documentation of this file.
1#include "mxio.h"
2
3#include "decomp.h"
4
5#include <assert.h>
6
7// This class should be 72 bytes in size, same as the MMIOINFO struct.
8// The current implementation has MMIOINFO as the only member of the class,
9// but this assert will enforce the size if we decide to change that.
10DECOMP_SIZE_ASSERT(MXIOINFO, sizeof(MMIOINFO));
11
12#ifdef MXIO_MINFO_MFILE
13#define ASSIGN_M_FILE(X) m_info.hmmio = (HMMIO) (X)
14#define M_FILE (HFILE)(m_info.hmmio)
15#define RAW_M_FILE m_info.hmmio
16#else
17#define ASSIGN_M_FILE(X) m_file = (X)
18#define M_FILE (m_file)
19#define RAW_M_FILE m_file
20#endif
21
22// FUNCTION: LEGO1 0x100cc800
23// FUNCTION: BETA10 0x1015e140
25{
26 memset(&m_info, 0, sizeof(m_info));
27}
28
29// FUNCTION: LEGO1 0x100cc820
30// FUNCTION: BETA10 0x1015e169
32{
33 Close(0);
34}
35
36// FUNCTION: LEGO1 0x100cc830
37// FUNCTION: BETA10 0x1015e189
38MxU16 MXIOINFO::Open(const char* p_filename, MxULong p_flags)
39{
40 OFSTRUCT unused;
41 MxU16 result = MMSYSERR_NOERROR;
42
43 m_info.lDiskOffset = m_info.lBufOffset = 0;
44
45 // DECOMP: Cast of p_flags to u16 forces the `movzx` instruction
46 // original: m_info.hmmio = OpenFile(p_filename, &unused, (MxU16) p_flags);
47 ASSIGN_M_FILE(OpenFile(p_filename, &unused, (MxU16) p_flags));
48
49 if (M_FILE != HFILE_ERROR) {
50 m_info.dwFlags = p_flags;
51 if (m_info.dwFlags & MMIO_ALLOCBUF) {
52
53 // Default buffer length of 8k if none specified
54 MxLong len = m_info.cchBuffer;
55 if (len == 0) {
56 len = 8192;
57 }
58
59 char* buf = new char[len];
60
61 if (!buf) {
62 m_info.dwFlags &= ~MMIO_ALLOCBUF;
63 m_info.cchBuffer = 0;
64 m_info.pchBuffer = 0;
65 result = MMIOERR_OUTOFMEMORY;
66 }
67 else {
68 m_info.cchBuffer = len;
69 m_info.pchBuffer = (HPSTR) buf;
70 }
71
72 m_info.pchNext = m_info.pchEndRead = m_info.pchBuffer;
73 m_info.pchEndWrite = m_info.pchBuffer + m_info.cchBuffer;
74 }
75 }
76 else {
77 result = MMIOERR_CANNOTOPEN;
78 }
79
80 return result;
81}
82
83// FUNCTION: LEGO1 0x100cc8e0
84// FUNCTION: BETA10 0x1015e30b
86{
87 MxU16 result = MMSYSERR_NOERROR;
88
89 if (RAW_M_FILE) {
90 result = Flush(0);
91 _lclose(M_FILE);
93
94 if (m_info.dwFlags & MMIO_ALLOCBUF) {
95 delete[] m_info.pchBuffer;
96 }
97
98 m_info.pchBuffer = m_info.pchEndRead = m_info.pchEndWrite = NULL;
99 m_info.dwFlags = 0;
100 }
101
102 return result;
103}
104
105// FUNCTION: LEGO1 0x100cc930
106// FUNCTION: BETA10 0x1015e3b2
107MxLong MXIOINFO::Read(void* p_buf, MxLong p_len)
108{
109 MxLong bytesRead = 0;
110
111 if (m_info.pchBuffer) {
112
113 MxLong bytesLeft = m_info.pchEndRead - m_info.pchNext;
114 while (p_len > 0) {
115
116 if (bytesLeft > 0) {
117 if (p_len < bytesLeft) {
118 bytesLeft = p_len;
119 }
120
121 memcpy(p_buf, m_info.pchNext, bytesLeft);
122
123 m_info.pchNext += bytesLeft;
124 bytesRead += bytesLeft;
125 p_len -= bytesLeft;
126 }
127
128 if (p_len > 0) {
129 if (Advance(MMIO_READ)) {
130 break;
131 }
132 else {
133 bytesLeft = m_info.pchEndRead - m_info.pchNext;
134 if (bytesLeft <= 0) {
135 break;
136 }
137 }
138 }
139 }
140 }
141 else if (RAW_M_FILE && p_len > 0) {
142 bytesRead = _hread(M_FILE, p_buf, p_len);
143
144 if (bytesRead == -1) {
145 bytesRead = 0;
146 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
147 }
148 else {
149 m_info.lDiskOffset += bytesRead;
150 }
151 }
152
153 return bytesRead;
154}
155
156// FUNCTION: BETA10 0x1015e4fc
157MxLong MXIOINFO::Write(void* p_buf, MxLong p_len)
158{
159 MxLong bytesWritten = 0;
160
161 if (m_info.pchBuffer) {
162
163 MxLong bytesLeft = m_info.pchEndWrite - m_info.pchNext;
164 while (p_len > 0) {
165
166 if (bytesLeft > 0) {
167 if (p_len < bytesLeft) {
168 bytesLeft = p_len;
169 }
170
171 memcpy(m_info.pchNext, p_buf, bytesLeft);
172 m_info.dwFlags |= MMIO_DIRTY;
173
174 m_info.pchNext += bytesLeft;
175 bytesWritten += bytesLeft;
176 p_len -= bytesLeft;
177 }
178
179 if (p_len > 0) {
180 if (Advance(MMIO_WRITE)) {
181 assert(0);
182 break;
183 }
184 else {
185 bytesLeft = m_info.pchEndWrite - m_info.pchNext;
186 if (bytesLeft <= 0) {
187 assert(0);
188 break;
189 }
190 }
191 }
192 }
193 }
194 else if (RAW_M_FILE && p_len > 0) {
195 bytesWritten = _hwrite(M_FILE, (const char*) p_buf, p_len);
196
197 if (bytesWritten == -1) {
198 bytesWritten = 0;
199 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
200 }
201 else {
202 m_info.lDiskOffset += bytesWritten;
203 }
204 }
205
206 // DECOMP: This assert is just "pchNext <= pchEndWrite"
207 // That would suggest that MXIOINFO directly extends MMIOINFO.
208 // TODO: Change that if we still have entropy at the end.
209 assert(m_info.pchNext <= m_info.pchEndWrite);
210 return bytesWritten;
211}
212
213// FUNCTION: LEGO1 0x100cca00
214// FUNCTION: BETA10 0x1015e6c4
216{
217 MxLong result = -1;
218 MxLong bytesRead;
219
220 // If buffered I/O
221 if (m_info.pchBuffer) {
222 if (p_origin == SEEK_CUR) {
223 if (!p_offset) {
224 // don't seek at all and just return where we are.
225 return m_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
226 }
227
228 // With SEEK_CUR, p_offset is a relative offset.
229 // Get the absolute position instead and use SEEK_SET.
230 p_offset += m_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
231 p_origin = SEEK_SET;
232 }
233 else if (p_origin == SEEK_END) {
234 // not possible with buffered I/O
235 return -1;
236 }
237
238 // else p_origin == SEEK_SET.
239
240 // is p_offset between the start and end of the buffer?
241 // i.e. can we do the seek without reading more from disk?
242 if (p_offset >= m_info.lBufOffset && p_offset < m_info.lBufOffset + m_info.cchBuffer) {
243 m_info.pchNext = m_info.pchBuffer + (p_offset - m_info.lBufOffset);
244 result = p_offset;
245 }
246 else {
247 // we have to read another chunk from disk.
248 if (RAW_M_FILE && !Flush(0)) {
249 m_info.lDiskOffset = _llseek(M_FILE, p_offset, p_origin);
250
251 if (m_info.lDiskOffset == -1) {
252 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
253 }
254 else {
255
256 // align offset to buffer size
257 m_info.lBufOffset = p_offset - (p_offset % m_info.cchBuffer);
258
259 // do we need to seek again?
260 // (i.e. are we already aligned to buffer size?)
261 if (p_offset != m_info.lBufOffset) {
262 m_info.lDiskOffset = _llseek(M_FILE, m_info.lBufOffset, SEEK_SET);
263
264 if (m_info.lDiskOffset == -1) {
265 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
266 }
267 }
268
269 if (m_info.lBufOffset == m_info.lDiskOffset) {
270 // is the file open for writing only?
271 if ((m_info.dwFlags & MMIO_RWMODE) == 0 || (m_info.dwFlags & MMIO_RWMODE) == MMIO_READWRITE) {
272 // We can read from the file. Fill the buffer.
273 bytesRead = _hread(M_FILE, m_info.pchBuffer, m_info.cchBuffer);
274
275 if (bytesRead == -1) {
276 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
277 }
278 else {
279 m_info.lDiskOffset += bytesRead;
280 m_info.pchNext = p_offset - m_info.lBufOffset + m_info.pchBuffer;
281 m_info.pchEndRead = m_info.pchBuffer + bytesRead;
282
283 if (m_info.pchNext < m_info.pchEndRead) {
284 result = p_offset;
285 }
286 }
287 }
288 else {
289 m_info.pchNext = p_offset - m_info.lBufOffset + m_info.pchBuffer;
290 result = p_offset;
291 }
292 }
293 }
294 }
295 }
296 }
297 else if (RAW_M_FILE) {
298 // No buffer so just seek the file directly (if we have a valid handle)
299 // i.e. if we just want to get the current file position
300 if (p_origin == SEEK_CUR && p_offset == 0) {
301 return m_info.lDiskOffset;
302 }
303
304 m_info.lDiskOffset = _llseek(M_FILE, p_offset, p_origin);
305
306 result = m_info.lDiskOffset;
307
308 if (result == -1) {
309 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
310 }
311 }
312
313 return result;
314}
315
316// FUNCTION: LEGO1 0x100ccbc0
317// FUNCTION: BETA10 0x1015e9ad
318MxU16 MXIOINFO::SetBuffer(char* p_buf, MxLong p_len, MxLong p_unused)
319{
320 MxU16 result = MMSYSERR_NOERROR;
321 result = Flush(0);
322
323 if (m_info.dwFlags & MMIO_ALLOCBUF) {
324 m_info.dwFlags &= ~MMIO_ALLOCBUF;
325 delete[] m_info.pchBuffer;
326 }
327
328 m_info.pchBuffer = p_buf;
329 m_info.cchBuffer = p_len;
330 m_info.pchEndWrite = m_info.pchBuffer + m_info.cchBuffer;
331 m_info.pchEndRead = m_info.pchBuffer;
332
333 return result;
334}
335
336// FUNCTION: LEGO1 0x100ccc10
337// FUNCTION: BETA10 0x1015ea3e
339{
340 MxU16 result = MMSYSERR_NOERROR;
341 MxLong bytesWritten;
342
343 // if buffer is dirty
344 if (m_info.dwFlags & MMIO_DIRTY) {
345 // if we have allocated an IO buffer
346 if (m_info.pchBuffer) {
347 // if we have a file open for writing
348 if (RAW_M_FILE && (m_info.dwFlags & MMIO_RWMODE)) {
349 // DECOMP: pulling this value out into a variable forces it into EBX
350 MxLong cchBuffer = m_info.cchBuffer;
351 if (cchBuffer > 0) {
352 if (m_info.lBufOffset != m_info.lDiskOffset) {
353 m_info.lDiskOffset = _llseek(M_FILE, m_info.lBufOffset, SEEK_SET);
354 }
355
356 // Was the previous seek (if required) successful?
357 if (m_info.lBufOffset != m_info.lDiskOffset) {
358 result = MMIOERR_CANNOTSEEK;
359 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
360 }
361 else {
362 bytesWritten = _hwrite(M_FILE, m_info.pchBuffer, cchBuffer);
363
364 if (bytesWritten == -1 || bytesWritten != cchBuffer) {
365 result = MMIOERR_CANNOTWRITE;
366 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
367 }
368 else {
369 m_info.lDiskOffset += bytesWritten;
370 m_info.pchNext = m_info.pchBuffer;
371 m_info.dwFlags &= ~MMIO_DIRTY;
372 }
373 }
374 }
375 }
376 else {
377 result = MMIOERR_CANNOTWRITE;
378 }
379 }
380 else {
381 result = MMIOERR_UNBUFFERED;
382 }
383 }
384
385 return result;
386}
387
388// FUNCTION: LEGO1 0x100ccd00
389// FUNCTION: BETA10 0x1015eb8f
391{
392 MxU16 result = MMSYSERR_NOERROR;
393 MxULong rwmode = m_info.dwFlags & MMIO_RWMODE;
394
395 if (m_info.pchBuffer) {
396 MxLong cch = m_info.cchBuffer;
397 MxLong bytesCounter;
398
399 // If we can and should write to the file,
400 // if we are being asked to write to the file,
401 // and if there is a buffer *to* write:
402 if ((rwmode == MMIO_WRITE || rwmode == MMIO_READWRITE) && (m_info.dwFlags & MMIO_DIRTY) &&
403 ((p_option & MMIO_WRITE) || (rwmode == MMIO_READWRITE)) && cch > 0) {
404
405 if (m_info.lBufOffset != m_info.lDiskOffset) {
406 m_info.lDiskOffset = _llseek(M_FILE, m_info.lBufOffset, SEEK_SET);
407 }
408
409 if (m_info.lBufOffset != m_info.lDiskOffset) {
410 result = MMIOERR_CANNOTSEEK;
411 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
412 }
413 else {
414 bytesCounter = _hwrite(M_FILE, m_info.pchBuffer, cch);
415
416 if (bytesCounter == -1 || bytesCounter != cch) {
417 result = MMIOERR_CANNOTWRITE;
418 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
419 }
420 else {
421 m_info.lDiskOffset += bytesCounter;
422 m_info.pchNext = m_info.pchBuffer;
423 m_info.pchEndRead = m_info.pchBuffer;
424 m_info.dwFlags &= ~MMIO_DIRTY;
425 }
426 }
427 }
428
429 m_info.lBufOffset += cch;
430 if ((!rwmode || rwmode == MMIO_READWRITE) && cch > 0) {
431 if (m_info.lBufOffset != m_info.lDiskOffset) {
432 m_info.lDiskOffset = _llseek(M_FILE, m_info.lBufOffset, SEEK_SET);
433 }
434
435 // if previous seek failed
436 if (m_info.lBufOffset != m_info.lDiskOffset) {
437 result = MMIOERR_CANNOTSEEK;
438 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
439 }
440 else {
441 bytesCounter = _hread(M_FILE, m_info.pchBuffer, cch);
442
443 if (bytesCounter == -1) {
444 result = MMIOERR_CANNOTREAD;
445 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
446 }
447 else {
448 m_info.lDiskOffset += bytesCounter;
449 m_info.pchNext = m_info.pchBuffer;
450 m_info.pchEndRead = m_info.pchBuffer + bytesCounter;
451 }
452 }
453 }
454 }
455 else {
456 result = MMIOERR_UNBUFFERED;
457 }
458
459 return result;
460}
461
462// FUNCTION: LEGO1 0x100cce60
463// FUNCTION: BETA10 0x1015edef
464MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU16 p_descend)
465{
466 MxU16 result = MMSYSERR_NOERROR;
467 MxULong ofs;
468 BOOL readOk;
469
470 if (!p_chunkInfo) {
471 return MMIOERR_BASE; // ?
472 }
473
474 if (!p_descend) {
475 p_chunkInfo->dwFlags = 0;
476 if (Read(p_chunkInfo, 8) != 8) {
477 result = MMIOERR_CANNOTREAD;
478 }
479 else {
480 if (m_info.pchBuffer) {
481 p_chunkInfo->dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
482 }
483 else {
484 p_chunkInfo->dwDataOffset = m_info.lDiskOffset;
485 }
486
487 if ((p_chunkInfo->ckid == FOURCC_RIFF || p_chunkInfo->ckid == FOURCC_LIST) &&
488 Read(&p_chunkInfo->fccType, 4) != 4) {
489 result = MMIOERR_CANNOTREAD;
490 }
491 }
492 }
493 else {
494 ofs = MAXLONG;
495
496 if (p_parentInfo) {
497 ofs = p_parentInfo->cksize + p_parentInfo->dwDataOffset;
498 }
499
500 BOOL running = TRUE;
501 readOk = FALSE;
502 MMCKINFO tmp;
503 tmp.dwFlags = 0;
504
505 while (running) {
506 if (Read(&tmp, 8) != 8) {
507 // If the first read fails, report read error. Else EOF.
508 result = readOk ? MMIOERR_CHUNKNOTFOUND : MMIOERR_CANNOTREAD;
509 running = FALSE;
510 }
511 else {
512 readOk = TRUE;
513 if (m_info.pchBuffer) {
514 tmp.dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
515 }
516 else {
517 tmp.dwDataOffset = m_info.lDiskOffset;
518 }
519
520 if (ofs < tmp.dwDataOffset) {
521 result = MMIOERR_CHUNKNOTFOUND;
522 running = FALSE;
523 }
524 else if ((p_descend == MMIO_FINDLIST && tmp.ckid == FOURCC_LIST) || (p_descend == MMIO_FINDRIFF && tmp.ckid == FOURCC_RIFF)) {
525 if (Read(&tmp.fccType, 4) != 4) {
526 result = MMIOERR_CANNOTREAD;
527 running = FALSE;
528 }
529 else if (p_chunkInfo->fccType == tmp.fccType) {
530 running = FALSE;
531 }
532 }
533 else if (p_chunkInfo->ckid == tmp.ckid) {
534 running = FALSE;
535 }
536 else if (Seek((tmp.cksize & 1) + tmp.cksize, SEEK_CUR) == -1) {
537 result = MMIOERR_CANNOTSEEK;
538 running = FALSE;
539 }
540 }
541 }
542
543 if (!result) {
544 // implicit memcpy
545 *p_chunkInfo = tmp;
546 }
547 }
548
549 return result;
550}
551
552// FUNCTION: BETA10 0x1015f08b
553MxU16 MXIOINFO::Ascend(MMCKINFO* p_chunkInfo, MxU16 p_ascend)
554{
555 MxLong ofs;
556 MxULong size;
557 MxU16 result = MMSYSERR_NOERROR;
558
559 if (p_chunkInfo == NULL) {
560 return MMIOERR_BASE;
561 }
562
563 if (m_info.dwFlags & MMIO_RWMODE) {
564 if (m_info.pchBuffer) {
565 size = (MxULong) (m_info.pchNext - m_info.pchBuffer) + m_info.lBufOffset - p_chunkInfo->dwDataOffset;
566 }
567 else {
568 size = m_info.lDiskOffset - p_chunkInfo->dwDataOffset;
569 }
570
571 // Write a zero byte if the chunk size is odd
572 if (size & 1) {
573 Write(&result, 1);
574 }
575
576 if ((p_chunkInfo->dwFlags & MMIO_DIRTY) && p_chunkInfo->cksize != size) {
577 ofs = p_chunkInfo->dwDataOffset - 4;
578 // Correct chunk size
579 p_chunkInfo->cksize = size;
580 p_chunkInfo->dwFlags &= ~MMIO_DIRTY;
581
582 // Now write the corrected size
583 if (m_info.pchBuffer && ofs >= m_info.lBufOffset && m_info.cchBuffer + m_info.lBufOffset > ofs) {
584 memcpy(m_info.pchBuffer + (ofs - m_info.lBufOffset), (char*) &size, 4);
585 m_info.dwFlags |= MMIO_DIRTY;
586 }
587 else {
588 m_info.lDiskOffset = _llseek(M_FILE, ofs, SEEK_SET);
589
590 if (m_info.lDiskOffset == ofs) {
591 if (_lwrite(M_FILE, (char*) &size, 4) != 4) {
592 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
593 result = MMIOERR_CANNOTWRITE;
594 }
595 else {
596 m_info.lDiskOffset += 4; // TODO: compiler weirdness?
597 }
598 }
599 else {
600 m_info.lDiskOffset = _llseek(M_FILE, 0, SEEK_CUR);
601 result = MMIOERR_CANNOTSEEK;
602 }
603 }
604 }
605 }
606
607 // Seek past the end of the chunk (plus optional pad byte if size is odd)
608 if (result == MMSYSERR_NOERROR &&
609 Seek((p_chunkInfo->cksize & 1) + p_chunkInfo->cksize + p_chunkInfo->dwDataOffset, SEEK_SET) == -1) {
610 result = MMIOERR_CANNOTSEEK;
611 }
612
613 return result;
614}
615
616// FUNCTION: BETA10 0x1015f28b
617MxU16 MXIOINFO::CreateChunk(MMCKINFO* p_chunkInfo, MxU16 p_create)
618{
619 MxU16 result = MMSYSERR_NOERROR;
620
621 if (p_chunkInfo == NULL) {
622 return MMIOERR_BASE;
623 }
624
625 if (p_create == MMIO_CREATERIFF) {
626 p_chunkInfo->ckid = FOURCC_RIFF;
627 }
628 if (p_create == MMIO_CREATELIST) {
629 p_chunkInfo->ckid = FOURCC_LIST;
630 }
631
632 p_chunkInfo->dwDataOffset = Seek(0, SEEK_CUR);
633 if (p_chunkInfo->dwDataOffset == -1) {
634 result = MMIOERR_CANNOTSEEK;
635 }
636 else {
637 p_chunkInfo->dwDataOffset += 8;
638 }
639
640 MxU32 size;
641 if (p_chunkInfo->ckid == FOURCC_RIFF || p_chunkInfo->ckid == FOURCC_LIST) {
642 size = 12;
643 }
644 else {
645 size = 8;
646 }
647
648 if (Write(p_chunkInfo, size) != size) {
649 result = MMIOERR_CANNOTWRITE;
650 }
651
652 p_chunkInfo->dwFlags = MMIO_DIRTY;
653 return result;
654}
[AI] A wrapper for low-level file I/O, abstracting MMIOINFO functionality, and providing additional b...
Definition: mxio.h:22
MxU16 Descend(MMCKINFO *p_chunkInfo, const MMCKINFO *p_parentInfo, MxU16 p_descend)
[AI] Descends into a specific RIFF or LIST chunk in a hierarchical file, reading chunk headers and up...
Definition: mxio.cpp:464
MxLong Seek(MxLong p_offset, MxLong p_origin)
[AI] Seeks to a specific position in the file (or file buffer).
Definition: mxio.cpp:215
MxU16 Advance(MxU16 p_option)
[AI] Advances the buffer state for reading/writing the next block, committing dirty writes and loadin...
Definition: mxio.cpp:390
~MXIOINFO()
[AI] Destructor, closes the file and releases all memory associated with buffers if necessary.
Definition: mxio.cpp:31
MxU16 SetBuffer(char *p_buf, MxLong p_len, MxLong p_unused)
[AI] Changes the buffer used for internal I/O (applies and releases old buffer if owned).
Definition: mxio.cpp:318
MxU16 Ascend(MMCKINFO *p_chunkInfo, MxU16 p_ascend)
[AI] Ascends from a chunk in a hierarchical file, correcting chunk size and finishing the chunk corre...
Definition: mxio.cpp:553
MxLong Read(void *p_buf, MxLong p_len)
[AI] Reads a number of bytes from the file or buffer into the destination buffer.
Definition: mxio.cpp:107
MXIOINFO()
[AI] Constructs a new MXIOINFO instance and initializes all struct members to zero.
Definition: mxio.cpp:24
MxLong Write(void *p_buf, MxLong p_len)
[AI] Writes data to the file or internal buffer.
Definition: mxio.cpp:157
MxU16 CreateChunk(MMCKINFO *p_chunkInfo, MxU16 p_create)
[AI] Creates a new hierarchical chunk (RIFF or LIST or other type), writing initial chunk header.
Definition: mxio.cpp:617
MxU16 Open(const char *p_filename, MxULong p_flags)
[AI] Opens a file for buffered/unbuffered I/O, initializing MMIOINFO and (optionally) internal buffer...
Definition: mxio.cpp:38
MMIOINFO m_info
[AI] Underlying MMIOINFO structure used for buffered and low-level file I/O.
Definition: mxio.h:125
MxU16 Flush(MxU16 p_unused)
[AI] Flushes contents of the buffer to disk if necessary (e.g., if data is dirty).
Definition: mxio.cpp:338
MxU16 Close(MxLong p_unused)
[AI] Closes the file and releases its resources, including buffer memory if owned.
Definition: mxio.cpp:85
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
typedef BOOL(FAR PASCAL *LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
#define M_FILE
Definition: mxio.cpp:18
#define ASSIGN_M_FILE(X)
Definition: mxio.cpp:17
#define RAW_M_FILE
Definition: mxio.cpp:19
int MxLong
[AI]
Definition: mxtypes.h:83
unsigned int MxULong
[AI]
Definition: mxtypes.h:93
unsigned short MxU16
[AI]
Definition: mxtypes.h:20
unsigned int MxU32
[AI]
Definition: mxtypes.h:32