/// MemoryStream::BufferedBytes // Return the number of bytes buffered within this memory stream starting // at the current file position. ULONG MemoryStream::BufferedBytes(void) const { if (m_pParent) { UQUAD bytes; // assert(m_pucBufPtr <= m_pucBufEnd); // The idea here is compute the difference between the // file position of the writer and the file position of the reader. // The counter includes the number of bytes that have been already // placed in the output buffer, even though we haven't read // them yet. We just remove the buffers we haven't read yet // from the counting: This is the number of bytes in front // of the file pointer, i.e. the file position in the // reading system. It should be smaller or equal than // the file position of the writing end. bytes = m_uqCounter - (m_pucBufEnd - m_pucBufPtr); // // Now compare this with the number of bytes in front of the // writing end: This is the number of bytes currently // available. return ULONG(m_pParent->FilePosition() - bytes); } else { // The file position directly. return FilePosition(); } }
// Parses the entire contents of an XNB file. void ContentReader::ReadXnb() { // Read the XNB header. uint32_t endPosition = ReadHeader(); ReadTypeManifest(); uint32_t sharedResourceCount = Read7BitEncodedInt(); // Read the primary asset data. Log.WriteLine("Asset:"); ReadObject(); // Read any shared resource instances. for (uint32_t i = 0 ; i < sharedResourceCount; i++) { Log.WriteLine("Shared resource %d:", i); ReadObject(); } // Make sure we read the amount of data that the file header said we should. if (FilePosition() != endPosition) { throw app_exception("End position does not match XNB header: unexpected amount of data was read."); } }
int File::Position() const { switch(srctype) { case MODE_MYFILE: case MODE_EXTFILE: return FilePosition(file); case MODE_MYDATA: case MODE_EXTDATA: return datapos; case MODE_TCPSOCKET: case MODE_UDPSOCKET: if(file == INVALID_FILE_POINTER) return -1; return 0; } return -1; }
// Reads the XNB file header (version number, size, etc.). uint32_t ContentReader::ReadHeader() { uint32_t startPosition = FilePosition(); // Magic number. uint8_t magic1 = ReadByte(); uint8_t magic2 = ReadByte(); uint8_t magic3 = ReadByte(); if (magic1 != 'X' || magic2 != 'N' || magic3 != 'B') { throw app_exception("Not an XNB file."); } // Target platform. uint8_t targetPlatform = ReadByte(); switch (targetPlatform) { case 'w': Log.WriteLine("Target platform: Windows"); break; case 'm': Log.WriteLine("Target platform: Windows Phone"); break; case 'x': Log.WriteLine("Target platform: Xbox 360"); break; default: Log.WriteLine("Unknown target platform %d", targetPlatform); break; } // Format version. uint8_t formatVersion = ReadByte(); if (formatVersion != 5) { Log.WriteLine("Warning: not an XNA Game Studio version 4.0 XNB file. Parsing may fail unexpectedly."); } // Flags. uint8_t flags = ReadByte(); if (flags & 1) { Log.WriteLine("Graphics profile: HiDef"); } else { Log.WriteLine("Graphics profile: Reach"); } bool isCompressed = (flags & 0x80) != 0; // File size. uint32_t sizeOnDisk = ReadUInt32(); if (startPosition + sizeOnDisk > FileSize()) { throw app_exception("XNB file has been truncated."); } if (isCompressed) { uint32_t decompressedSize = ReadUInt32(); uint32_t compressedSize = startPosition + sizeOnDisk - FilePosition(); Log.WriteLine("%d bytes of asset data are compressed into %d", decompressedSize, compressedSize); throw app_exception("Don't support reading the contents of compressed XNB files."); } return startPosition + sizeOnDisk; }
/*---------------------------------------------------------------------*/ BOOL CreateEventHeader(H_STREAM hstream, RF_PACKET * packet) { CHAR string[32]; UINT8 stream, channel; UINT16 i, unit, length; INT32 position; REAL64 time; RF_HEADER hdr; ASSERT(packet != NULL); if (!ValidateStreamHandle(hstream)) return (FALSE); _archive[_reads[hstream].harchive].last_error = ARC_NO_ERROR; /* Open the file if needed */ if (_reads[hstream].file == VOID_H_FILE) { position = VOID_INT32; if ((_reads[hstream].file = FileOpenForRead(_reads[hstream].event.filespec)) == VOID_H_FILE) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } } else { /* Otherwise, save position in file */ position = FilePosition(_reads[hstream].file); if (!FileRewind(_reads[hstream].file)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } } /* Read first packet */ if (!ReadPacket(_reads[hstream].file, &hdr, &_reads[hstream].eh)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } /* Is it an EH? */ if (hdr.type == EH) { /* Get the sampling rate */ _reads[hstream].rate = DecodeRFRate(&_reads[hstream].eh); if (!IsValidRate(_reads[hstream].rate)) { _archive[_reads[hstream].harchive].last_error = ARC_NO_RATE; return (FALSE); } debugf("CEH EHrate: %.1f...", _reads[hstream].rate); } else { /* No, read last packet */ if (!FileSeekEOF(_reads[hstream].file)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } _reads[hstream].in_seq = VOID_UINT16; if (!UnReadPacket(_reads[hstream].file)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } if (!ReadPacket(_reads[hstream].file, &hdr, &_reads[hstream].eh)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } if (!FileRewind(_reads[hstream].file)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } /* Is it an ET? */ if (hdr.type == ET) { /* Get the sampling rate */ _reads[hstream].rate = DecodeRFRate(&_reads[hstream].eh); if (!IsValidRate(_reads[hstream].rate)) { _archive[_reads[hstream].harchive].last_error = ARC_NO_RATE; return (FALSE); } debugf("CEH ETrate: %.1f...", _reads[hstream].rate); } else { /* Try to derive rate... */ unit = VOID_UINT8; while (TRUE) { if (!ReadPacket(_reads[hstream].file, &hdr, &_reads[hstream].eh)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } if (FileAtEOF()) { _archive[_reads[hstream].harchive].last_error = ARC_NO_RATE; return (FALSE); } if (hdr.type == DT && hdr.length > 0) { unit = hdr.unit; stream = hdr.stream; channel = hdr.channel; time = hdr.time; length = hdr.length; break; } } if (unit == VOID_UINT8) { _archive[_reads[hstream].harchive].last_error = ARC_NO_RATE; return (FALSE); } while (TRUE) { if (!ReadPacket(_reads[hstream].file, &hdr, &_reads[hstream].eh)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } if (FileAtEOF()) { _archive[_reads[hstream].harchive].last_error = ARC_NO_RATE; return (FALSE); } if (hdr.type == DT && hdr.unit == unit && hdr.stream == stream && hdr.channel == channel) { _reads[hstream].rate = (REAL32) (((REAL64) length / (hdr.time - time) * 10) + 0.5) / 10; if (!IsValidRate(_reads[hstream].rate)) { _archive[_reads[hstream].harchive].last_error = ARC_NO_RATE; return (FALSE); } if (!FileRewind(_reads[hstream].file)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } ArchiveLog(ARC_LOG_ERRORS, "Warning: sampling rate (%.1fsps) is derived DT times, EH/ET packets will be incomplete!", _reads[hstream].rate); /* Store rate in packet */ memset((UINT8 *) (&_reads[hstream].eh) + 24, ' ', sizeof(RF_PACKET) - 24); if (_reads[hstream].rate < 1) sprintf(string, "%-4.1f", _reads[hstream].rate); else sprintf(string, "%-4hu", (UINT16)_reads[hstream].rate); for (i = 0; i < 4; i++) { if (string[i]) _reads[hstream].eh.pac.eh.rate[i] = string[i]; } /* Set packet length so this won't be confused with 120 data */ _reads[hstream].eh.hdr.bpp[0] = 0x02; _reads[hstream].eh.hdr.bpp[1] = 0x88; break; } } } debugf("CEH derived: %.1f...", _reads[hstream].rate); } /* Restore position if it was saved above */ if (position != VOID_INT32) { if (!FileSeekAbsolute(_reads[hstream].file, position)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } } /* Find first data packet */ if (!GetNextDataPacket(hstream, &hdr, packet)) return (FALSE); /* Fixup an event header */ _reads[hstream].out_seq = 0; _reads[hstream].out_evn = hdr.evn_no; FixupHeaderTrailer(hstream, EH); /* Unget the packet */ _reads[hstream].in_seq = VOID_UINT16; if (!UnReadPacket(_reads[hstream].file)) { _archive[_reads[hstream].harchive].last_error = ARC_FILE_IO_ERROR; return (FALSE); } /* EH is in user buffer and we're ready to read the first data packet */ _reads[hstream].out_seq++; memcpy(packet, &_reads[hstream].eh, RF_PACKET_SIZE); return (TRUE); } /* end CreateEventHeader() */
/* printf("Face %i:\n v0: %f, %f, %f\n v1: %f, %f, %f\n" " v2: %f, %f, %f\n", i, tList[i].verts[0][0], tList[i].verts[0][1], tList[i].verts[0][2], tList[i].verts[1][0], tList[i].verts[1][1], tList[i].verts[1][2], tList[i].verts[2][0], tList[i].verts[2][1], tList[i].verts[2][2]); */ } } //========================================================================== // // Load3DS // //========================================================================== #if 0 /* 3DS stuff is unused. don't even know whether it's working */ static void Load3DS(FILE *input, triangle_t **triList, int *triangleCount) { unsigned int i, j; qboolean stop; qboolean foundVertexList; unsigned int chunkType, chunkPos, chunkSize; unsigned int editChunkSize, editChunkPos; unsigned int objectChunkSize, objectChunkPos; unsigned int meshChunkSize, meshChunkPos; unsigned int vertex; unsigned int vertexCount; struct vList_s { float v[3]; } *vList; unsigned int triCount; triangle_t *tList; InputFile = input; if (ReadShort() != _3DS_MAIN3DS) { _3DSError("Missing 3DS main chunk header.\n"); } SeekTo(16); if (ReadShort() != _3DS_EDIT3DS) { _3DSError("Missing 3DS edit chunk header.\n"); } editChunkSize = ReadLong(); editChunkPos = FilePosition()-6; stop = false; while (stop == false) { chunkPos = FilePosition(); chunkType = ReadShort(); switch (chunkType) { case _3DS_EDIT_UNKNW01: case _3DS_EDIT_UNKNW02: case _3DS_EDIT_UNKNW03: case _3DS_EDIT_UNKNW04: case _3DS_EDIT_UNKNW05: case _3DS_EDIT_UNKNW06: case _3DS_EDIT_UNKNW07: case _3DS_EDIT_UNKNW08: case _3DS_EDIT_UNKNW09: case _3DS_EDIT_UNKNW10: case _3DS_EDIT_UNKNW11: case _3DS_EDIT_UNKNW12: case _3DS_EDIT_UNKNW13: case _3DS_EDIT_MATERIAL: case _3DS_EDIT_VIEW1: case _3DS_EDIT_BACKGR: case _3DS_EDIT_AMBIENT: SeekTo(chunkPos+ReadLong()); break; case _3DS_EDIT_OBJECT: stop = true; default: break; } if (FilePosition()-editChunkPos >= editChunkSize) { _3DSError("Couldn't find OBJECT chunk.\n"); } } objectChunkSize = ReadLong(); objectChunkPos = FilePosition()-6; SkipName(); stop = false; while (stop == false) { chunkPos = FilePosition(); chunkType = ReadShort(); switch (chunkType) { case _3DS_OBJ_UNKNWN01: case _3DS_OBJ_UNKNWN02: case _3DS_OBJ_LIGHT: case _3DS_OBJ_CAMERA: SeekTo(chunkPos+ReadLong()); break; case _3DS_OBJ_TRIMESH: stop = true; default: break; } if (FilePosition()-objectChunkPos >= objectChunkSize) { _3DSError("Couldn't find TRIMESH chunk.\n"); } } meshChunkSize = ReadLong(); meshChunkPos = FilePosition()-6; stop = false; foundVertexList = false; while (stop == false) { chunkPos = FilePosition(); chunkType = ReadShort(); switch (chunkType) { case _3DS_TRI_FACEL2: case _3DS_TRI_VISIBLE: SeekTo(chunkPos+ReadLong()); break; case _3DS_TRI_VERTEXL: chunkSize = ReadLong(); vertexCount = ReadShort(); vList = (struct vList_s *) SafeMalloc(vertexCount * sizeof(vList[0])); for (i = 0; i < vertexCount; i++) { vList[i].v[0] = ReadFloat(); vList[i].v[1] = -ReadFloat(); vList[i].v[2] = ReadFloat(); } SeekTo(chunkPos+chunkSize); foundVertexList = true; break; case _3DS_TRI_FACEL1: chunkSize = ReadLong(); triCount = ReadShort(); if (triCount >= MAXTRIANGLES) { COM_Error("Too many triangles in file %s\n", InputFileName); } *triangleCount = triCount; tList = (triangle_t *) SafeMalloc(MAXTRIANGLES * sizeof(triangle_t)); *triList = tList; for (i = 0; i < triCount; i++) { for (j = 0; j < 3; j++) { vertex = ReadShort(); tList[i].verts[j][0] = vList[vertex].v[0]; tList[i].verts[j][1] = vList[vertex].v[1]; tList[i].verts[j][2] = vList[vertex].v[2]; } ReadShort(); // Skip face flags } stop = true; break; default: break; } if (FilePosition()-meshChunkPos >= meshChunkSize) { if (foundVertexList == false) { _3DSError("Couldn't find TRI_VERTEXL chunk.\n"); } else { _3DSError("Couldn't find TRI_FACEL1 chunk.\n"); } } } }