5 * Created by Alyssa Milburn on Fri Jan 18 2008.
6 * Copyright (c) 2008 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
21 #include "exceptions.h"
22 #include "endianlove.h"
24 cobFile::cobFile(fs::path filepath
) {
26 file
.open(path
.native_directory_string().c_str(), std::ios::binary
);
29 throw creaturesException(std::string("couldn't open COB file \"") + path
.native_directory_string() + "\"");
31 // TODO: c1 cob support
34 if (strncmp(majic
, "cob2", 4) != 0)
35 throw creaturesException(std::string("bad magic of C2 COB file \"") + path
.native_directory_string() + "\"");
38 // TODO: catch exceptions, and free all blocks before passing it up the stack
39 cobBlock
*b
= new cobBlock(this);
42 file
.peek(); // make sure eof() gets set
47 for (std::vector
<cobBlock
*>::iterator i
= blocks
.begin(); i
!= blocks
.end(); i
++) {
52 cobBlock::cobBlock(cobFile
*p
) {
53 std::istream
&file
= p
->getStream();
56 file
.read(cobtype
, 4);
57 type
= std::string(cobtype
, 4);
59 file
.read((char *)&size
, 4); size
= swapEndianLong(size
);
61 offset
= file
.tellg();
62 file
.seekg(size
, std::ios::cur
);
69 cobBlock::~cobBlock() {
74 void cobBlock::load() {
76 std::istream
&file
= parent
->getStream();
81 throw creaturesException("Failed to seek to block offset.");
85 buffer
= new unsigned char[size
];
86 file
.read((char *)buffer
, size
);
89 throw creaturesException("Failed to read block.");
93 void cobBlock::free() {
102 // TODO: argh, isn't there a better way to do this?
103 std::string
readstring(std::istream
&file
) {
104 unsigned int i
= 0, n
= 4096;
105 char *buf
= (char *)malloc(n
);
108 file
.read(&buf
[i
], 1);
110 throw creaturesException("Failed to read string.");
112 // found null terminator
124 buf
= (char *)realloc(buf
, n
);
129 cobAgentBlock::cobAgentBlock(cobBlock
*p
) {
131 std::istream
&file
= p
->getParent()->getStream();
134 file
.seekg(p
->getOffset());
136 throw creaturesException("Failed to seek to block offset.");
138 file
.read((char *)&quantityremaining
, 2); quantityremaining
= swapEndianShort(quantityremaining
);
139 file
.read((char *)&lastusage
, 4); lastusage
= swapEndianLong(lastusage
);
140 file
.read((char *)&reuseinterval
, 4); reuseinterval
= swapEndianLong(reuseinterval
);
141 file
.read((char *)&usebyday
, 1);
142 file
.read((char *)&usebymonth
, 1);
143 file
.read((char *)&usebyyear
, 2); usebyyear
= swapEndianShort(usebyyear
);
145 file
.seekg(12, std::ios::cur
); // unused
147 name
= readstring(file
);
148 description
= readstring(file
);
149 installscript
= readstring(file
);
150 removescript
= readstring(file
);
152 unsigned short noevents
;
153 file
.read((char *)&noevents
, 2); noevents
= swapEndianShort(noevents
);
154 for (unsigned int i
= 0; i
< noevents
; i
++) {
155 scripts
.push_back(readstring(file
));
158 unsigned short nodeps
;
159 file
.read((char *)&nodeps
, 2); nodeps
= swapEndianShort(nodeps
);
160 for (unsigned int i
= 0; i
< nodeps
; i
++) {
161 unsigned short deptype
;
162 file
.read((char *)&deptype
, 2); deptype
= swapEndianShort(deptype
);
163 deptypes
.push_back(deptype
);
165 // depnames should be read as lower-case to ease comparison
166 std::string depname
= readstring(file
);
167 std::transform(depname
.begin(), depname
.end(), depname
.begin(), (int(*)(int))tolower
);
168 depnames
.push_back(depname
);
171 file
.read((char *)&thumbnailwidth
, 2); thumbnailwidth
= swapEndianShort(thumbnailwidth
);
172 file
.read((char *)&thumbnailheight
, 2); thumbnailheight
= swapEndianShort(thumbnailheight
);
173 thumbnail
= new unsigned short[thumbnailwidth
* thumbnailheight
];
174 file
.read((char *)thumbnail
, 2 * thumbnailwidth
* thumbnailheight
);
177 cobAgentBlock::~cobAgentBlock() {
181 cobFileBlock::cobFileBlock(cobBlock
*p
) {
183 std::istream
&file
= p
->getParent()->getStream();
186 file
.seekg(p
->getOffset());
188 throw creaturesException("Failed to seek to block offset.");
190 file
.read((char *)&filetype
, 2); filetype
= swapEndianShort(filetype
);
191 file
.seekg(4, std::ios::cur
); // unused
192 file
.read((char *)&filesize
, 4); filesize
= swapEndianLong(filesize
);
194 // filenames should be read as lower-case to ease comparison
195 filename
= readstring(file
);
196 std::transform(filename
.begin(), filename
.end(), filename
.begin(), (int(*)(int))tolower
);
199 cobFileBlock::~cobFileBlock() {
202 unsigned char *cobFileBlock::getFileContents() {
203 if (!parent
->isLoaded())
206 return parent
->getBuffer() + 10 + filename
.size() + 1;