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"
56 bool isValid()
const {
return (
isRaw ? raw != 0 : reg != 0); }
86 static SegmentObj *createSegmentObj(SegmentType type);
92 inline SegmentType getType()
const {
return _type; }
155 return offset < _locals.
size() * 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 };
253 for (uint i = 0; i < _table.size(); i++) {
254 if (isValidEntry(i)) {
266 _table[oldff].next_free = oldff;
267 assert(_table[oldff].data ==
nullptr);
268 _table[oldff].data =
new T;
271 uint newIdx = _table.size();
272 _table.push_back(Entry());
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);
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);
613 const reg_t value = ((reg_t *)_data)[index];
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;
696 reg_t *target = (reg_t *)_data + index;
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:
738 reg_t *target = (reg_t *)_data + index;
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:
903struct ArrayTable :
public SegmentObjTable<SciArray> {
904 ArrayTable() : SegmentObjTable<SciArray>(SEG_TYPE_ARRAY) {}
909 SegmentRef dereference(reg_t pointer)
override;
916 kDefaultSkipColor = 250
919#define BITMAP_PROPERTY(size, property, offset)\
920inline uint##size get##property() const {\
921 return READ_SCI11ENDIAN_UINT##size(_data + (offset));\
923inline 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
1188struct BitmapTable :
public SegmentObjTable<SciBitmap> {
1189 BitmapTable() : SegmentObjTable<SciBitmap>(SEG_TYPE_BITMAP) {}
1191 SegmentRef dereference(reg_t pointer)
override {
1194 ret.maxSize = at(pointer.getOffset()).getRawSize();
1195 ret.raw = at(pointer.getOffset()).getRawData();
Definition: display_client.h:113
size_type size() const
Definition: array.h:316
void push_back(const T &element)
Definition: array.h:181
Definition: serializer.h:352
Definition: serializer.h:80
static String format(MSVC_PRINTF const char *fmt,...) GCC_PRINTF(1
Definition: atari-screen.h:42
Definition: seg_manager.h:48
Out copy(In first, In last, Out dst)
Definition: algorithm.h:52
signed char * fill(signed char *first, signed char *last, Value val)
Definition: algorithm.h:168
size_t strnlen(const char *src, size_t maxSize)
size_t strlcpy(char *dst, const char *src, size_t size)
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: segment.h:317
Common::Array< reg_t > listAllOutgoingReferences(reg_t object) const override
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:165
uint _capacity
Definition: segment.h:166
Common::Array< reg_t > listAllOutgoingReferences(reg_t object) const override
SegmentRef dereference(reg_t pointer) override
reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const override
Definition: segment.h:180
bool isValidOffset(uint32 offset) const override
Definition: segment.h:176
Definition: segment.h:382
bool isValidOffset(uint32 offset) const override
Definition: segment.h:394
Common::Array< reg_t > listAllDeallocatable(SegmentId segId) const override
Definition: segment.h:401
reg_t findCanonicAddress(SegManager *segMan, reg_t addr) const override
Definition: segment.h:398
SegmentRef dereference(reg_t pointer) override
Definition: segment.h:227
Definition: segment.h:354
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:373
Definition: segment.h:202
Definition: segment.h:341
Common::Array< reg_t > listAllOutgoingReferences(reg_t object) const override
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:344
Definition: segment.h:147
Common::Array< reg_t > listAllOutgoingReferences(reg_t object) const override
reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const override
int script_id
Definition: segment.h:148
SegmentRef dereference(reg_t pointer) override
bool isValidOffset(uint32 offset) const override
Definition: segment.h:154
Definition: segment.h:195
reg_t succ
Definition: segment.h:197
reg_t pred
Definition: segment.h:196
Definition: segment.h:328
Common::Array< reg_t > listAllOutgoingReferences(reg_t object) const override
void freeAtAddress(SegManager *segMan, reg_t sub_addr) override
Definition: segment.h:331
virtual SegmentRef dereference(reg_t pointer)
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr)
Definition: segment.h:123
virtual bool isValidOffset(uint32 offset) const =0
virtual Common::Array< reg_t > listAllDeallocatable(SegmentId segId) const
Definition: segment.h:130
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const
Definition: segment.h:116
virtual Common::Array< reg_t > listAllOutgoingReferences(reg_t object) const
Definition: segment.h:142
Definition: segment.h:236
Definition: segment.h:234
int entries_used
Definition: segment.h:243
int first_free
Definition: segment.h:242
Common::Array< reg_t > listAllDeallocatable(SegmentId segId) const override
Definition: segment.h:298
bool isValidOffset(uint32 offset) const override
Definition: segment.h:279
int maxSize
number of available bytes
Definition: segment.h:43
bool skipByte
true if referencing the 2nd data byte of *reg, false otherwise
Definition: segment.h:46
bool isRaw
true if data is raw, false if it is a reg_t sequence
Definition: segment.h:38
Definition: vm_types.h:39