Bonjour,
Je fais une traduction d'un code que j'ai depuis pas mal d'années en asm x86 qui génère un effet de vague d'eau sur une bitmap, dans l'idée d'en apprendre quelque chose je cherche à convertir ce code en c++, je pense avoir traduit environ 90% correctement mais les 10% restant me donne du fil à retordre, je n'ai pas d'erreur de compilation, les deux seuls warnings ne concerne pas directement cette partie du code mais des API Win 32, c'est une fois executer que au lieu d'avoir des belles vagues j'ai un genre de tas de pixels qui bougent pendant à peine une seconde puis le programme plante.
c'est qui me préocupe c'est principalement deux fonctions dont je pense qu'il y a une subitilité que je n'arrive pas à reproduire correctement en C++:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 _WaveGetPixel: movzx eax,byte ptr [esi] ; esi = Src shl eax,2 movzx edx,byte ptr [esi+3] lea edx,[edx+2*edx] add eax,edx movzx edx,byte ptr [esi-3] lea edx,[edx+2*edx] add eax,edx movzx edx,byte ptr [esi+ecx] ; ecx = dwDIByteWidth lea edx,[edx+2*edx] add eax,edx mov edx,esi sub edx,ecx movzx edx,byte ptr [edx] lea edx,[edx+2*edx] add eax,edx shr eax,4 mov [edi],al ; edi = Rdr inc esi inc edi ret ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 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) ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _WaveRender proc _lpWaveObject local @dwPosX,@dwPosY,@dwPtrSource,@dwFlag pushad xor eax,eax mov @dwFlag,eax mov ebx,_lpWaveObject assume ebx:ptr WAVE_OBJECT test [ebx].dwFlag,F_WO_ACTIVE jz _Ret or [ebx].dwFlag,F_WO_NEED_UPDATE mov esi,[ebx].lpWave1 ; esi = 00756F98 mov edi,[ebx].dwWaveByteWidth ; edi = pixel pointer xor ecx,ecx inc ecx ; ecx=i -- i=1; i<height; i++ _Loop1: xor edx,edx ; edx=j -- j=0; j<width; j++ _Loop2: push edx ;******************************************************************** ; PosY = i + energy above pixel - energy below pixel ; PosX = j + energy left of pixel - energy right of pixel ;******************************************************************** mov eax,edi sub eax,[ebx].dwWaveByteWidth mov eax,[esi+eax] mov @dwPosY,eax mov eax,[ebx].dwWaveByteWidth lea eax,[edi+eax] mov eax,[esi+eax] sub @dwPosY,eax add @dwPosY,ecx mov eax,[esi+edi-4];;;;; sub eax,[esi+edi+4] add eax,edx ;@dwPosX = eax mov @dwPosX,eax cmp eax,0 jl _Continue cmp eax,[ebx].dwBmpWidth ; = 395 jge _Continue mov eax,@dwPosY cmp eax,0 jl _Continue cmp eax,[ebx].dwBmpHeight ; = 123 jge _Continue ;******************************************************************** ; ptrSource = dwPosY * dwDIByteWidth + dwPosX * 3 ; ptrDest = i * dwDIByteWidth + j * 3 ;******************************************************************** mov eax,@dwPosX lea eax,[eax+eax*2] mov @dwPosX,eax push edx mov eax,@dwPosY mul [ebx].dwDIByteWidth ; = 1188 add eax,@dwPosX mov @dwPtrSource,eax mov eax,ecx mul [ebx].dwDIByteWidth pop edx lea edx,[edx+edx*2] add eax,edx ;@dwPtrDest = eax ;******************************************************************** ; Render pixel [ptrDest] = Original pixel [ptrSource] ;******************************************************************** pushad mov ecx,@dwPtrSource mov esi,[ebx].lpDIBitsSource mov edi,[ebx].lpDIBitsRender lea esi,[esi+ecx] lea edi,[edi+eax] .if ecx != eax or @dwFlag,1 ; If the source pixel and destination pixel are different, it indicates that the activity is still ongoing mov ecx,[ebx].dwDIByteWidth call _WaveGetPixel call _WaveGetPixel call _WaveGetPixel .else cld movsw ; ESI + 3 movsb ; EDI + 3 .endif popad ;******************************************************************** ; Continue looping ;******************************************************************** _Continue: pop edx inc edx add edi,4 ; Increment pixel cmp edx,[ebx].dwBmpWidth jb _Loop2 inc ecx mov eax,[ebx].dwBmpHeight dec eax cmp ecx,eax jb _Loop1 ;******************************************************************** ; Copy the rendered pixel data to hDc (Device Context) ;******************************************************************** invoke SetDIBits,[ebx].hDcRender,[ebx].hBmpRender,0,[ebx].dwBmpHeight,\ [ebx].lpDIBitsRender,addr [ebx].stBmpInfo,DIB_RGB_COLORS .if ! @dwFlag and [ebx].dwFlag,not F_WO_ACTIVE .endif _Ret: ;******************************************************************** assume ebx:nothing popad ret _WaveRender endp
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 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; // 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] 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; } }
Partager