aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorColin Snover2016-07-29 15:48:14 -0500
committerColin Snover2016-08-01 10:37:14 -0500
commit2071196f4235c75ff020605f53b3d397532e841a (patch)
treeaaae025e3e221e29e7d0c2f2b9c48f4e760caf6e /engines/sci/engine
parent4e31c9aaf4aa36b6fea039d1779317e6a943e68b (diff)
downloadscummvm-rg350-2071196f4235c75ff020605f53b3d397532e841a.tar.gz
scummvm-rg350-2071196f4235c75ff020605f53b3d397532e841a.tar.bz2
scummvm-rg350-2071196f4235c75ff020605f53b3d397532e841a.zip
SCI32: Add bitmap segment and remove GC option from hunk segment
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/gc.cpp12
-rw-r--r--engines/sci/engine/kernel.cpp1
-rw-r--r--engines/sci/engine/kgraphics32.cpp17
-rw-r--r--engines/sci/engine/kscripts.cpp2
-rw-r--r--engines/sci/engine/savegame.cpp22
-rw-r--r--engines/sci/engine/savegame.h3
-rw-r--r--engines/sci/engine/seg_manager.cpp59
-rw-r--r--engines/sci/engine/seg_manager.h14
-rw-r--r--engines/sci/engine/segment.cpp14
-rw-r--r--engines/sci/engine/segment.h240
10 files changed, 363 insertions, 21 deletions
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp
index e0467e9461..ad4fd19405 100644
--- a/engines/sci/engine/gc.cpp
+++ b/engines/sci/engine/gc.cpp
@@ -154,16 +154,18 @@ AddrSet *findAllActiveReferences(EngineState *s) {
}
}
- // Init: Explicitly opted-out hunks
- else if (heap[i]->getType() == SEG_TYPE_HUNK) {
- HunkTable *ht = static_cast<HunkTable *>(heap[i]);
+#ifdef ENABLE_SCI32
+ // Init: Explicitly opted-out bitmaps
+ else if (heap[i]->getType() == SEG_TYPE_BITMAP) {
+ BitmapTable *bt = static_cast<BitmapTable *>(heap[i]);
- for (uint j = 0; j < ht->_table.size(); j++) {
- if (!ht->_table[j].data.gc) {
+ for (uint j = 0; j < bt->_table.size(); j++) {
+ if (!bt->_table[j].data.getShouldGC()) {
wm.push(make_reg(i, j));
}
}
}
+#endif
}
}
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 2afb8b73d1..d764a88a0a 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -408,6 +408,7 @@ uint16 Kernel::findRegType(reg_t reg) {
#ifdef ENABLE_SCI32
case SEG_TYPE_ARRAY:
case SEG_TYPE_STRING:
+ case SEG_TYPE_BITMAP:
#endif
result |= SIG_TYPE_REFERENCE;
break;
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 44085da6e7..e458109cc2 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -536,13 +536,14 @@ reg_t kBitmapCreate(EngineState *s, int argc, reg_t *argv) {
int16 scaledHeight = argc > 5 ? argv[5].toSint16() : g_sci->_gfxText32->_scaledHeight;
bool useRemap = argc > 6 ? argv[6].toSint16() : false;
- BitmapResource bitmap(s->_segMan, width, height, skipColor, 0, 0, scaledWidth, scaledHeight, 0, useRemap, true);
+ reg_t bitmapId;
+ SciBitmap &bitmap = *s->_segMan->allocateBitmap(&bitmapId, width, height, skipColor, 0, 0, scaledWidth, scaledHeight, 0, useRemap, true);
memset(bitmap.getPixels(), backColor, width * height);
- return bitmap.getObject();
+ return bitmapId;
}
reg_t kBitmapDestroy(EngineState *s, int argc, reg_t *argv) {
- s->_segMan->freeHunkEntry(argv[0]);
+ s->_segMan->freeBitmap(argv[0]);
return s->r_acc;
}
@@ -552,7 +553,7 @@ reg_t kBitmapDrawLine(EngineState *s, int argc, reg_t *argv) {
}
reg_t kBitmapDrawView(EngineState *s, int argc, reg_t *argv) {
- BitmapResource bitmap(argv[0]);
+ SciBitmap &bitmap = *s->_segMan->lookupBitmap(argv[0]);
CelObjView view(argv[1].toUint16(), argv[2].toSint16(), argv[3].toSint16());
const int16 x = argc > 4 ? argv[4].toSint16() : 0;
@@ -582,7 +583,7 @@ reg_t kBitmapDrawView(EngineState *s, int argc, reg_t *argv) {
reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv) {
// called e.g. from TextButton::createBitmap() in Torin's Passage, script 64894
- BitmapResource bitmap(argv[0]);
+ SciBitmap &bitmap = *s->_segMan->lookupBitmap(argv[0]);
Common::String text = s->_segMan->getString(argv[1]);
Common::Rect textRect(
argv[2].toSint16(),
@@ -609,7 +610,7 @@ reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv) {
reg_t textBitmapObject = g_sci->_gfxText32->createFontBitmap(textRect.width(), textRect.height(), Common::Rect(textRect.width(), textRect.height()), text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, false, false);
CelObjMem textCel(textBitmapObject);
textCel.draw(bitmap.getBuffer(), textRect, Common::Point(textRect.left, textRect.top), false);
- s->_segMan->freeHunkEntry(textBitmapObject);
+ s->_segMan->freeBitmap(textBitmapObject);
return s->r_acc;
}
@@ -617,7 +618,7 @@ reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv) {
reg_t kBitmapDrawColor(EngineState *s, int argc, reg_t *argv) {
// called e.g. from TextView::init() and TextView::draw() in Torin's Passage, script 64890
- BitmapResource bitmap(argv[0]);
+ SciBitmap &bitmap = *s->_segMan->lookupBitmap(argv[0]);
Common::Rect fillRect(
argv[1].toSint16(),
argv[2].toSint16(),
@@ -642,7 +643,7 @@ reg_t kBitmapInvert(EngineState *s, int argc, reg_t *argv) {
}
reg_t kBitmapSetDisplace(EngineState *s, int argc, reg_t *argv) {
- BitmapResource bitmap(argv[0]);
+ SciBitmap &bitmap = *s->_segMan->lookupBitmap(argv[0]);
bitmap.setDisplace(Common::Point(argv[1].toSint16(), argv[2].toSint16()));
return s->r_acc;
}
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index 42e7a2028f..6fd130bceb 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -40,7 +40,7 @@ reg_t kLoad(EngineState *s, int argc, reg_t *argv) {
// Request to dynamically allocate hunk memory for later use
if (restype == kResourceTypeMemory)
- return s->_segMan->allocateHunkEntry("kLoad()", resnr, true);
+ return s->_segMan->allocateHunkEntry("kLoad()", resnr);
return make_reg(0, ((restype << 11) | resnr)); // Return the resource identifier as handle
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 31fb848a2c..f49853de2f 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -158,6 +158,18 @@ void syncWithSerializer(Common::Serializer &s, SciString &obj) {
obj.setValue(i, value);
}
}
+
+void syncWithSerializer(Common::Serializer &s, SciBitmap &obj) {
+ debug("TODO: Sync bitmap");
+
+// if (s.isSaving()) {
+// size = obj.getSize();
+// s.syncAsUint32LE(size);
+// } else {
+// s.syncAsUint32LE(size);
+// obj.setSize(size);
+// }
+}
#endif
#pragma mark -
@@ -273,6 +285,8 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
} else if (type == SEG_TYPE_STRING) {
// Set the correct segment for SCI32 strings
_stringSegId = i;
+ } else if (s.getVersion() >= 36 && type == SEG_TYPE_BITMAP) {
+ _bitmapSegId = i;
#endif
}
@@ -687,6 +701,14 @@ void StringTable::saveLoadWithSerializer(Common::Serializer &ser) {
sync_Table<StringTable>(ser, *this);
}
+
+void BitmapTable::saveLoadWithSerializer(Common::Serializer &ser) {
+ if (ser.getVersion() < 36)
+ return;
+
+ // TODO: Should only include bitmaps with gc = true
+ sync_Table(ser, *this);
+}
#endif
void GfxPalette::palVarySaveLoadPalette(Common::Serializer &s, Palette *palette) {
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index 43909accf2..c5c2bcef08 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -37,6 +37,7 @@ struct EngineState;
*
* Version - new/changed feature
* =============================
+ * 36 - SCI32 bitmap segment
* 35 - SCI32 remap
* 34 - SCI32 palettes, and store play time in ticks
* 33 - new overridePriority flag in MusicEntry
@@ -60,7 +61,7 @@ struct EngineState;
*/
enum {
- CURRENT_SAVEGAME_VERSION = 35,
+ CURRENT_SAVEGAME_VERSION = 36,
MINIMUM_SAVEGAME_VERSION = 14
};
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index e6692060b6..67da4c847d 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -43,6 +43,7 @@ SegManager::SegManager(ResourceManager *resMan, ScriptPatcher *scriptPatcher)
#ifdef ENABLE_SCI32
_arraysSegId = 0;
_stringSegId = 0;
+ _bitmapSegId = 0;
#endif
createClassTable();
@@ -72,6 +73,7 @@ void SegManager::resetSegMan() {
#ifdef ENABLE_SCI32
_arraysSegId = 0;
_stringSegId = 0;
+ _bitmapSegId = 0;
#endif
// Reinitialize class table
@@ -393,7 +395,7 @@ void SegManager::freeHunkEntry(reg_t addr) {
ht->freeEntryContents(addr.getOffset());
}
-reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size, bool gc) {
+reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) {
HunkTable *table;
int offset;
@@ -412,7 +414,6 @@ reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size, bool gc) {
h->mem = malloc(size);
h->size = size;
h->type = hunk_type;
- h->gc = gc;
return addr;
}
@@ -942,6 +943,60 @@ void SegManager::freeString(reg_t addr) {
stringTable.freeEntry(addr.getOffset());
}
+#pragma mark -
+#pragma mark Bitmaps
+
+SciBitmap *SegManager::allocateBitmap(reg_t *addr, const int16 width, const int16 height, const uint8 skipColor, const int16 displaceX, const int16 displaceY, const int16 scaledWidth, const int16 scaledHeight, const uint32 paletteSize, const bool remap, const bool gc) {
+ BitmapTable *table;
+ int offset;
+
+ if (!_bitmapSegId) {
+ table = (BitmapTable *)allocSegment(new BitmapTable(), &(_bitmapSegId));
+ } else {
+ table = (BitmapTable *)_heap[_bitmapSegId];
+ }
+
+ offset = table->allocEntry();
+
+ *addr = make_reg(_bitmapSegId, offset);
+ SciBitmap *bitmap = &table->at(offset);
+
+ if (bitmap == nullptr) {
+ *addr = NULL_REG;
+ }
+
+ bitmap->create(width, height, skipColor, displaceX, displaceY, scaledWidth, scaledHeight, paletteSize, remap, gc);
+
+ return bitmap;
+}
+
+SciBitmap *SegManager::lookupBitmap(const reg_t addr) {
+ if (_heap[addr.getSegment()]->getType() != SEG_TYPE_BITMAP)
+ error("Attempt to use non-bitmap %04x:%04x as bitmap", PRINT_REG(addr));
+
+ BitmapTable &bitmapTable = *(BitmapTable *)_heap[addr.getSegment()];
+
+ if (!bitmapTable.isValidEntry(addr.getOffset()))
+ error("Attempt to use non-bitmap %04x:%04x as bitmap", PRINT_REG(addr));
+
+ return &(bitmapTable.at(addr.getOffset()));
+}
+
+void SegManager::freeBitmap(const reg_t addr) {
+ if (_heap[addr.getSegment()]->getType() != SEG_TYPE_BITMAP)
+ error("Attempt to use non-bitmap %04x:%04x as bitmap", PRINT_REG(addr));
+
+ BitmapTable &bitmapTable = *(BitmapTable *)_heap[addr.getSegment()];
+
+ if (!bitmapTable.isValidEntry(addr.getOffset()))
+ error("Attempt to use non-bitmap %04x:%04x as bitmap", PRINT_REG(addr));
+
+ bitmapTable.at(addr.getOffset()).destroy();
+ bitmapTable.freeEntry(addr.getOffset());
+}
+
+#pragma mark -
+
#endif
void SegManager::createClassTable() {
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index ba2ba33a6a..acebecea97 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -29,6 +29,10 @@
#include "sci/engine/vm.h"
#include "sci/engine/vm_types.h"
#include "sci/engine/segment.h"
+#ifdef ENABLE_SCI32
+// TODO: Baaaad?
+#include "sci/graphics/celobj32.h"
+#endif
namespace Sci {
@@ -225,11 +229,9 @@ public:
* @param[in] size Number of bytes to allocate for the hunk entry
* @param[in] hunk_type A descriptive string for the hunk entry, for
* debugging purposes
- * @param[in] gc Whether to make the hunk eligible for garbage
- * collection
* @return The offset of the freshly allocated hunk entry
*/
- reg_t allocateHunkEntry(const char *hunk_type, int size, bool gc);
+ reg_t allocateHunkEntry(const char *hunk_type, int size);
/**
* Deallocates a hunk entry
@@ -435,10 +437,15 @@ public:
SciArray<reg_t> *allocateArray(reg_t *addr);
SciArray<reg_t> *lookupArray(reg_t addr);
void freeArray(reg_t addr);
+
SciString *allocateString(reg_t *addr);
SciString *lookupString(reg_t addr);
void freeString(reg_t addr);
SegmentId getStringSegmentId() { return _stringSegId; }
+
+ SciBitmap *allocateBitmap(reg_t *addr, const int16 width, const int16 height, const uint8 skipColor = kDefaultSkipColor, const int16 displaceX = 0, const int16 displaceY = 0, const int16 scaledWidth = kLowResX, const int16 scaledHeight = kLowResY, const uint32 paletteSize = 0, const bool remap = false, const bool gc = true);
+ SciBitmap *lookupBitmap(reg_t addr);
+ void freeBitmap(reg_t addr);
#endif
const Common::Array<SegmentObj *> &getSegments() const { return _heap; }
@@ -464,6 +471,7 @@ private:
#ifdef ENABLE_SCI32
SegmentId _arraysSegId;
SegmentId _stringSegId;
+ SegmentId _bitmapSegId;
#endif
public:
diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp
index 2cff799f4b..7f690cb7c4 100644
--- a/engines/sci/engine/segment.cpp
+++ b/engines/sci/engine/segment.cpp
@@ -70,6 +70,9 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
case SEG_TYPE_STRING:
mem = new StringTable();
break;
+ case SEG_TYPE_BITMAP:
+ mem = new BitmapTable();
+ break;
#endif
default:
error("Unknown SegmentObj type %d", type);
@@ -310,6 +313,17 @@ SegmentRef StringTable::dereference(reg_t pointer) {
return ret;
}
+#pragma mark -
+#pragma mark Bitmaps
+
+SegmentRef BitmapTable::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = true;
+ ret.maxSize = at(pointer.getOffset()).getRawSize();
+ ret.raw = at(pointer.getOffset()).getRawData();
+ return ret;
+}
+
#endif
} // End of namespace Sci
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 6c94c24ff9..c25ede1d6a 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -71,6 +71,7 @@ enum SegmentType {
#ifdef ENABLE_SCI32
SEG_TYPE_ARRAY = 11,
SEG_TYPE_STRING = 12,
+ SEG_TYPE_BITMAP = 13,
#endif
SEG_TYPE_MAX // For sanity checking
@@ -205,7 +206,6 @@ struct Hunk {
void *mem;
uint32 size;
const char *type;
- bool gc;
};
template<typename T>
@@ -520,6 +520,244 @@ struct StringTable : public SegmentObjTable<SciString> {
SegmentRef dereference(reg_t pointer);
};
+#pragma mark -
+#pragma mark Bitmaps
+
+enum {
+ kDefaultSkipColor = 250
+};
+
+#define BITMAP_PROPERTY(size, property, offset)\
+inline uint##size get##property() const {\
+ return READ_SCI11ENDIAN_UINT##size(_data + (offset));\
+}\
+inline void set##property(uint##size value) {\
+ WRITE_SCI11ENDIAN_UINT##size(_data + (offset), (value));\
+}
+
+/**
+ * A convenience class for creating and modifying in-memory
+ * bitmaps.
+ */
+class SciBitmap {
+ byte *_data;
+ int _dataSize;
+ Buffer _buffer;
+ bool _gc;
+
+public:
+ enum BitmapFlags {
+ kBitmapRemap = 2
+ };
+
+ /**
+ * Gets the size of the bitmap header for the current
+ * engine version.
+ */
+ static inline uint16 getBitmapHeaderSize() {
+ // TODO: These values are accurate for each engine, but there may be no reason
+ // to not simply just always use size 40, since SCI2.1mid does not seem to
+ // actually store any data above byte 40, and SCI2 did not allow bitmaps with
+ // scaling resolutions other than the default (320x200). Perhaps SCI3 used
+ // the extra bytes, or there is some reason why they tried to align the header
+ // size with other headers like pic headers?
+// uint32 bitmapHeaderSize;
+// if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) {
+// bitmapHeaderSize = 46;
+// } else if (getSciVersion() == SCI_VERSION_2_1_EARLY) {
+// bitmapHeaderSize = 40;
+// } else {
+// bitmapHeaderSize = 36;
+// }
+// return bitmapHeaderSize;
+ return 46;
+ }
+
+ /**
+ * Gets the byte size of a bitmap with the given width
+ * and height.
+ */
+ static inline uint32 getBitmapSize(const uint16 width, const uint16 height) {
+ return width * height + getBitmapHeaderSize();
+ }
+
+ inline SciBitmap() : _data(nullptr), _dataSize(0), _gc(true) {}
+
+ /**
+ * Allocates and initialises a new bitmap.
+ */
+ inline void create(const int16 width, const int16 height, const uint8 skipColor, const int16 displaceX, const int16 displaceY, const int16 scaledWidth, const int16 scaledHeight, const uint32 paletteSize, const bool remap, const bool gc) {
+
+ _dataSize = getBitmapSize(width, height) + paletteSize;
+ _data = (byte *)realloc(_data, _dataSize);
+ _gc = gc;
+
+ const uint16 bitmapHeaderSize = getBitmapHeaderSize();
+
+ setWidth(width);
+ setHeight(height);
+ setDisplace(Common::Point(displaceX, displaceY));
+ setSkipColor(skipColor);
+ _data[9] = 0;
+ WRITE_SCI11ENDIAN_UINT16(_data + 10, 0);
+ setRemap(remap);
+ setDataSize(width * height);
+ WRITE_SCI11ENDIAN_UINT32(_data + 16, 0);
+ setHunkPaletteOffset(paletteSize > 0 ? (width * height) : 0);
+ setDataOffset(bitmapHeaderSize);
+ setUncompressedDataOffset(bitmapHeaderSize);
+ setControlOffset(0);
+ setScaledWidth(scaledWidth);
+ setScaledHeight(scaledHeight);
+
+ _buffer = Buffer(getWidth(), getHeight(), getPixels());
+ }
+
+ inline void destroy() {
+ free(_data);
+ _data = nullptr;
+ _dataSize = 0;
+ }
+
+ inline int getRawSize() const {
+ return _dataSize;
+ }
+
+ inline byte *getRawData() const {
+ return _data;
+ }
+
+ inline Buffer &getBuffer() {
+ return _buffer;
+ }
+
+ inline bool getShouldGC() const {
+ return _gc;
+ }
+
+ inline void enableGC() {
+ _gc = true;
+ }
+
+ inline void disableGC() {
+ _gc = false;
+ }
+
+ BITMAP_PROPERTY(16, Width, 0);
+ BITMAP_PROPERTY(16, Height, 2);
+
+ inline Common::Point getDisplace() const {
+ return Common::Point(
+ (int16)READ_SCI11ENDIAN_UINT16(_data + 4),
+ (int16)READ_SCI11ENDIAN_UINT16(_data + 6)
+ );
+ }
+
+ inline void setDisplace(const Common::Point &displace) {
+ WRITE_SCI11ENDIAN_UINT16(_data + 4, (uint16)displace.x);
+ WRITE_SCI11ENDIAN_UINT16(_data + 6, (uint16)displace.y);
+ }
+
+ inline uint8 getSkipColor() const {
+ return _data[8];
+ }
+
+ inline void setSkipColor(const uint8 skipColor) {
+ _data[8] = skipColor;
+ }
+
+ inline bool getRemap() const {
+ return READ_SCI11ENDIAN_UINT16(_data + 10) & kBitmapRemap;
+ }
+
+ inline void setRemap(const bool remap) {
+ uint16 flags = READ_SCI11ENDIAN_UINT16(_data + 10);
+ if (remap) {
+ flags |= kBitmapRemap;
+ } else {
+ flags &= ~kBitmapRemap;
+ }
+ WRITE_SCI11ENDIAN_UINT16(_data + 10, flags);
+ }
+
+ BITMAP_PROPERTY(32, DataSize, 12);
+
+ inline uint32 getHunkPaletteOffset() const {
+ return READ_SCI11ENDIAN_UINT32(_data + 20);
+ }
+
+ inline void setHunkPaletteOffset(uint32 hunkPaletteOffset) {
+ if (hunkPaletteOffset) {
+ hunkPaletteOffset += getBitmapHeaderSize();
+ }
+
+ WRITE_SCI11ENDIAN_UINT32(_data + 20, hunkPaletteOffset);
+ }
+
+ BITMAP_PROPERTY(32, DataOffset, 24);
+
+ // NOTE: This property is used as a "magic number" for
+ // validating that a block of memory is a valid bitmap,
+ // and so is always set to the size of the header.
+ BITMAP_PROPERTY(32, UncompressedDataOffset, 28);
+
+ // NOTE: This property always seems to be zero
+ BITMAP_PROPERTY(32, ControlOffset, 32);
+
+ inline uint16 getScaledWidth() const {
+ if (getDataOffset() >= 40) {
+ return READ_SCI11ENDIAN_UINT16(_data + 36);
+ }
+
+ // SCI2 bitmaps did not have scaling ability
+ return 320;
+ }
+
+ inline void setScaledWidth(uint16 scaledWidth) {
+ if (getDataOffset() >= 40) {
+ WRITE_SCI11ENDIAN_UINT16(_data + 36, scaledWidth);
+ }
+ }
+
+ inline uint16 getScaledHeight() const {
+ if (getDataOffset() >= 40) {
+ return READ_SCI11ENDIAN_UINT16(_data + 38);
+ }
+
+ // SCI2 bitmaps did not have scaling ability
+ return 200;
+ }
+
+ inline void setScaledHeight(uint16 scaledHeight) {
+ if (getDataOffset() >= 40) {
+ WRITE_SCI11ENDIAN_UINT16(_data + 38, scaledHeight);
+ }
+ }
+
+ inline byte *getPixels() {
+ return _data + getUncompressedDataOffset();
+ }
+
+ inline byte *getHunkPalette() {
+ if (getHunkPaletteOffset() == 0) {
+ return nullptr;
+ }
+ return _data + getHunkPaletteOffset();
+ }
+};
+
+struct BitmapTable : public SegmentObjTable<SciBitmap> {
+ BitmapTable() : SegmentObjTable<SciBitmap>(SEG_TYPE_BITMAP) {}
+
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ at(sub_addr.getOffset()).destroy();
+ freeEntry(sub_addr.getOffset());
+ }
+
+ void saveLoadWithSerializer(Common::Serializer &ser);
+ SegmentRef dereference(reg_t pointer);
+};
+
#endif