Frage zu meiner DDrawScreenshot funktion
-
Erst einmal erklährung. Ich habe einen 3.2 Ghz P4 HT. Prince of Persia (The Sands of the Time... oder so) läuft bei mir flüssig.
Ich habe jetzt eine Screenshot-Funktion geschrieben, die ein 1024*768*8
(256 Farben) bild Fotographiert und in eine 24 bit Bitmap umwandelt. Da das etwa 2 sec gedauert hat, habe ich eine asm Funktion daraus gemacht. Es dauert jetzt "nur" 0.5 sec, in etwa.
Da das Programm insgesamt ein Spiel wird, wirken sich diese 0.5 sec negativ aus. Ich kann mir bloß nicht erklären, warum das so lange dauert, da immerhin oben genannte Spiele bei mir flüssig laufen. (und das bei 1024 * 768 Pixeln).void SaveBmp24 ( int width, int height) { int quantity = width*height; int DataBytes = 3*quantity; char BmpPath[512]; byte *Farben=(byte*)malloc(768); int SubAdr=ZeilenBreite+1024; LPBYTE pData; pData=(LPBYTE)calloc(sizeof(byte),DataBytes); //Header vorbereiten BITMAPFILEHEADER kFileHeader; kFileHeader.bfType = 0x4d42; // "BM" kFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + DataBytes; kFileHeader.bfReserved1 = 0; kFileHeader.bfReserved2 = 0; kFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); BITMAPINFOHEADER kInfoHeader; kInfoHeader.biSize = sizeof(BITMAPINFOHEADER); kInfoHeader.biWidth = width; kInfoHeader.biHeight = height; kInfoHeader.biPlanes = 1; kInfoHeader.biBitCount = 24; kInfoHeader.biCompression = BI_RGB; kInfoHeader.biSizeImage = 0; kInfoHeader.biXPelsPerMeter = 0; kInfoHeader.biYPelsPerMeter = 0; kInfoHeader.biClrUsed = 0; kInfoHeader.biClrImportant = 0; //Bitmap berechnen lpDDPalette->GetEntries(0, 0, 256, palEntry); LockVRAM(); for(int i=0;i<256;i++) { Farben[i]=palEntry[i].peBlue; Farben[i+256]=palEntry[i].peGreen; Farben[i+512]=palEntry[i].peRed; } _asm { //Adresse in den Video-RAM berechnen mov esi,VIO_RAM mov eax,ZeilenBreite mov ebx,767 mul ebx add esi,eax //Zieldata adressieren mov edi,pData //Die Daten mit den Farben adressieren mov ebx,Farben xor eax,eax //eax löschen mov edx,768 //Schleifenzähler 0 laden _loop0: mov ecx,1024 //Schleifenzähler 1 laden _loop1: push ebx //ebx zunächst sichern lodsb //al laden add ebx,eax //und zu ebx addieren (der rest von eax ist ja 0) mov al,[ebx] stosb //Schreiben add ebx,256 mov al,[ebx] stosb add ebx,256 mov al,[ebx] stosb pop ebx loop _loop1 sub esi,SubAdr //Zeile darunter einlesen dec edx jne _loop0 } UnlockVRAM(); lpDDPalette->SetEntries(0, 0, 256, palEntry); sprintf(BmpPath,"%s%s",PathScreen,"Screenshot.bmp"); FILE *Bmp=fopen(BmpPath,"wb"); fwrite( &kFileHeader,sizeof(BITMAPFILEHEADER),1 ,Bmp); fwrite( &kInfoHeader,sizeof(BITMAPINFOHEADER),1 ,Bmp); fwrite( pData ,sizeof(byte) ,DataBytes,Bmp); fclose(Bmp); free(pData); free(Farben); Farben=0; }
Der ASM-Abschnitt benötigt die 0.5 sec, wenn ich diesen raus nehme (per /.../, dauert das ganze eine Zeit, die kaum mehr der Rede wert ist.
Woran lieght das?
Ich hoffe, das ganze ist so halbwegs verständlich...
-
naja, die funktion kann noch deutlich verbessert werden, aber das problem liegt vermutlich eher im speichertyp, von dem du liest.
wo zeigt VIO_RAM hin?
-
@Camper: VIO_RAM zeigt auf ein DDRAW-Surface
LPDIRECTDRAWSURFACE7 lpDDsBack; DDSURFACEDESC2 ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize=sizeof(ddsd); if((lpDDsBack->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))!=DD_OK) return FALSE; VIO_RAM=(BYTE *)ddsd.lpSurface;
Ich weiß micht inwiefern du dich mit DirectX beschäftigt hast, dürfte aber eigentlich zu verstehen sein.
die funktion kann noch deutlich verbessert werden
Geht noch zu Optimieren? Wie? (Ich geb zu, bin in ASM vielleicht noch nicht so weit...)
Danke für alle Antworten, Gruß Streusselkuchen