--- libgig/trunk/src/gig.cpp 2014/05/20 12:15:05 2564
+++ libgig/trunk/src/gig.cpp 2014/06/08 19:00:30 2609
@@ -3056,7 +3056,7 @@
memset(_3lnk->LoadChunkData(), 0, _3lnkChunkSize);
// move 3prg to last position
- pCkRegion->MoveSubChunk(pCkRegion->GetSubList(LIST_TYPE_3PRG), 0);
+ pCkRegion->MoveSubChunk(pCkRegion->GetSubList(LIST_TYPE_3PRG), (RIFF::Chunk*)NULL);
}
// update dimension definitions in '3lnk' chunk
@@ -3759,6 +3759,56 @@
return dimreg;
}
+ int Region::GetDimensionRegionIndexByValue(const uint DimValues[8]) {
+ uint8_t bits;
+ int veldim = -1;
+ int velbitpos;
+ int bitpos = 0;
+ int dimregidx = 0;
+ for (uint i = 0; i < Dimensions; i++) {
+ if (pDimensionDefinitions[i].dimension == dimension_velocity) {
+ // the velocity dimension must be handled after the other dimensions
+ veldim = i;
+ velbitpos = bitpos;
+ } else {
+ switch (pDimensionDefinitions[i].split_type) {
+ case split_type_normal:
+ if (pDimensionRegions[0]->DimensionUpperLimits[i]) {
+ // gig3: all normal dimensions (not just the velocity dimension) have custom zone ranges
+ for (bits = 0 ; bits < pDimensionDefinitions[i].zones ; bits++) {
+ if (DimValues[i] <= pDimensionRegions[bits << bitpos]->DimensionUpperLimits[i]) break;
+ }
+ } else {
+ // gig2: evenly sized zones
+ bits = uint8_t(DimValues[i] / pDimensionDefinitions[i].zone_size);
+ }
+ break;
+ case split_type_bit: // the value is already the sought dimension bit number
+ const uint8_t limiter_mask = (0xff << pDimensionDefinitions[i].bits) ^ 0xff;
+ bits = DimValues[i] & limiter_mask; // just make sure the value doesn't use more bits than allowed
+ break;
+ }
+ dimregidx |= bits << bitpos;
+ }
+ bitpos += pDimensionDefinitions[i].bits;
+ }
+ dimregidx &= 255;
+ DimensionRegion* dimreg = pDimensionRegions[dimregidx];
+ if (!dimreg) return -1;
+ if (veldim != -1) {
+ // (dimreg is now the dimension region for the lowest velocity)
+ if (dimreg->VelocityTable) // custom defined zone ranges
+ bits = dimreg->VelocityTable[DimValues[veldim] & 127];
+ else // normal split type
+ bits = uint8_t((DimValues[veldim] & 127) / pDimensionDefinitions[veldim].zone_size);
+
+ const uint8_t limiter_mask = (1 << pDimensionDefinitions[veldim].bits) - 1;
+ dimregidx |= (bits & limiter_mask) << velbitpos;
+ dimregidx &= 255;
+ }
+ return dimregidx;
+ }
+
/**
* Returns the appropriate DimensionRegion for the given dimension bit
* numbers (zone index). You usually use GetDimensionRegionByValue
@@ -4025,6 +4075,241 @@
}
}
+// *************** Script ***************
+// *
+
+ Script::Script(ScriptGroup* group, RIFF::Chunk* ckScri) {
+ pGroup = group;
+ pChunk = ckScri;
+ if (ckScri) { // object is loaded from file ...
+ // read header
+ uint32_t headerSize = ckScri->ReadUint32();
+ Compression = (Compression_t) ckScri->ReadUint32();
+ Encoding = (Encoding_t) ckScri->ReadUint32();
+ Language = (Language_t) ckScri->ReadUint32();
+ Bypass = (Language_t) ckScri->ReadUint32() & 1;
+ crc = ckScri->ReadUint32();
+ uint32_t nameSize = ckScri->ReadUint32();
+ Name.resize(nameSize, ' ');
+ for (int i = 0; i < nameSize; ++i)
+ Name[i] = ckScri->ReadUint8();
+ // to handle potential future extensions of the header
+ ckScri->SetPos(sizeof(int32_t) + headerSize);
+ // read actual script data
+ uint32_t scriptSize = ckScri->GetSize() - ckScri->GetPos();
+ data.resize(scriptSize);
+ for (int i = 0; i < scriptSize; ++i)
+ data[i] = ckScri->ReadUint8();
+ } else { // this is a new script object, so just initialize it as such ...
+ Compression = COMPRESSION_NONE;
+ Encoding = ENCODING_ASCII;
+ Language = LANGUAGE_NKSP;
+ Bypass = false;
+ crc = 0;
+ Name = "Unnamed Script";
+ }
+ }
+
+ Script::~Script() {
+ }
+
+ /**
+ * Returns the current script (i.e. as source code) in text format.
+ */
+ String Script::GetScriptAsText() {
+ String s;
+ s.resize(data.size(), ' ');
+ memcpy(&s[0], &data[0], data.size());
+ return s;
+ }
+
+ /**
+ * Replaces the current script with the new script source code text given
+ * by @a text.
+ *
+ * @param text - new script source code
+ */
+ void Script::SetScriptAsText(const String& text) {
+ data.resize(text.size());
+ memcpy(&data[0], &text[0], text.size());
+ }
+
+ void Script::UpdateChunks() {
+ // recalculate CRC32 check sum
+ __resetCRC(crc);
+ __calculateCRC(&data[0], data.size(), crc);
+ __encodeCRC(crc);
+ // make sure chunk exists and has the required size
+ const int chunkSize = 7*sizeof(int32_t) + Name.size() + data.size();
+ if (!pChunk) pChunk = pGroup->pList->AddSubChunk(CHUNK_ID_SCRI, chunkSize);
+ else pChunk->Resize(chunkSize);
+ // fill the chunk data to be written to disk
+ uint8_t* pData = (uint8_t*) pChunk->LoadChunkData();
+ int pos = 0;
+ store32(&pData[pos], 6*sizeof(int32_t) + Name.size()); // total header size
+ pos += sizeof(int32_t);
+ store32(&pData[pos], Compression);
+ pos += sizeof(int32_t);
+ store32(&pData[pos], Encoding);
+ pos += sizeof(int32_t);
+ store32(&pData[pos], Language);
+ pos += sizeof(int32_t);
+ store32(&pData[pos], Bypass ? 1 : 0);
+ pos += sizeof(int32_t);
+ store32(&pData[pos], crc);
+ pos += sizeof(int32_t);
+ store32(&pData[pos], Name.size());
+ pos += sizeof(int32_t);
+ for (int i = 0; i < Name.size(); ++i, ++pos)
+ pData[pos] = Name[i];
+ for (int i = 0; i < data.size(); ++i, ++pos)
+ pData[pos] = data[i];
+ }
+
+ /**
+ * Move this script from its current ScriptGroup to another ScriptGroup
+ * given by @a pGroup.
+ *
+ * @param pGroup - script's new group
+ */
+ void Script::SetGroup(ScriptGroup* pGroup) {
+ if (this->pGroup = pGroup) return;
+ if (pChunk)
+ pChunk->GetParent()->MoveSubChunk(pChunk, pGroup->pList);
+ this->pGroup = pGroup;
+ }
+
+ /**
+ * Returns the script group this script currently belongs to. Each script
+ * is a member of exactly one ScriptGroup.
+ *
+ * @returns current script group
+ */
+ ScriptGroup* Script::GetGroup() const {
+ return pGroup;
+ }
+
+ void Script::RemoveAllScriptReferences() {
+ File* pFile = pGroup->pFile;
+ for (int i = 0; pFile->GetInstrument(i); ++i) {
+ Instrument* instr = pFile->GetInstrument(i);
+ instr->RemoveScript(this);
+ }
+ }
+
+// *************** ScriptGroup ***************
+// *
+
+ ScriptGroup::ScriptGroup(File* file, RIFF::List* lstRTIS) {
+ pFile = file;
+ pList = lstRTIS;
+ pScripts = NULL;
+ if (lstRTIS) {
+ RIFF::Chunk* ckName = lstRTIS->GetSubChunk(CHUNK_ID_LSNM);
+ ::LoadString(ckName, Name);
+ } else {
+ Name = "Default Group";
+ }
+ }
+
+ ScriptGroup::~ScriptGroup() {
+ if (pScripts) {
+ std::list