22 #ifndef SCI_ENGINE_SEGMENT_H 23 #define SCI_ENGINE_SEGMENT_H 25 #include "common/serializer.h" 26 #include "common/str.h" 27 #include "sci/engine/object.h" 28 #include "sci/engine/vm.h" 29 #include "sci/engine/vm_types.h" 32 #include "sci/graphics/palette32.h" 54 SegmentRef() : isRaw(true), raw(0), maxSize(0), skipByte(false) {}
56 bool isValid()
const {
return (isRaw ? raw != 0 : reg != 0); }
86 static SegmentObj *createSegmentObj(SegmentType type);
92 inline SegmentType getType()
const {
return _type; }
98 virtual bool isValidOffset(uint32 offset)
const = 0;
155 return offset < _locals.
size() * 2;
177 return offset < _capacity * 2;
181 return make_reg(addr.getSegment(), 0);
219 List() : first(NULL_REG), last(NULL_REG) {
221 memset(nextNodes, 0,
sizeof(nextNodes));
235 typedef T value_type;
240 enum { HEAPENTRY_INVALID = -1 };
242 int first_free = HEAPENTRY_INVALID;
243 int entries_used = 0;
253 for (uint i = 0; i < _table.
size(); i++) {
254 if (isValidEntry(i)) {
262 if (first_free != HEAPENTRY_INVALID) {
263 int oldff = first_free;
264 first_free = _table[oldff].next_free;
266 _table[oldff].next_free = oldff;
267 assert(_table[oldff].data ==
nullptr);
268 _table[oldff].
data =
new T;
271 uint newIdx = _table.
size();
273 _table.
back().data =
new T;
274 _table[newIdx].next_free = newIdx;
280 return isValidEntry(offset);
283 bool isValidEntry(
int idx)
const {
284 return idx >= 0 && (uint)idx < _table.
size() && _table[idx].next_free == idx;
287 virtual void freeEntry(
int idx) {
288 if (idx < 0 || (uint)idx >= _table.
size())
289 ::
error(
"Table::freeEntry: Attempt to release invalid table index %d", idx);
291 _table[idx].next_free = first_free;
292 delete _table[idx].
data;
293 _table[idx].
data =
nullptr;
300 for (uint i = 0; i < _table.
size(); i++)
306 uint size()
const {
return _table.
size(); }
308 T &at(uint index) {
return *_table[index].
data; }
309 const T &at(uint index)
const {
return *_table[index].
data; }
311 T &operator[](uint index) {
return at(index); }
312 const T &operator[](uint index)
const {
return at(index); }
332 freeEntry(sub_addr.getOffset());
345 freeEntry(sub_addr.getOffset());
357 for (uint i = 0; i < _table.size(); i++) {
359 freeEntryContents(i);
363 void freeEntryContents(
int idx) {
368 void freeEntry(
int idx)
override {
369 freeEntryContents(idx);
374 freeEntry(sub_addr.getOffset());
395 return offset < _size;
399 return make_reg(addr.getSegment(), 0);
402 const reg_t r = make_reg(segId, 0);
418 kArrayTypeString = 3,
420 kArrayTypeInvalid = 5
425 kArrayTrimCenter = 2,
432 _type(kArrayTypeInvalid),
437 SciArray(
const SciArray &array) {
440 _elementSize = array._elementSize;
441 _data = malloc(_elementSize * _size);
443 memcpy(_data, array._data, _elementSize * _size);
446 SciArray &operator=(
const SciArray &array) {
453 _elementSize = array._elementSize;
454 _data = malloc(_elementSize * _size);
456 memcpy(_data, array._data, _elementSize * _size);
461 ~SciArray()
override {
464 _type = kArrayTypeInvalid;
472 SciArrayType getType()
const {
479 void setType(
const SciArrayType type) {
480 assert(_type == kArrayTypeInvalid);
482 case kArrayTypeInt16:
484 _elementSize =
sizeof(
reg_t);
486 case kArrayTypeString:
487 _elementSize =
sizeof(char);
490 _elementSize =
sizeof(byte);
493 error(
"Invalid array type %d", type);
501 uint16 size()
const {
508 uint16 byteSize()
const {
509 uint16 size1 = _size;
510 if (_type == kArrayTypeID || _type == kArrayTypeInt16) {
511 size1 *=
sizeof(uint16);
521 void resize(uint16 newSize,
const bool force =
false) {
522 if (force || newSize > _size) {
523 _data = realloc(_data, _elementSize * newSize);
524 if (newSize > _size) {
525 memset((byte *)_data + _elementSize * _size, 0, (newSize - _size) * _elementSize);
534 void *getRawData() {
return _data; }
535 const void *getRawData()
const {
return _data; }
540 reg_t getAsID(
const uint16 index) {
541 if (getSciVersion() >= SCI_VERSION_3) {
551 assert(index < _size);
555 case kArrayTypeInt16:
557 return ((
reg_t *)_data)[index];
559 case kArrayTypeString: {
562 if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
563 value = ((int8 *)_data)[index];
565 value = ((uint8 *)_data)[index];
568 return make_reg(0, value);
571 error(
"Invalid array type %d", _type);
578 void setFromID(
const uint16 index,
const reg_t value) {
579 if (getSciVersion() >= SCI_VERSION_3) {
583 assert(index < _size);
587 case kArrayTypeInt16:
589 ((
reg_t *)_data)[index] = value;
592 case kArrayTypeString:
593 ((byte *)_data)[index] = value.toSint16();
596 error(
"Invalid array type %d", _type);
603 int16 getAsInt16(
const uint16 index) {
604 assert(_type == kArrayTypeInt16);
606 if (getSciVersion() >= SCI_VERSION_3) {
610 assert(index < _size);
614 assert(value.isNumber());
615 return value.toSint16();
621 void setFromInt16(
const uint16 index,
const int16 value) {
622 assert(_type == kArrayTypeInt16);
624 if (getSciVersion() >= SCI_VERSION_3) {
628 assert(index < _size);
631 ((
reg_t *)_data)[index] = make_reg(0, value);
638 byte &byteAt(
const uint16 index) {
639 assert(_type == kArrayTypeString || _type == kArrayTypeByte);
641 if (getSciVersion() >= SCI_VERSION_3) {
645 assert(index < _size);
648 return ((byte *)_data)[index];
655 char &charAt(
const uint16 index) {
656 assert(_type == kArrayTypeString || _type == kArrayTypeByte);
658 if (getSciVersion() >= SCI_VERSION_3) {
662 assert(index < _size);
665 return ((
char *)_data)[index];
672 reg_t &IDAt(
const uint16 index) {
673 assert(_type == kArrayTypeID || _type == kArrayTypeInt16);
675 if (getSciVersion() >= SCI_VERSION_3) {
679 assert(index < _size);
682 return ((
reg_t *)_data)[index];
689 void setElements(
const uint16 index, uint16 count,
const reg_t *values) {
690 resize(index + count);
693 case kArrayTypeInt16:
695 const reg_t *source = values;
698 *target++ = *source++;
703 case kArrayTypeString: {
704 const reg_t *source = values;
705 byte *target = (byte *)_data + index;
707 if (!source->isNumber()) {
708 error(
"Non-number %04x:%04x sent to byte or string array", PRINT_REG(*source));
710 *target++ = source->getOffset();
716 error(
"Attempted write to SciArray with invalid type %d", _type);
724 void fill(
const uint16 index, uint16 count,
const reg_t value) {
725 if (count == 65535 ) {
726 count = size() - index;
733 resize(index + count);
736 case kArrayTypeInt16:
745 case kArrayTypeString: {
746 byte *target = (byte *)_data + index;
747 const byte fillValue = value.getOffset();
749 *target++ = fillValue;
754 case kArrayTypeInvalid:
756 error(
"Attempted write to uninitialized SciArray");
765 void copy(SciArray &source,
const uint16 sourceIndex,
const uint16 targetIndex, int16 count) {
767 count = source.size() - sourceIndex;
774 resize(targetIndex + count);
775 source.resize(sourceIndex + count);
777 assert(source._elementSize == _elementSize);
779 const byte *sourceData = (byte *)source._data + sourceIndex * source._elementSize;
780 byte *targetData = (byte *)_data + targetIndex * _elementSize;
781 memmove(targetData, sourceData, count * _elementSize);
784 void byteCopy(
const SciArray &source,
const uint16 sourceOffset,
const uint16 targetOffset,
const uint16 count) {
785 error(
"SciArray::byteCopy not implemented");
791 void trim(
const int8 flags,
const char showChar) {
793 kWhitespaceBoundary = 32,
797 byte *data = (byte *)_data;
798 byte *end = data + _size;
802 if (flags & kArrayTrimLeft) {
805 while (source < end && *source !=
'\0' && *source != showChar && *source <= kWhitespaceBoundary) {
808 memmove(target, source,
Common::strnlen((
char *)source, _size - 1) + 1);
811 if (flags & kArrayTrimRight) {
813 while (source > data && *source != showChar && *source <= kWhitespaceBoundary) {
819 if (flags & kArrayTrimCenter) {
821 while (target < end && *target !=
'\0' && *target <= kWhitespaceBoundary && *target != showChar) {
825 if (*target !=
'\0') {
826 while (target < end && *target !=
'\0' && (*target > kWhitespaceBoundary || *target == showChar)) {
830 if (*target !=
'\0') {
832 while (*source !=
'\0') {
833 while (source < end && *source !=
'\0' && *source <= kWhitespaceBoundary && *source != showChar) {
837 while (source < end && *source !=
'\0' && (*source > kWhitespaceBoundary || *source == showChar)) {
838 *target++ = *source++;
843 while (source >= data && source > target && (*source <= kWhitespaceBoundary || *source >= kAsciiBoundary) && *source != showChar) {
848 memmove(target, source,
Common::strnlen((
char *)source, _size - 1) + 1);
858 assert(_type == kArrayTypeString);
867 assert(_type == kArrayTypeString || _type == kArrayTypeByte);
868 resize(
string.size() + 1,
true);
881 case kArrayTypeInt16:
884 case kArrayTypeString:
887 case kArrayTypeInvalid:
916 kDefaultSkipColor = 250
919 #define BITMAP_PROPERTY(size, property, offset)\ 920 inline uint##size get##property() const {\ 921 return READ_SCI11ENDIAN_UINT##size(_data + (offset));\ 923 inline void set##property(uint##size value) {\ 924 WRITE_SCI11ENDIAN_UINT##size(_data + (offset), (value));\ 948 static inline uint16 getBitmapHeaderSize() {
971 static inline uint32 getBitmapSize(
const uint16 width,
const uint16 height) {
972 return width * height + getBitmapHeaderSize();
975 inline SciBitmap() : _data(
nullptr), _dataSize(0), _gc(
true) {}
977 inline SciBitmap(
const SciBitmap &other) {
978 _dataSize = other._dataSize;
979 _data = (byte *)malloc(other._dataSize);
980 memcpy(_data, other._data, other._dataSize);
987 inline ~SciBitmap()
override {
993 inline SciBitmap &operator=(
const SciBitmap &other) {
994 if (
this == &other) {
999 _dataSize = other._dataSize;
1000 _data = (byte *)malloc(other._dataSize);
1001 memcpy(_data, other._data, _dataSize);
1013 inline void create(
const int16 width,
const int16 height,
const uint8 skipColor,
const int16 originX,
const int16 originY,
const int16 xResolution,
const int16 yResolution,
const uint32 paletteSize,
const bool remap,
const bool gc) {
1015 _dataSize = getBitmapSize(width, height) + paletteSize;
1016 _data = (byte *)realloc(_data, _dataSize);
1019 const uint16 bitmapHeaderSize = getBitmapHeaderSize();
1024 setSkipColor(skipColor);
1026 WRITE_SCI11ENDIAN_UINT16(_data + 10, 0);
1028 setDataSize(width * height);
1029 WRITE_SCI11ENDIAN_UINT32(_data + 16, 0);
1030 setHunkPaletteOffset(paletteSize > 0 ? (bitmapHeaderSize + width * height) : 0);
1031 setDataOffset(bitmapHeaderSize);
1032 setUncompressedDataOffset(bitmapHeaderSize);
1033 setControlOffset(0);
1034 setXResolution(xResolution);
1035 setYResolution(yResolution);
1040 inline int getRawSize()
const {
1044 inline byte *getRawData()
const {
1048 inline Buffer &getBuffer() {
1052 inline bool getShouldGC()
const {
1056 inline void enableGC() {
1060 inline void disableGC() {
1064 BITMAP_PROPERTY(16, Width, 0);
1065 BITMAP_PROPERTY(16, Height, 2);
1069 (int16)READ_SCI11ENDIAN_UINT16(_data + 4),
1070 (int16)READ_SCI11ENDIAN_UINT16(_data + 6)
1075 WRITE_SCI11ENDIAN_UINT16(_data + 4, (uint16)origin.
x);
1076 WRITE_SCI11ENDIAN_UINT16(_data + 6, (uint16)origin.
y);
1079 inline uint8 getSkipColor()
const {
1083 inline void setSkipColor(
const uint8 skipColor) {
1084 _data[8] = skipColor;
1087 inline bool getRemap()
const {
1088 return READ_SCI11ENDIAN_UINT16(_data + 10) & kBitmapRemap;
1091 inline void setRemap(
const bool remap) {
1092 uint16 flags = READ_SCI11ENDIAN_UINT16(_data + 10);
1094 flags |= kBitmapRemap;
1096 flags &= ~kBitmapRemap;
1098 WRITE_SCI11ENDIAN_UINT16(_data + 10, flags);
1101 BITMAP_PROPERTY(32, DataSize, 12);
1103 BITMAP_PROPERTY(32, HunkPaletteOffset, 20);
1105 BITMAP_PROPERTY(32, DataOffset, 24);
1109 BITMAP_PROPERTY(32, UncompressedDataOffset, 28);
1112 BITMAP_PROPERTY(32, ControlOffset, 32);
1114 inline uint16 getXResolution()
const {
1115 if (getDataOffset() >= 40) {
1116 return READ_SCI11ENDIAN_UINT16(_data + 36);
1123 inline void setXResolution(uint16 xResolution) {
1124 if (getDataOffset() >= 40) {
1125 WRITE_SCI11ENDIAN_UINT16(_data + 36, xResolution);
1129 inline uint16 getYResolution()
const {
1130 if (getDataOffset() >= 40) {
1131 return READ_SCI11ENDIAN_UINT16(_data + 38);
1138 inline void setYResolution(uint16 yResolution) {
1139 if (getDataOffset() >= 40) {
1140 WRITE_SCI11ENDIAN_UINT16(_data + 38, yResolution);
1144 inline byte *getPixels() {
1145 return _data + getUncompressedDataOffset();
1148 inline byte *getHunkPalette() {
1149 if (getHunkPaletteOffset() == 0) {
1152 return _data + getHunkPaletteOffset();
1155 inline void setPalette(
const Palette &palette) {
1156 byte *paletteData = getHunkPalette();
1157 if (paletteData !=
nullptr) {
1158 SciSpan<byte> paletteSpan(paletteData, getRawSize() - getHunkPaletteOffset());
1159 HunkPalette::write(paletteSpan, palette);
1165 void applyRemap(SciArray &clut) {
1166 const int length = getWidth() * getHeight();
1167 uint8 *pixel = getPixels();
1168 for (
int i = 0; i < length; ++i) {
1169 const int16 color = clut.getAsInt16(*pixel);
1170 assert(color >= 0 && color <= 255);
1171 *pixel++ = (uint8)color;
1177 getWidth(), getHeight(),
1178 getXResolution(), getYResolution(),
1179 getOrigin().x, getOrigin().y,
1181 getRemap() ?
"remap" :
"no remap",
1182 getShouldGC() ?
"GC" :
"no GC");
1186 #undef BITMAP_PROPERTY 1194 ret.
maxSize = at(pointer.getOffset()).getRawSize();
1195 ret.raw = at(pointer.getOffset()).getRawData();
1207 #endif // SCI_ENGINE_SEGMENT_H bool skipByte
true if referencing the 2nd data byte of *reg, false otherwise
Definition: segment.h:46
bool isValidOffset(uint32 offset) const override
Definition: segment.h:154
static String format(MSVC_PRINTF const char *fmt,...) GCC_PRINTF(1
const T * data() const
Definition: array.h:210
virtual Common::Array< reg_t > listAllDeallocatable(SegmentId segId) const
Definition: segment.h:130
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: segment.h:227
Definition: segment.h:341
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:331
Definition: segment.h:354
bool isValidOffset(uint32 offset) const override
Definition: segment.h:176
Definition: segment.h:234
Definition: serializer.h:79
Definition: segment.h:382
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:373
Definition: segment.h:202
reg_t succ
Definition: segment.h:197
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:344
Definition: segment.h:317
Out copy(In first, In last, Out dst)
Definition: algorithm.h:52
virtual Common::Array< reg_t > listAllOutgoingReferences(reg_t object) const
Definition: segment.h:142
Common::Array< reg_t > listAllDeallocatable(SegmentId segId) const override
Definition: segment.h:401
bool isValidOffset(uint32 offset) const override
Definition: segment.h:279
int maxSize
number of available bytes
Definition: segment.h:43
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr)
Definition: segment.h:123
void push_back(const T &element)
Definition: array.h:183
Definition: segment.h:147
Definition: segment.h:236
Definition: segment.h:328
reg_t pred
Definition: segment.h:196
int script_id
Definition: segment.h:148
reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const override
Definition: segment.h:180
Definition: serializer.h:308
bool isRaw
true if data is raw, false if it is a reg_t sequence
Definition: segment.h:38
Common::Array< reg_t > listAllDeallocatable(SegmentId segId) const override
Definition: segment.h:298
size_type size() const
Definition: array.h:318
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: seg_manager.h:48
signed char * fill(signed char *first, signed char *last, Value val)
Definition: algorithm.h:168
reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const override
Definition: segment.h:398
Definition: display_client.h:113
size_t strnlen(const char *src, size_t maxSize)
Definition: helpers.h:247
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const
Definition: segment.h:116
Definition: segment.h:195
Definition: vm_types.h:39
Definition: segment.h:165
T & back()
Definition: array.h:232
bool isValidOffset(uint32 offset) const override
Definition: segment.h:394
uint _capacity
Definition: segment.h:166