Ich versuche mit Delphi einen function hook auf wglSwapBuffers zu machen und dann einen Screenshot aus einem ogl spiel zu machen.
Folgendes ist für mich schwer begreiflich.
1. wenn ich opengl von delphi6 verwende, dann geht es ausser dass ich natürlich die farbe für das bitmap nicht bekomme.
opengl kann nur GL_RGBA...
2. wenn ich nur dglOpenGl verwende dann stürtzt mir das spiel ab.
wenn ich beides verwende, dann funktioniert es zwar mit GL_BGRA aber ich denke das ist redundant bzw. nicht sinn der sache.
Ein weiters problem scheint auch zu sein, das
Code:
glGetIntegerv(GL_VIEWPORT, @Viewport);
nur zufällig die richtige auflösung liefert. manuell gesetzt funktioniert es:
Code:
Viewport[2] := 800;
Viewport[3] := 600;
Hier hab ich den verdacht, dass opengl buggy ist und ich dglOpenGl scheinbar nur für GL_BGRA verwende.
Ist aber nur ein verdacht.
gibt es irgend welche tips für mich was ich mir anschauen sollte - oder eine Lösung
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Ich denke nicht, dass es an OpenGL liegt, dass das Spiel angestürzt ist. Sondern ich denke es liegt an dem was du machst. Bei C++ Programmen/Spielen ist es häufig so, dass für das Release nur die wirklich notwendigste Fehlerbehandlung stattfindet. Bei der kleinsten Exception steigen die Spiele dann immer sofort aus.
Wieso denke ich ist es im Spiel mit der dglOpenGL zu einem Fehler gekommen und mit der OpenGL.pas nicht? Nun die OpenGL.pas bindet alle Methoden statisch. Wärend die dglOpenGL.pas aber OpenGL dynamisch lädt und die Funktionspointer in Variablen abspeichert. Die Variablen hebe ich deswegen so hervor, da eine DLL in jeder Anwendung einen anderen Speicherbereich für Daten hat. Und da globale Hooks eher über DLL gemacht werden müsstest du den Header in jeder Anwendung initialisieren. Es genügt nicht, dass bei dir in der Hooksteuernden Anwendung zu machen.
Allerdings wäre es sicher besser, wenn du die dglOpenGL in diesem Falle nicht verwendest. Denn der Header lädt so ziemlich alle Pointer die er finden kann. Statisch gelinkt wären es nur die paar Benötigten.
Die benötigte Konstante (GL_BGRA) kannst du auch selber in deine Quellen einfügen. Die existiert deswegen nicht, da die OpenGL.pas schlicht und ergreifend zu alt dafür ist.
Und abschließend etwas anderes. Spiele sind normal sehr streng mit den Nutzungsregeln die sie auferlegen. Sollte du also eine Straftat begehen oder das für Cheats etc für online Spiele nutzen dann werden wird das Thema entfernen. Denn das wäre eine Straftat und wenn man will kann man das unter Umständen als Beihilfe auslegen. Und das wollen wir nicht.
Die benötigte Konstante (GL_BGRA) kannst du auch selber in deine Quellen einfügen. Die existiert deswegen nicht, da die OpenGL.pas schlicht und ergreifend zu alt dafür ist.
Das hab ich mir gedacht.
Ich hab bereits versucht GL_BGRA als konstante hinzuzufügen
Code:
const
GL_BGRA = $80E1;
allerdings wärend ich das so schreibe funktioniert es plötzlich - denke ich hab mich vorher damit verwurschtelt.
Als function hook hab ich es ebenfalls probiert ( nicht als .dll ) allerdings hatte ich ziemliche probleme damit ein Bitmap zu speichern - kein wunder ...
Jedenfalls bleibt weiterhin das problem, dass ich die Fenstergröße einfach nicht richtig bekomme.
Das ist wohl die letzte Frage - wie bekomme ich die auflösung des Fensters von dem ich den screenshot hole.
Zur beantwortunge der Illegalität.
1. ist decompilieren verboten - wie die lizenzvereinbarungen des herstellers aussehen weiß ich nicht, aber gegen cheats wir der schon was haben. - hooks aber sind nicht verboten - die sind ja im windows vorgesehen und damit wird sogar geworben ( wie toll das ist ).
2. Ich bin der letzte der einen Cheat schreibt.
Cheats schreiben ist meißtens recht leicht, zumindestens wenn es wallhacks oder sowas betrifft.
Ich mach das gegenteil - zu Medal of Honor Spearhead hab ich vor 2-3 Jahren mal einen Anticheat geschreiben.
Die Moh community hat mich gebeten den mal zu aktuallisieren. Vor allem, weil windows Vista es nicht zulässt screenshots über bitblt aus video fenster zu holen.
Jetzt bleibt mir nichts anderes über als den screenshot dirrekt von der Puffer zu holen.
Den Anticheat findest du auf dieser Seite:
http://www.spearhead-league.net/mos/ind ... Itemid=107
Er erweitert das spiel sowieso schon - in moh war nie vorgesehen custom maps nachzuladen - das macht mein programm ebenfalls.
Ich denke nicht, dass ea games sich darüber aufregen wird.
Jedenfalls hoffe ich, ich bekomme das letzt problem noch behoben ( auflösung des Fensters bekommen )
lg
Arnulf
Wie es im zusammenhand mit reversing, spielmodifikationen rechtlich in Deutschland aussieht würde mich auch interessieren, da ich auch ganz gerne an Starcraft rummodifiziere(natürlich keine cheats).
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Wieso die Fenstergröße nicht funktioniert weiß ich nicht. Könnte evtl was damit zu tun haben, dass es sich dabei um eine Hookanwendung handelt. Ich hatte auch schon mal eine kleine Hookdemo geschrieben. Sobald ich dort nur Kleinigkeiten zuviel gemacht hatte gabs Fehler. Allerdings habe ich das nicht näher untersucht sondern nur kurz angerissen.
"Alternativ" kannst du evtl mit der Methode WindowFromDC das Fensterhandel des DCs erfragen, der an wglSwapBuffers übergeben wurde. Und mit GetWindowInfo kannst du die Clientgröße des Fensters erfragen. Das ist aber ein Weg ganz ohne OpenGL.
Zum Rechtlichen: Ich wollte das nur erwähnen. Ich weiß nicht wie da die Rechtlage aussieht. Aber als seriöses Forum sollte man nichts illegales unterstützen. Zu mal Cheats auch nur was im privaten Bereich verlohren haben.
ach ich werde das ständig gefragt wenn ich wiedermal an meinem anticheat bastle ....
api calls in dem hook sind auch keine gute idee - hab ich probiert - ist schief gegangen ....
( vielleicht gehts irgendwie aber ich versuchs ersmal noch über opengl ).
allerdings komme ich mit den typen hier nicht zurecht und ich kann nur die höhe bestimmen. wie bekomme ich dann die breite? versucht hab ich für die Breite das hier - obwohl ich nicht weiß was das überhaupt ist
Code:
glGetIntegerv (GL_UNPACK_ROW_LENGTH,@viewW);
die typen hab ich so gemacht.
Code:
viewH : GLint;
viewW : GLint;
und auch so hab ichs probiert:
Code:
viewport : array[3..4] of GLint;
hoffe damit geht es - sobald ich rausbekomme wie ich die breite finde .
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Die Größe des Viewport bekommst du meines Wissens nach nur durch GL_VIEWPORT. Die Konstanten die du benutzt haben nur etwas mit Texturen zu tun. GL_UNPACK_IMAGE_HEIGHT_EXT stammt von 3D Texturen und GL_UNPACK_ROW_LENGTH gibt die Länge/Größe einer Zeile in einer 2D Textur wieder. Aber mit dem Viewport haben beide gar nichts zu tun.
Bei dem was ich mal gemacht hatte benutze ich kurioser Weise genau diese beiden Windows API Methoden. Und da gehts. Ich habe das aber nicht auf Vista und auch nicht mit Spielen probiert. Wobei der Code aber noch ein paar Schwächen aufweist.
glGetIntegerv(GL_VIEWPORT, @Viewport[0]); funktioniert im Übrigen in meinem Code mit meinen Anwendungen. Das Viewport ist aber ein Array mit 4 Einträgen. Also Viewport: array [0..3] of GLint; oder je Geschmack auch [1..4]. Aber es müssen 4 Stellen sein. Sonst überschreibst du dir was auf dem Stack und das kommt sicher nicht so gut. Evtl solltest du sicherheitshalber auch die erste Stelle des Arrays mit angeben. Siehe am Anfang des Absatzes. Muss zwar nicht unbedingt aber sicher ist sicher. Lässt dann keinen Interpretationsspielraum für den Kompiler.
Falls es immer noch nicht geht kannst du zur Not auch mal das probieren was ich gemacht hatte. Wobei du dann aber bitte noch eine Kleinigkeit verändern solltest. In der HookDll.dpr in der Methode Setup. Nach den Befehlen SetWindowsHookEx und UnpatchFunctions solltest du folgendes einfügen. Denn sonst kann es eine Weile dauern bis die DLL wieder deinstalliert wird, da die Fenster das nicht sofort mitbekommen.
ich mach etwas änliches - hab keine ahnung warum es das erste mal nicht funktioniert hat ... ist etwas stressig mit den hooks
Code:
window := WindowFromDC(device);
GetWindowRect(window,r);
das hier:
Code:
glGetIntegerv(GL_VIEWPORT, @Viewport[0])
muss ich mal probieren - obwohl ich doch denke es sollte ( so hab ichs probiert ).
Code:
glGetIntegerv(GL_VIEWPORT, @Viewport)
sein
na ich probier nochmal mit viewport. mal sehen
hast du eigentlich einen tip für mich wie ich den screenshot am bessten in mein programm übertragen könnnte.
ich wills nicht auf die festplatte speichern sondern mittels ipc in mein programm laden.
mmf, pipe, copydata - was würde sich bei einem bitmap mit injected .dll eigenen?
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Ja das mit Hooks ist in etwa wie Luftbaloons auf Messern zu balancieren...
GetWindowRect vs. GetWindowInfo. Das Info benutze ich deswegen, da man das Clientrect braucht. Wenn ich mich nicht vertue liefert das GetWindowRect die absolute Position des Fensters auf dem Bildschirm. Der Clientbereich eines Fensters beginnt bei 0, 0 und dort wurden schon so Sachen wie der Rahmen und die Titelleiste abgezogen.
@Viewport[0] vs. @Viewport. Da das Array eigentlich statisch ist sollte es gleich sein, da bei einem statischen die Größe im Code steckt und die Adresse auf die Daten zeigt. Bei Dynamischen oder Strings hingegen macht es einen Unterschied, denn dann ist @Viewport die Adresse der Variable und nicht die der Daten.
Das Array hat aber 4 Einträge, oder? Und nicht eienn Einträg mit Wert 4 sondern platz für 4 Stellen. Das ist Wichtig. Sonst wird was überschrieben.
Wie man das übergeben gestalten kann habe ich keine Ahnung. Problem dabei. Du bräuchtest bei einer Pipe zum Beispiel einen festen Namen. Außerdem muss du verhindern, dass 2 Anwendungen gleichzeitig ihre Daten in die Pipe schreiben. Denn sonst bekommst du nur Datenmüll raus. Wenn es nicht sogar Fehler proviziert.
das übertragen macht mir gerade graue haare.
shared memory oder pipe sind wohl die wahl.
ich hab das momentan mit wm_copdata realisiert und kann bereits schön zuschauen beim spielen.
allerdings ruckt es kurz beim screeshot holen ( 1 mal die sekunde) - nicht immer aber doch manchmal störend.
ich denke mit shared memory könnte man das noch optimieren.
glReadPixel dürfte nicht stören, aber das schreiben in einen memorystream und das versenden per wm_copydata.
Das zu synchronisieren dürfte aber noch stressig werden..
bisher verschick ich ja einfach 1 mal in der sekunde - wenn ich aber sozusagen einen screenshot holen will wirds interessant.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Warum der Viewport nicht geht weiß ich nicht.
Zum Übertragen kann ich nichts sagen. Aber das Blöde dabei ist, es muss schnell sein. Denn sonst wirds nicht Lustig für den Spieler. Fraps bremmst ja bei jedem Frame. Aber bei dir ist das nicht möglich. Bei der Frage bin ich aber überfragt.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Wenn es eine möglichkeit gibt, Speicher über prozesse hinweg zu sharen, solltest du versuchen, Das aktuelle OpenGL-Bild in gerade diesen Speicher zu schieben und ein zusätzliches Byte reservieren. Dieses würdest du dann auf 1 setzen, wenn ein Bild vorhanden ist. Dein "Leseprozess" prüft dieses Byte so lange, bis eine 1 drin steht, liest das Bild und setzt das Byte auf 0. Dann erst wird wieder ein Screenshot geholt. Das könnte klappen.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Ist das überhaupt sicher genug? Okay. Bytes sind atomare Operationen und werden nicht vom Windowssheduler unterbrochen. Wobei ich nicht weiß ob diese "Regel" auf DualCores überhaupt noch eine Bewandniss hat bzw ob sich der Prozessor/cache darum kümmert, dass das Byte zu dem Zeitpunkt gelockt ist. Selbst wenn nicht ein bit ist eher nicht tagisch. Viel interessanter ist da wohl eher die Sache, dass es unter Umständen theoretisch auch möglich wäre, dass deine Anwendung das Bild erst dann ausliest wenn das Spiel in diesen Speicher wieder schreibt. Auch wenn ich weiß, dass die Chancen dafür eher sehr sehr sehr gering sind. Technisch aber nicht unbedingt unmöglich.
Da würde ich mit einer Semaphore/Mutex den Speicher locken. Beide können durch Angabe eines Names globale Gültigkeit erhalten. Falls der Speicher gerade gelockt ist, dann evtl das Kopieren aussetzen (nicht warten), denn sonst könnte das Spiel in Mitleidenschaft gezogen werden. Dein Tool sollte dann aber maximal 10-20 Sekunden ohne Bild auskommen. Denn die Semaphore / Mutex ließen sich auch von Schadprogrammen dauerhaft blockieren wodurch dann nie ein Bild zu dir käme. Der Schutz wäre wirkungslos.
Das Signalisieren würde ich mit einem Event (TEvent) lösen. Dieses kann im Spiel gesetzt werden und deine Anwendung kann darauf warten ohne dauerhaft im Speicher rumlesen zu müssen.
Wie schaut das eigentlich aus, falls jemand auch andere OpenGL Anwendungen gleichzeitig benutzt? Es müssen ja auch nicht 2 Spiele sein. Sondern es reicht eine Anwenung die OpenGL benutzt und simple leichte Animationen hat. Solche "Irren" soll es geben die so etwas machen. Ich wäre zum Beispiel so jemand. Würdest du dann 2 Screens geschickt bekommen?
Außerdem würde mich persönlich interessieren wie du den Speicher erzeugt hast damit er von beiden Anwendungen genutzt werden kann? Bzw wenn der nicht über einen Namen identifiziert wird wie du dann das Handle / Adresse bekannt gegeben hast?
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Moment. Wenn das byte erst wieder auf 0 gesetzt wird nachdem das Kopieren des lesens aus dem Puffer heraus fertig ist, sollte es eigentlich nicht zu einem Problem kommen, oder?
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.