QString MemoryDump::query(const int queryId, const ColorPalette& col, KnowledgeSources src) const { QString ret; Instance instance = queryInstance(queryId, src); QString s = QString("%1%2%3%4: ") .arg(col.color(ctTypeId)) .arg("0x") .arg(queryId, 0, 16) .arg(col.color(ctReset)); if (instance.isValid()) { s += QString("%1%2%3 (ID%4 0x%5%6)") .arg(col.color(ctType)) .arg(instance.typeName()) .arg(col.color(ctReset)) .arg(col.color(ctTypeId)) .arg((uint)instance.type()->id(), 0, 16) .arg(col.color(ctReset)); ret = instance.toString(&col); } else s += "(unresolved type)"; s += QString(" @%1 0x%2%3\n") .arg(col.color(ctAddress)) .arg(instance.address(), _specs.sizeofPointer << 1, 16, QChar('0')) .arg(col.color(ctReset)); ret = s + ret; return ret; }
QString MemoryDump::dump(const QString& type, quint64 address, int length, const ColorPalette& col) const { if (type == "char") { char c; if (_vmem->readAtomic(address, &c, sizeof(char)) != sizeof(char)) queryError(QString("Cannot read memory from address 0x%1") .arg(address, (_specs.sizeofPointer << 1), 16, QChar('0'))); return QString("%1 (0x%2)").arg(c).arg(c, (sizeof(c) << 1), 16, QChar('0')); } if (type == "int") { qint32 i; if (_vmem->readAtomic(address, (char*)&i, sizeof(qint32)) != sizeof(qint32)) queryError(QString("Cannot read memory from address 0x%1") .arg(address, (_specs.sizeofPointer << 1), 16, QChar('0'))); return QString("%1 (0x%2)").arg(i).arg((quint32)i, (sizeof(i) << 1), 16, QChar('0')); } if (type == "long") { qint64 l; if (_vmem->readAtomic(address, (char*)&l, sizeof(qint64)) != sizeof(qint64)) queryError(QString("Cannot read memory from address 0x%1") .arg(address, (_specs.sizeofPointer << 1), 16, QChar('0'))); return QString("%1 (0x%2)").arg(l).arg((quint64)l, (sizeof(l) << 1), 16, QChar('0')); } if (type == "raw" || type == "hex") { QString ret; const int buflen = 256, linelen = 16; char buf[buflen]; char bufstr[linelen + 1] = {0}; // Make sure we got a valid length if (length < 0) queryError(QString("No valid length given for dumping raw memory")); int totalBytesRead = 0, col = 0; while (length > 0) { int bytesRead = _vmem->readAtomic(address, buf, qMin(buflen, length)); length -= bytesRead; int i = 0; while (i < bytesRead) { // New line every 16 bytes begins with address if (totalBytesRead % 16 == 0) { if (totalBytesRead > 0) { ret += QString(" |%0|\n").arg(bufstr, -linelen); memset(bufstr, 0, linelen + 1); col = 0; } ret += QString("%1 ").arg(address, _specs.sizeofPointer << 1, 16, QChar('0')); } // Wider column after 8 bytes if (totalBytesRead % 8 == 0) ret += ' '; // Write the character as hex string if ((unsigned char)buf[i] < 16) ret += '0'; ret += QString::number((unsigned char)buf[i], 16) + ' '; // Add character to string buffer, if it's an ASCII char if ( ((unsigned char)buf[i] >= 32) && ((unsigned char)buf[i] < 127) ) bufstr[col] = buf[i]; else bufstr[col] = '.'; ++col; ++totalBytesRead; ++address; ++i; } } // Finish it up if (col > 0) { while (col < linelen) { ret += " "; if (col % 8 == 0) ret += ' '; ++col; } ret += QString(" |%0|").arg(bufstr, -linelen); } return ret; } QStringList components = type.split('.', QString::SkipEmptyParts); Instance result; if (!components.isEmpty()) { // Get first instance result = getInstanceAt(components.first(), address, QStringList("user")); components.pop_front(); while (!components.isEmpty()) { result = getNextInstance(components.first(), result, ksNone); components.pop_front(); } return QString("%1%2%3 (ID%4 0x%5%6) @%7 0x%8%9\n") .arg(col.color(ctType)) .arg(result.typeName()) .arg(col.color(ctReset)) .arg(col.color(ctTypeId)) .arg((uint)result.type()->id(), 0, 16) .arg(col.color(ctReset)) .arg(col.color(ctAddress)) .arg(result.address(), 0, 16) .arg(col.color(ctReset)) + result.toString(&col); } queryError3("Unknown type: " + type, QueryException::ecUnresolvedType, type); return QString(); }
QString MemoryDump::query(const QString& queryString, const ColorPalette& col, KnowledgeSources src) const { QString ret; if (queryString.isEmpty()) { // Generate a list of all global variables for (int i = 0; i < _factory->vars().size(); i++) { if (i > 0) ret += "\n"; Variable* var = _factory->vars().at(i); ret += var->prettyName(); } } else { Instance instance = queryInstance(queryString, src); QString s = QString("%1%2%3: ") .arg(col.color(ctBold)) .arg(queryString) .arg(col.color(ctReset)); if (instance.isValid()) { s += QString("%1%2%3 (ID%4 0x%5%6)") .arg(col.color(ctType)) .arg(instance.typeName()) .arg(col.color(ctReset)) .arg(col.color(ctTypeId)) .arg((uint)instance.type()->id(), 0, 16) .arg(col.color(ctReset)); if (instance.isNull()) ret = QString(col.color(ctAddress)) + "NULL" + QString(col.color(ctReset)); else { ret = instance.toString(&col); } } else s += "(unresolved type)"; s += QString(" @%1 0x%2%3") .arg(col.color(ctAddress)) .arg(instance.address(), _specs.sizeofPointer << 1, 16, QChar('0')) .arg(col.color(ctReset)); if (instance.bitSize() >= 0) { s += QString("[%1%3%2:%1%4%2]") .arg(col.color(ctOffset)) .arg(col.color(ctReset)) .arg((instance.size() << 3) - instance.bitOffset() - 1) .arg((instance.size() << 3) - instance.bitOffset() - instance.bitSize()); } ret = s + "\n" + ret; } return ret; }
void GL_CalcLuminance(duint8 const *buffer, dint width, dint height, dint pixelSize, colorpaletteid_t paletteId, dfloat *retBrightX, dfloat *retBrightY, ColorRawf *retColor, dfloat *retLumSize) { DENG2_ASSERT(buffer && retBrightX && retBrightY && retColor && retLumSize); static duint8 const sizeLimit = 192, brightLimit = 224, colLimit = 192; ColorPalette *palette = (pixelSize == 1? &resSys().colorPalette(paletteId) : nullptr); // Apply the defaults. // Default to the center of the texture. *retBrightX = *retBrightY = .5f; // Default to black (i.e., no light). for(dint c = 0; c < 3; ++c) { retColor->rgb[c] = 0; } retColor->alpha = 1; // Default to a zero-size light. *retLumSize = 0; dint region[4]; FindClipRegionNonAlpha(buffer, width, height, pixelSize, region); dd_bool zeroAreaRegion = (region[0] > region[1] || region[2] > region[3]); if(zeroAreaRegion) return; // // Image contains at least one non-transparent pixel. // long bright[2]; for(dint i = 0; i < 2; ++i) { bright[i] = 0; } long average[3], lowAvg[3]; for(dint i = 0; i < 3; ++i) { average[i] = 0; lowAvg[i] = 0; } duint8 const *src = buffer; // In paletted mode, the alpha channel follows the actual image. duint8 const *alphaSrc = &buffer[width * height]; // Skip to the start of the first column. if(region[2] > 0) { src += pixelSize * width * region[2]; alphaSrc += width * region[2]; } duint8 rgb[3]; dint avgCnt = 0, lowCnt = 0; dint cnt = 0, posCnt = 0; for(dint y = region[2]; y <= region[3]; ++y) { // Skip to the beginning of the row. if(region[0] > 0) { src += pixelSize * region[0]; alphaSrc += region[0]; } for(dint x = region[0]; x <= region[1]; ++x, src += pixelSize, alphaSrc++) { // Alpha pixels don't count. Why? -ds dd_bool const pixelIsTransparent = (pixelSize == 1? *alphaSrc < 255 : pixelSize == 4? src[3] < 255 : false); if(pixelIsTransparent) continue; if(pixelSize == 1) { Vector3ub palColor = palette->color(*src); rgb[0] = palColor.x; rgb[1] = palColor.y; rgb[2] = palColor.z; } else if(pixelSize >= 3) { std::memcpy(rgb, src, 3); } // Bright enough? if(rgb[0] > brightLimit || rgb[1] > brightLimit || rgb[2] > brightLimit) { // This pixel will participate in calculating the average center point. posCnt++; bright[0] += x; bright[1] += y; } // Bright enough to affect size? if(rgb[0] > sizeLimit || rgb[1] > sizeLimit || rgb[2] > sizeLimit) cnt++; // How about the color of the light? if(rgb[0] > colLimit || rgb[1] > colLimit || rgb[2] > colLimit) { avgCnt++; for(dint c = 0; c < 3; ++c) { average[c] += rgb[c]; } } else { lowCnt++; for(dint c = 0; c < 3; ++c) { lowAvg[c] += rgb[c]; } } } // Skip to the end of this row. if(region[1] < width - 1) { src += pixelSize * (width - 1 - region[1]); alphaSrc += (width - 1 - region[1]); } } if(posCnt) { // Calculate the average of the bright pixels. *retBrightX = (long double) bright[0] / posCnt; *retBrightY = (long double) bright[1] / posCnt; } else { // No bright pixels - Place the origin at the center of the non-alpha region. *retBrightX = region[0] + (region[1] - region[0]) / 2.0f; *retBrightY = region[2] + (region[3] - region[2]) / 2.0f; } // Determine rounding (to the nearest pixel center). dint roundXDir = dint( *retBrightX + .5f ) == dint( *retBrightX )? 1 : -1; dint roundYDir = dint( *retBrightY + .5f ) == dint( *retBrightY )? 1 : -1; // Apply all rounding and output as decimal. *retBrightX = (ROUND(*retBrightX) + .5f * roundXDir) / dfloat( width ); *retBrightY = (ROUND(*retBrightY) + .5f * roundYDir) / dfloat( height ); if(avgCnt || lowCnt) { // The color. if(!avgCnt) { // Low-intensity color average. for(dint c = 0; c < 3; ++c) { retColor->rgb[c] = lowAvg[c] / lowCnt / 255.f; } } else { // High-intensity color average. for(dint c = 0; c < 3; ++c) { retColor->rgb[c] = average[c] / avgCnt / 255.f; } } Vector3f color(retColor->rgb); R_AmplifyColor(color); for(dint i = 0; i < 3; ++i) { retColor->rgb[i] = color[i]; } // How about the size of the light source? /// @todo These factors should be cvars. *retLumSize = MIN_OF(((2 * cnt + avgCnt) / 3.0f / 70.0f), 1); } /* DEBUG_Message(("GL_CalcLuminance: width %dpx, height %dpx, bits %d\n" " cell region X[%d, %d] Y[%d, %d]\n" " flare X= %g Y=%g %s\n" " flare RGB[%g, %g, %g] %s\n", width, height, pixelSize, region[0], region[1], region[2], region[3], *retBrightX, *retBrightY, (posCnt? "(average)" : "(center)"), retColor->red, retColor->green, retColor->blue, (avgCnt? "(hi-intensity avg)" : lowCnt? "(low-intensity avg)" : "(white light)"))); */ }