为什么会生成一条 3 像素的线(一红一绿一蓝)而不是圆形波浪水?

问题描述 投票:0回答:1

好吧,我在翻译方面取得了良好的进展,因为现在我可以看到像素出现在位图上,但是我不明白的是错误在哪里,我已经重新检查了几次,我认为我已经正确翻译了不同的基本功能但我仍然无法得到著名的圆圈,一旦我修改了一些东西,而不是让三个像素水平对齐并以红色、蓝色和绿色相互间隔like this after zooming,它就会让我看到一条灰色的水平线是我能知道的是,在所有情况下,执行 x 秒后,程序要么不再响应,要么自行关闭。

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// esi -> edi, ecx = line width
// return = (4 * Pixel(x, y) + 3 * Pixel(x - 1, y) + 3 * Pixel(x + 1, y) + 3 * Pixel(x, y + 1) + 3 * Pixel(x, y - 1)) / 16
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

void WaveGetPixel(unsigned char* dst, const unsigned char* src, int stride) {
    unsigned int sum = 0;
    unsigned int pix;

    // (4 * Pxl(x,y) +
    //  3 * Pxl(x-1,y) +
    //  3 * Pxl(x+1,y) +
    //  3 * Pxl(x,y+1) +
    //  3 * Pxl(x,y-1)) / 16
    //
    // convolution kernel:
    //
    // +----+----+----+
    // |    | 3A |    |
    // +----+----+----+
    // | 3L | 4C | 3R |
    // +----+----+----+
    // |    | 3B |    |
    // +----+----+----+

    // 4 * Pxl(x,y)
    // current pixel (4C)
    pix = src[0];
    pix <<= 2;
    sum += pix;

    // 3 * Pxl(x-1,y)
    // pixel to the left (3L)
    pix = src[-1];
    pix *= 3;
    sum += pix;

    // 3 * Pxl(x+1,y)
    // pixel to the right (3R)
    pix = src[1];
    pix *= 3;
    sum += pix;

    // 3 * Pxl(x,y+1)
    // pixel below (3B)
    pix = src[stride];
    pix *= 3;
    sum += pix;

    // 3 * Pxl(x,y-1)
    // pixel above (3A)
    pix = src[-stride];
    pix *= 3;
    sum += pix;

    // / 16
    sum >>= 4;

    dst[0] = sum;
}

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Rendering subroutine, renders the new frame data into lpDIBitsRender
// Algorithm:
// posx = Wave1(x-1, y) - Wave1(x+1, y) + x
// posy = Wave1(x, y-1) - Wave1(x, y+1) + y
// SourceBmp(x, y) = DestBmp(posx, posy)
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

void WaveRender(WAVE_OBJECT* lpWaveObject) { // Translation OK
    int dwPosX, dwPosY, dwFlag = 0;
    int dwPtrSource;
    int dwPtrDest;

    if (!(lpWaveObject->dwFlag & F_WO_ACTIVE))
        return;

    lpWaveObject->dwFlag |= F_WO_NEED_UPDATE;
    int *esi = lpWaveObject->lpWave1;
    int edi = lpWaveObject->dwWaveByteWidth;

    unsigned char *Src = lpWaveObject->lpDIBitsSource;
    unsigned char *Rdr = lpWaveObject->lpDIBitsRender;

    int i = 1;
    do {
        int j = 0;
        do {

            // Calculate PosY = i + energy above pixel - energy below pixel
            dwPosY = esi[(edi - lpWaveObject->dwWaveByteWidth) / sizeof(*esi)];
            dwPosY = dwPosY - esi[(lpWaveObject->dwWaveByteWidth + edi) / sizeof(*esi)] + i;

            // Calculate PosX = j + energy left of pixel - energy right of pixel
            dwPosX = esi[(edi - 4) / sizeof(*esi)] - esi[(edi + 4) / sizeof(*esi)] + j;

            if (dwPosX >= 0 && dwPosX < lpWaveObject->dwBmpWidth && dwPosY >= 0 && dwPosY < lpWaveObject->dwBmpHeight) {
                // Calculate ptrSource = dwPosY * dwDIByteWidth + dwPosX * 3
                dwPtrSource = (dwPosY * lpWaveObject->dwDIByteWidth + dwPosX * 3);

                // Calculate ptrDest = i * dwDIByteWidth + j * 3
                dwPtrDest = (i * lpWaveObject->dwDIByteWidth + j * 3);

                // Render pixel [ptrDest] = Original pixel [ptrSource]
                Src += dwPtrSource; //lea   esi,[esi+ecx]
                Rdr += dwPtrDest;   //lea   edi,[edi+eax]  

                if (dwPtrSource != dwPtrDest) {
                    dwFlag |= 1;  // Set flag to indicate that the state is still active
                    WaveGetPixel(Rdr, Src, lpWaveObject->dwDIByteWidth);
                    Rdr += 1;
                    Src += 1;
                    WaveGetPixel(Rdr, Src, lpWaveObject->dwDIByteWidth);
                    Rdr += 1;
                    Src += 1;
                    WaveGetPixel(Rdr, Src, lpWaveObject->dwDIByteWidth);
                    Rdr += 1;
                    Src += 1;
                }
                else {
                    Rdr = Src;
                    //Src = lpWaveObject->lpDIBitsSource + 3;
                    //Rdr = lpWaveObject->lpDIBitsRender + 3;
                }
            }
            edi += 4;
            j += 1;
        } while (j < lpWaveObject->dwBmpWidth);
         i += 1;
    } while (i < lpWaveObject->dwBmpHeight - 1);

    // Copy rendered pixel data to hDc
    SetDIBits(lpWaveObject->hDcRender, lpWaveObject->hBmpRender, 0, lpWaveObject->dwBmpHeight, (const int*)lpWaveObject->lpDIBitsRender, &lpWaveObject->stBmpInfo, DIB_RGB_COLORS);

    if (!dwFlag) {
        lpWaveObject->dwFlag &= ~F_WO_ACTIVE;
    }
}

经过调试后,似乎在一个小函数中仍然存在访问冲突的历史,但我真的不明白它会如何被翻译得很差,所以我想错误可能来自调用它的函数,因此我将如果您看到任何内容,请在此处查看,这是原始的 asm 源代码:https://pastebin.com/gceED3Sg 就像所问的那样。

编辑:好的,所以我用 IDA 向我建议的代码替换了代码的某些部分,这些部分对我来说完全令人厌恶且难以理解,例如: dwPosY = (int)((char*)esi + edi - lpWaveObject->dwWaveByteWidth);最后,现在我有了一个动画的外观,除了圆圈比圆圈更多的线条......而且程序总是在几秒钟后崩溃......所以我不知道为什么会这样。解决了部分问题或为什么它不断崩溃,但我试图看看是否有任何其他代码可以用这个废话替换,如果它有助于它更好地工作,我稍后会尝试理解这意味着什么。 与此同时,以下是该功能的当前状态:

  void WaveGetPixel(unsigned char * dst, const unsigned char * src, int stride) {
  unsigned int sum = 0;
  unsigned int pix;

  // (4 * Pxl(x,y) +
  //  3 * Pxl(x-1,y) +
  //  3 * Pxl(x+1,y) +
  //  3 * Pxl(x,y+1) +
  //  3 * Pxl(x,y-1)) / 16
  //
  // convolution kernel:
  //
  // +----+----+----+
  // |    | 3A |    |
  // +----+----+----+
  // | 3L | 4C | 3R |
  // +----+----+----+
  // |    | 3B |    |
  // +----+----+----+

  // 4 * Pxl(x,y)
  // current pixel (4C)
  pix = src[0];
  pix <<= 2;
  sum += pix;

  // 3 * Pxl(x-1,y)
  // pixel to the left (3L)
  pix = src[-3];
  pix *= 3;
  sum += pix;

  // 3 * Pxl(x+1,y)
  // pixel to the right (3R)
  pix = src[3];
  pix *= 3;
  sum += pix;

  // 3 * Pxl(x,y+1)
  // pixel below (3B)
  pix = src[stride];
  pix *= 3;
  sum += pix;

  // 3 * Pxl(x,y-1)
  // pixel above (3A)
  pix = src[-stride];
  pix *= 3;
  sum += pix;

  // / 16
  sum >>= 4;

  dst[0] = sum;
}

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Rendering subroutine, renders the new frame data into lpDIBitsRender
// Algorithm:
// posx = Wave1(x-1, y) - Wave1(x+1, y) + x
// posy = Wave1(x, y-1) - Wave1(x, y+1) + y
// SourceBmp(x, y) = DestBmp(posx, posy)
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

void WaveRender(WAVE_OBJECT * lpWaveObject) { // Translation OK
  int dwPosX, dwPosY, dwFlag = 0;
  int dwPtrSource;
  int dwPtrDest;

  if (!(lpWaveObject -> dwFlag & F_WO_ACTIVE))
    return;

  lpWaveObject -> dwFlag |= F_WO_NEED_UPDATE;
  int * esi = lpWaveObject -> lpWave1;
  int edi = lpWaveObject -> dwWaveByteWidth;
  //int edi = (lpWaveObject->dwWaveByteWidth / sizeof(*esi));

  //unsigned char *Src = lpWaveObject->lpDIBitsSource;
  //unsigned char *Rdr = lpWaveObject->lpDIBitsRender;

  unsigned char * Src;
  unsigned char * Rdr;

  int i = 1;
  do {
    int j = 0;
    do {

      // Calculate PosY = i + energy above pixel - energy below pixel
      //dwPosY = esi[(edi - lpWaveObject->dwWaveByteWidth) / sizeof(*esi)];
      //dwPosY = dwPosY - esi[(lpWaveObject->dwWaveByteWidth + edi) / sizeof(*esi)] + i;
      dwPosY = * (int * )((char * ) esi + edi - lpWaveObject -> dwWaveByteWidth);
      dwPosY = dwPosY - * (int * )((char * ) esi + lpWaveObject -> dwWaveByteWidth + edi) + i;

      // Calculate PosX = j + energy left of pixel - energy right of pixel
      //dwPosX = esi[(edi - 4) / sizeof(*esi)] - esi[(edi + 4) / sizeof(*esi)] + j;
      dwPosX = * (int * )((char * ) esi + edi - 4) - * (int * )((char * ) esi + edi + 4) + j;

      if (dwPosX >= 0 && dwPosX < lpWaveObject -> dwBmpWidth && dwPosY >= 0 && dwPosY < lpWaveObject -> dwBmpHeight) {
        // Calculate ptrSource = dwPosY * dwDIByteWidth + dwPosX * 3
        dwPtrSource = (dwPosY * lpWaveObject -> dwDIByteWidth + dwPosX * 3);

        // Calculate ptrDest = i * dwDIByteWidth + j * 3
        dwPtrDest = (i * lpWaveObject -> dwDIByteWidth + j * 3);

        // Render pixel [ptrDest] = Original pixel [ptrSource]
        //Src += dwPtrSource; //lea esi,[esi+ecx]
        //Rdr += dwPtrDest;   //lea edi,[edi+eax]  
        Src = & lpWaveObject -> lpDIBitsSource[dwPtrSource];
        Rdr = & lpWaveObject -> lpDIBitsRender[dwPtrDest];

        if (dwPtrSource != dwPtrDest) {
          dwFlag |= 1; // Set flag to indicate that the state is still active
          WaveGetPixel(Rdr, Src, lpWaveObject -> dwDIByteWidth);
          Rdr += 1;
          Src += 1;
          WaveGetPixel(Rdr, Src, lpWaveObject -> dwDIByteWidth);
          Rdr += 1;
          Src += 1;
          WaveGetPixel(Rdr, Src, lpWaveObject -> dwDIByteWidth);
          Rdr += 1;
          Src += 1;
        } else {
          Src = Src + 3;
          Rdr = Rdr + 3;
        }
      }
      edi += 4;
      j += 1;
    } while (j < lpWaveObject -> dwBmpWidth);
    i += 1;
  } while (i < lpWaveObject -> dwBmpHeight - 1);

  // Copy rendered pixel data to hDc
  SetDIBits(lpWaveObject -> hDcRender, lpWaveObject -> hBmpRender, 0, lpWaveObject -> dwBmpHeight, (const int * ) lpWaveObject -> lpDIBitsRender, & lpWaveObject -> stBmpInfo, DIB_RGB_COLORS);

  if (!dwFlag) {
    lpWaveObject -> dwFlag &= ~F_WO_ACTIVE;
  }
}

Screenshot of the weird result

c++ assembly winapi masm masm32
1个回答
0
投票

好吧,这很好,我只是替换了这些来自 IDA 的令人厌恶的代码,如我上次编辑中所解释的,特别是在 WaveSpread 函数上......并且它起作用了,我得到了圆形波浪......所以这很酷,但实际上是什么这东西真的意味着吗? (int)((char*)&esi[nWidth] 我什至看不懂...请问有办法让它更干净吗?

© www.soinside.com 2019 - 2024. All rights reserved.