xoreos  0.0.5
cdpth.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include <cstring>
26 
27 #include "src/common/util.h"
28 #include "src/common/scopedptr.h"
29 #include "src/common/ptrvector.h"
30 #include "src/common/error.h"
31 #include "src/common/readstream.h"
32 
33 #include "src/aurora/cdpth.h"
34 #include "src/aurora/smallfile.h"
35 
36 namespace Aurora {
37 
39 
40 struct ReadContext {
42 
44 
47 
49 
51  cdpth(&c), width(w), height(h) {
52  }
53 };
54 
55 static void loadCDPTH(ReadContext &ctx);
56 static void readCells(ReadContext &ctx);
57 static void checkConsistency(ReadContext &ctx);
58 static void createDepth(ReadContext &ctx);
59 
61  ReadContext ctx(cdpth, width, height);
62 
63  try {
64  if ((ctx.width == 0) || (ctx.width >= 0x8000) || (ctx.height == 0) || (ctx.height >= 0x8000))
65  throw Common::Exception("Invalid dimensions of %ux%u", ctx.width, ctx.height);
66 
67  if (((ctx.width % 64) != 0) || ((ctx.height % 64) != 0))
68  throw Common::Exception("Dimensions need to be divisible by 64");
69 
70  loadCDPTH(ctx);
71  } catch (Common::Exception &e) {
72  e.add("Failed reading CDPTH file");
73  throw;
74  }
75 
76  return ctx.depth.release();
77 }
78 
81 
82  assert(stream);
83  return load(*stream, width, height);
84 }
85 
86 static void loadCDPTH(ReadContext &ctx) {
87  readCells(ctx);
88  checkConsistency(ctx);
89  createDepth(ctx);
90 }
91 
92 static void readCells(ReadContext &ctx) {
93  /* Read the cell data, each containing 64x64 pixels. Of course, since this
94  * is a *compressed* format, the data is compressed using the LZSS algorithm
95  * also used for .small files. */
96 
97  ctx.cells.reserve(4096);
98 
99  try {
100  // Read the cell offset and sizes
101  for (size_t i = 0; i < 4096; i++) {
102  const uint32 size = ctx.cdpth->readUint16LE();
103  const uint32 offset = ctx.cdpth->readUint16LE() * 512;
104 
105  if (offset < 0x4000)
106  break;
107 
108  ctx.cells.push_back(0);
109  if (size == 0)
110  continue;
111 
112  const size_t pos = ctx.cdpth->pos();
113 
114  Common::SeekableSubReadStream cellData(ctx.cdpth, offset, offset + size);
115  ctx.cells.back() = Aurora::Small::decompress(cellData);
116 
117  if (ctx.cells.back()->size() != 8192)
118  throw Common::Exception("Invalid size for cell %u: %u", (uint)i, (uint)ctx.cells.back()->size());
119 
120  ctx.cdpth->seek(pos);
121  }
122 
123  if (ctx.cells.empty())
124  throw Common::Exception("No cells");
125 
126  } catch (Common::Exception &e) {
127  e.add("Failed reading CDPTH file");
128  throw e;
129  }
130 }
131 
132 static void checkConsistency(ReadContext &ctx) {
133  if (((ctx.width / 64) * (ctx.height / 64)) != ctx.cells.size())
134  throw Common::Exception("%u cells for an image of %ux%u", (uint)ctx.cells.size(), ctx.width, ctx.height);
135 }
136 
137 static void createDepth(ReadContext &ctx) {
138  /* Create the actual depth data, which is made up of 64x64 pixel cells. */
139 
140  ctx.depth.reset(new uint16[ctx.width * ctx.height]);
141  std::memset(ctx.depth.get(), 0xFF, ctx.width * ctx.height * sizeof(uint16));
142 
143  const uint32 cellWidth = 64;
144  const uint32 cellHeight = 64;
145  const uint32 cellsX = ctx.width / cellWidth;
146 
147  uint16 *data = ctx.depth.get();
148  for (size_t i = 0; i < ctx.cells.size(); i++) {
149  Common::SeekableReadStream *cell = ctx.cells[i];
150  if (!cell)
151  continue;
152 
153  const uint32 xC = i % cellsX;
154  const uint32 yC = i / cellsX;
155 
156  // Pixel position of this cell within the big image
157  const uint32 imagePos = yC * cellHeight * ctx.width + xC * cellWidth;
158 
159  for (uint32 y = 0; y < cellHeight; y++) {
160  for (uint32 x = 0; x < cellWidth; x++) {
161  const uint32 pos = imagePos + y * ctx.width + x;
162  const uint16 pixel = cell->readUint16LE();
163 
164  if (pos > (ctx.width * ctx.height))
165  continue;
166 
167  data[pos] = pixel;
168  }
169  }
170  }
171 }
172 
173 } // End of namespace Aurora
static void readCells(ReadContext &ctx)
Definition: cdpth.cpp:92
static const uint16 * load(Common::SeekableReadStream &cdpth, uint32 width, uint32 height)
Read a CDPTH out of this stream.
Definition: cdpth.cpp:60
uint16 readUint16LE()
Read an unsigned 16-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:122
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
static void decompress(Common::ReadStream &small, Common::WriteStream &out)
Definition: smallfile.cpp:255
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
PointerType release()
Returns the plain pointer value and releases ScopedPtr.
Definition: scopedptr.h:103
Common::SeekableReadStream * cdpth
Definition: cdpth.cpp:41
Common::PtrVector< Common::SeekableReadStream > Cells
Definition: cdpth.cpp:38
static void checkConsistency(ReadContext &ctx)
Definition: cdpth.cpp:132
Exception that provides a stack of explanations.
Definition: error.h:36
A simple scoped smart pointer template.
Basic exceptions to throw.
Common::ScopedArray< uint16 > depth
Definition: cdpth.cpp:48
uint16_t uint16
Definition: types.h:202
Utility templates and functions.
StackException Exception
Definition: error.h:59
A vector storing pointer to objects, with automatic deletion.
Basic reading stream interfaces.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
static void loadCDPTH(ReadContext &ctx)
Definition: cdpth.cpp:86
Compressed DePTH, found in Sonic, holding image depth values.
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
Decompressing "small" files, Nintendo DS LZSS (types 0x00 and 0x10), found in Sonic.
uint32_t uint32
Definition: types.h:204
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Definition: readstream.h:359
ReadContext(Common::SeekableReadStream &c, uint32 w, uint32 h)
Definition: cdpth.cpp:50
Interface for a seekable & readable data stream.
Definition: readstream.h:265
static void createDepth(ReadContext &ctx)
Definition: cdpth.cpp:137
unsigned int uint
Definition: types.h:211