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 };
254 for (uint i = 0; i < _table.
size(); i++) {
255 if (isValidEntry(i)) {
263 first_free = HEAPENTRY_INVALID;
269 if (first_free != HEAPENTRY_INVALID) {
270 int oldff = first_free;
271 first_free = _table[oldff].next_free;
273 _table[oldff].next_free = oldff;
274 assert(_table[oldff].data ==
nullptr);
275 _table[oldff].
data =
new T;
278 uint newIdx = _table.
size();
280 _table.
back().data =
new T;
281 _table[newIdx].next_free = newIdx;
287 return isValidEntry(offset);
290 bool isValidEntry(
int idx)
const {
291 return idx >= 0 && (uint)idx < _table.
size() && _table[idx].next_free == idx;
294 virtual void freeEntry(
int idx) {
295 if (idx < 0 || (uint)idx >= _table.
size())
296 ::
error(
"Table::freeEntry: Attempt to release invalid table index %d", idx);
298 _table[idx].next_free = first_free;
299 delete _table[idx].
data;
300 _table[idx].
data =
nullptr;
307 for (uint i = 0; i < _table.
size(); i++)
313 uint size()
const {
return _table.
size(); }
315 T &at(uint index) {
return *_table[index].
data; }
316 const T &at(uint index)
const {
return *_table[index].
data; }
318 T &operator[](uint index) {
return at(index); }
319 const T &operator[](uint index)
const {
return at(index); }
339 freeEntry(sub_addr.getOffset());
352 freeEntry(sub_addr.getOffset());
364 for (uint i = 0; i < _table.size(); i++) {
366 freeEntryContents(i);
370 void freeEntryContents(
int idx) {
375 void freeEntry(
int idx)
override {
376 freeEntryContents(idx);
381 freeEntry(sub_addr.getOffset());
402 return offset < _size;
406 return make_reg(addr.getSegment(), 0);
409 const reg_t r = make_reg(segId, 0);
425 kArrayTypeString = 3,
427 kArrayTypeInvalid = 5
432 kArrayTrimCenter = 2,
439 _type(kArrayTypeInvalid),
444 SciArray(
const SciArray &array) {
447 _elementSize = array._elementSize;
448 _data = malloc(_elementSize * _size);
450 memcpy(_data, array._data, _elementSize * _size);
453 SciArray &operator=(
const SciArray &array) {
460 _elementSize = array._elementSize;
461 _data = malloc(_elementSize * _size);
463 memcpy(_data, array._data, _elementSize * _size);
468 ~SciArray()
override {
471 _type = kArrayTypeInvalid;
479 SciArrayType getType()
const {
486 void setType(
const SciArrayType type) {
487 assert(_type == kArrayTypeInvalid);
489 case kArrayTypeInt16:
491 _elementSize =
sizeof(
reg_t);
493 case kArrayTypeString:
494 _elementSize =
sizeof(char);
497 _elementSize =
sizeof(byte);
500 error(
"Invalid array type %d", type);
508 uint16 size()
const {
515 uint16 byteSize()
const {
516 uint16 size1 = _size;
517 if (_type == kArrayTypeID || _type == kArrayTypeInt16) {
518 size1 *=
sizeof(uint16);
528 void resize(uint16 newSize,
const bool force =
false) {
529 if (force || newSize > _size) {
530 _data = realloc(_data, _elementSize * newSize);
531 if (newSize > _size) {
532 memset((byte *)_data + _elementSize * _size, 0, (newSize - _size) * _elementSize);
541 void *getRawData() {
return _data; }
542 const void *getRawData()
const {
return _data; }
547 reg_t getAsID(
const uint16 index) {
548 if (getSciVersion() >= SCI_VERSION_3) {
558 assert(index < _size);
562 case kArrayTypeInt16:
564 return ((
reg_t *)_data)[index];
566 case kArrayTypeString: {
569 if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
570 value = ((int8 *)_data)[index];
572 value = ((uint8 *)_data)[index];
575 return make_reg(0, value);
578 error(
"Invalid array type %d", _type);
585 void setFromID(
const uint16 index,
const reg_t value) {
586 if (getSciVersion() >= SCI_VERSION_3) {
590 assert(index < _size);
594 case kArrayTypeInt16:
596 ((
reg_t *)_data)[index] = value;
599 case kArrayTypeString:
600 ((byte *)_data)[index] = value.toSint16();
603 error(
"Invalid array type %d", _type);
610 int16 getAsInt16(
const uint16 index) {
611 assert(_type == kArrayTypeInt16);
613 if (getSciVersion() >= SCI_VERSION_3) {
617 assert(index < _size);
621 assert(value.isNumber());
622 return value.toSint16();
628 void setFromInt16(
const uint16 index,
const int16 value) {
629 assert(_type == kArrayTypeInt16);
631 if (getSciVersion() >= SCI_VERSION_3) {
635 assert(index < _size);
638 ((
reg_t *)_data)[index] = make_reg(0, value);
645 byte &byteAt(
const uint16 index) {
646 assert(_type == kArrayTypeString || _type == kArrayTypeByte);
648 if (getSciVersion() >= SCI_VERSION_3) {
652 assert(index < _size);
655 return ((byte *)_data)[index];
662 char &charAt(
const uint16 index) {
663 assert(_type == kArrayTypeString || _type == kArrayTypeByte);
665 if (getSciVersion() >= SCI_VERSION_3) {
669 assert(index < _size);
672 return ((
char *)_data)[index];
679 reg_t &IDAt(
const uint16 index) {
680 assert(_type == kArrayTypeID || _type == kArrayTypeInt16);
682 if (getSciVersion() >= SCI_VERSION_3) {
686 assert(index < _size);
689 return ((
reg_t *)_data)[index];
696 void setElements(
const uint16 index, uint16 count,
const reg_t *values) {
697 resize(index + count);
700 case kArrayTypeInt16:
702 const reg_t *source = values;
705 *target++ = *source++;
710 case kArrayTypeString: {
711 const reg_t *source = values;
712 byte *target = (byte *)_data + index;
714 if (!source->isNumber()) {
715 error(
"Non-number %04x:%04x sent to byte or string array", PRINT_REG(*source));
717 *target++ = source->getOffset();
723 error(
"Attempted write to SciArray with invalid type %d", _type);
731 void fill(
const uint16 index, uint16 count,
const reg_t value) {
732 if (count == 65535 ) {
733 count = size() - index;
740 resize(index + count);
743 case kArrayTypeInt16:
752 case kArrayTypeString: {
753 byte *target = (byte *)_data + index;
754 const byte fillValue = value.getOffset();
756 *target++ = fillValue;
761 case kArrayTypeInvalid:
763 error(
"Attempted write to uninitialized SciArray");
772 void copy(SciArray &source,
const uint16 sourceIndex,
const uint16 targetIndex, int16 count) {
774 count = source.size() - sourceIndex;
781 resize(targetIndex + count);
782 source.resize(sourceIndex + count);
784 assert(source._elementSize == _elementSize);
786 const byte *sourceData = (byte *)source._data + sourceIndex * source._elementSize;
787 byte *targetData = (byte *)_data + targetIndex * _elementSize;
788 memmove(targetData, sourceData, count * _elementSize);
791 void byteCopy(
const SciArray &source,
const uint16 sourceOffset,
const uint16 targetOffset,
const uint16 count) {
792 error(
"SciArray::byteCopy not implemented");
798 void trim(
const int8 flags,
const char showChar) {
800 kWhitespaceBoundary = 32,
804 byte *data = (byte *)_data;
805 byte *end = data + _size;
809 if (flags & kArrayTrimLeft) {
812 while (source < end && *source !=
'\0' && *source != showChar && *source <= kWhitespaceBoundary) {
815 memmove(target, source,
Common::strnlen((
char *)source, _size - 1) + 1);
818 if (flags & kArrayTrimRight) {
820 while (source > data && *source != showChar && *source <= kWhitespaceBoundary) {
826 if (flags & kArrayTrimCenter) {
828 while (target < end && *target !=
'\0' && *target <= kWhitespaceBoundary && *target != showChar) {
832 if (*target !=
'\0') {
833 while (target < end && *target !=
'\0' && (*target > kWhitespaceBoundary || *target == showChar)) {
837 if (*target !=
'\0') {
839 while (*source !=
'\0') {
840 while (source < end && *source !=
'\0' && *source <= kWhitespaceBoundary && *source != showChar) {
844 while (source < end && *source !=
'\0' && (*source > kWhitespaceBoundary || *source == showChar)) {
845 *target++ = *source++;
850 while (source >= data && source > target && (*source <= kWhitespaceBoundary || *source >= kAsciiBoundary) && *source != showChar) {
855 memmove(target, source,
Common::strnlen((
char *)source, _size - 1) + 1);
865 assert(_type == kArrayTypeString);
874 assert(_type == kArrayTypeString || _type == kArrayTypeByte);
875 resize(
string.size() + 1,
true);
888 case kArrayTypeInt16:
891 case kArrayTypeString:
894 case kArrayTypeInvalid:
923 kDefaultSkipColor = 250
926 #define BITMAP_PROPERTY(size, property, offset)\ 927 inline uint##size get##property() const {\ 928 return READ_SCI11ENDIAN_UINT##size(_data + (offset));\ 930 inline void set##property(uint##size value) {\ 931 WRITE_SCI11ENDIAN_UINT##size(_data + (offset), (value));\ 955 static inline uint16 getBitmapHeaderSize() {
978 static inline uint32 getBitmapSize(
const uint16 width,
const uint16 height) {
979 return width * height + getBitmapHeaderSize();
982 inline SciBitmap() : _data(
nullptr), _dataSize(0), _gc(
true) {}
984 inline SciBitmap(
const SciBitmap &other) {
985 _dataSize = other._dataSize;
986 _data = (byte *)malloc(other._dataSize);
987 memcpy(_data, other._data, other._dataSize);
994 inline ~SciBitmap()
override {
1000 inline SciBitmap &operator=(
const SciBitmap &other) {
1001 if (
this == &other) {
1006 _dataSize = other._dataSize;
1007 _data = (byte *)malloc(other._dataSize);
1008 memcpy(_data, other._data, _dataSize);
1020 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) {
1022 _dataSize = getBitmapSize(width, height) + paletteSize;
1023 _data = (byte *)realloc(_data, _dataSize);
1026 const uint16 bitmapHeaderSize = getBitmapHeaderSize();
1031 setSkipColor(skipColor);
1033 WRITE_SCI11ENDIAN_UINT16(_data + 10, 0);
1035 setDataSize(width * height);
1036 WRITE_SCI11ENDIAN_UINT32(_data + 16, 0);
1037 setHunkPaletteOffset(paletteSize > 0 ? (bitmapHeaderSize + width * height) : 0);
1038 setDataOffset(bitmapHeaderSize);
1039 setUncompressedDataOffset(bitmapHeaderSize);
1040 setControlOffset(0);
1041 setXResolution(xResolution);
1042 setYResolution(yResolution);
1047 inline int getRawSize()
const {
1051 inline byte *getRawData()
const {
1055 inline Buffer &getBuffer() {
1059 inline bool getShouldGC()
const {
1063 inline void enableGC() {
1067 inline void disableGC() {
1071 BITMAP_PROPERTY(16, Width, 0);
1072 BITMAP_PROPERTY(16, Height, 2);
1076 (int16)READ_SCI11ENDIAN_UINT16(_data + 4),
1077 (int16)READ_SCI11ENDIAN_UINT16(_data + 6)
1082 WRITE_SCI11ENDIAN_UINT16(_data + 4, (uint16)origin.
x);
1083 WRITE_SCI11ENDIAN_UINT16(_data + 6, (uint16)origin.
y);
1086 inline uint8 getSkipColor()
const {
1090 inline void setSkipColor(
const uint8 skipColor) {
1091 _data[8] = skipColor;
1094 inline bool getRemap()
const {
1095 return READ_SCI11ENDIAN_UINT16(_data + 10) & kBitmapRemap;
1098 inline void setRemap(
const bool remap) {
1099 uint16 flags = READ_SCI11ENDIAN_UINT16(_data + 10);
1101 flags |= kBitmapRemap;
1103 flags &= ~kBitmapRemap;
1105 WRITE_SCI11ENDIAN_UINT16(_data + 10, flags);
1108 BITMAP_PROPERTY(32, DataSize, 12);
1110 BITMAP_PROPERTY(32, HunkPaletteOffset, 20);
1112 BITMAP_PROPERTY(32, DataOffset, 24);
1116 BITMAP_PROPERTY(32, UncompressedDataOffset, 28);
1119 BITMAP_PROPERTY(32, ControlOffset, 32);
1121 inline uint16 getXResolution()
const {
1122 if (getDataOffset() >= 40) {
1123 return READ_SCI11ENDIAN_UINT16(_data + 36);
1130 inline void setXResolution(uint16 xResolution) {
1131 if (getDataOffset() >= 40) {
1132 WRITE_SCI11ENDIAN_UINT16(_data + 36, xResolution);
1136 inline uint16 getYResolution()
const {
1137 if (getDataOffset() >= 40) {
1138 return READ_SCI11ENDIAN_UINT16(_data + 38);
1145 inline void setYResolution(uint16 yResolution) {
1146 if (getDataOffset() >= 40) {
1147 WRITE_SCI11ENDIAN_UINT16(_data + 38, yResolution);
1151 inline byte *getPixels() {
1152 return _data + getUncompressedDataOffset();
1155 inline byte *getHunkPalette() {
1156 if (getHunkPaletteOffset() == 0) {
1159 return _data + getHunkPaletteOffset();
1162 inline void setPalette(
const Palette &palette) {
1163 byte *paletteData = getHunkPalette();
1164 if (paletteData !=
nullptr) {
1165 SciSpan<byte> paletteSpan(paletteData, getRawSize() - getHunkPaletteOffset());
1166 HunkPalette::write(paletteSpan, palette);
1172 void applyRemap(SciArray &clut) {
1173 const int length = getWidth() * getHeight();
1174 uint8 *pixel = getPixels();
1175 for (
int i = 0; i < length; ++i) {
1176 const int16 color = clut.getAsInt16(*pixel);
1177 assert(color >= 0 && color <= 255);
1178 *pixel++ = (uint8)color;
1184 getWidth(), getHeight(),
1185 getXResolution(), getYResolution(),
1186 getOrigin().x, getOrigin().y,
1188 getRemap() ?
"remap" :
"no remap",
1189 getShouldGC() ?
"GC" :
"no GC");
1193 #undef BITMAP_PROPERTY 1201 ret.
maxSize = at(pointer.getOffset()).getRawSize();
1202 ret.raw = at(pointer.getOffset()).getRawData();
1214 #endif // SCI_ENGINE_SEGMENT_H int first_free
Definition: segment.h:242
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:207
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
void clear()
Definition: array.h:320
Definition: segment.h:348
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:338
Definition: segment.h:361
int entries_used
Definition: segment.h:243
bool isValidOffset(uint32 offset) const override
Definition: segment.h:176
Definition: segment.h:234
Definition: serializer.h:79
Definition: segment.h:389
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:380
Definition: segment.h:202
reg_t succ
Definition: segment.h:197
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:351
Definition: segment.h:324
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:408
bool isValidOffset(uint32 offset) const override
Definition: segment.h:286
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:180
Definition: segment.h:147
Definition: segment.h:236
Definition: segment.h:335
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:305
size_type size() const
Definition: array.h:315
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: seg_manager.h:48
int16 x
Definition: rect.h:46
signed char * fill(signed char *first, signed char *last, Value val)
Definition: algorithm.h:168
int16 y
Definition: rect.h:47
reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const override
Definition: segment.h:405
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:229
bool isValidOffset(uint32 offset) const override
Definition: segment.h:401
uint _capacity
Definition: segment.h:166