1
0
forked from 0ad/0ad
0ad/source/tools/atlas/DatafileIO/BAR/BAR.cpp
Ykkrosh a56bd4b2c1 Add GPL header to Atlas code
This was SVN commit r6910.
2009-06-20 16:13:29 +00:00

143 lines
3.6 KiB
C++

/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "BAR.h"
#include "Util.h"
#include "Stream/Stream.h"
#include "Stream/Memory.h"
//for :25 strncmp and :81 memset
#include <string.h>
#include <cassert>
using namespace DatafileIO;
BARReader::BARReader(SeekableInputStream& stream)
: m_Stream(stream)
{
}
#define CHECK(expr) if (!(expr)) { assert(!(expr)); return false; }
bool BARReader::Initialise()
{
assert(m_FileList.size() == 0); // Only call Init once
char head[4];
m_Stream.Read(head, 4);
CHECK(strncmp(head, "ESPN", 4) == 0);
uint32_t unknown;
m_Stream.Read(&unknown, 4);
CHECK(unknown == 2);
m_Stream.Read(&unknown, 4);
CHECK(unknown == 0x44332211);
for (int i = 0; i < 66; ++i)
{
m_Stream.Read(&unknown, 4);
CHECK(unknown == 0);
}
m_Stream.Read(&unknown, 4); // TODO: checksum?
uint32_t numFiles, filetableOffset;
m_Stream.Read(&numFiles, 4);
m_Stream.Read(&filetableOffset, 4);
m_Stream.Read(&unknown, 4);
CHECK(unknown == 0);
m_Stream.Seek(filetableOffset, Stream::FROM_START);
utf16string rootName = ReadUString(m_Stream);
uint32_t numRootFiles;
m_Stream.Read(&numRootFiles, 4);
CHECK(numRootFiles == numFiles);
m_FileList.reserve(numFiles);
for (uint32_t i = 0; i < numFiles; ++i)
{
BAREntry file;
uint32_t offset, length0, length1;
m_Stream.Read(&offset, 4);
m_Stream.Read(&length0, 4);
m_Stream.Read(&length1, 4);
CHECK(length0 == length1); // ??
file.offset = offset;
file.filesize = length0;
// Ranges: 1995-2005, 1-12, 0-5, 1-31, 0+10-23, 0-59, 0-59, 0-999
m_Stream.Read(&file.modified.year, 2);
m_Stream.Read(&file.modified.month, 2);
m_Stream.Read(&file.modified.dayofweek, 2);
m_Stream.Read(&file.modified.day, 2);
m_Stream.Read(&file.modified.hour, 2);
m_Stream.Read(&file.modified.minute, 2);
m_Stream.Read(&file.modified.second, 2);
m_Stream.Read(&file.modified.msecond, 2);
if (file.modified.year == 0xCCCC) // no date specified
memset(&file.modified, 0, sizeof(file.modified));
file.filename = rootName + ReadUString(m_Stream);
m_FileList.push_back(file);
}
// TODO: check this is really EOF
return true;
}
struct buffer_releaser
{
SeekableInputStream* stream;
};
SeekableInputStream* BARReader::GetFile(const BAREntry& file) const
{
void* buffer;
size_t size;
m_Stream.Seek((off_t)file.offset, Stream::FROM_START);
m_Stream.AcquireBuffer(buffer, size, file.filesize);
return new SeekableInputStream_mem((char*)buffer, size, new SeekableInputStream_mem::Releaser_StreamBuffer(&m_Stream));
}
void BARReader::TransferFile(const BAREntry& file, OutputStream& stream) const
{
m_Stream.Seek((off_t)file.offset, Stream::FROM_START);
const size_t bufSize = 128*1024; // people
static char* buffer[bufSize];
size_t bytesLeft = file.filesize;
while (bytesLeft)
{
size_t bytesRead = m_Stream.Read(buffer, std::min(bufSize, bytesLeft));
stream.Write(buffer, bytesRead);
bytesLeft -= bytesRead;
if (bytesRead == 0)
break;
}
}