Pläne

Halbzeit meines Urlaubes und ich habe keine einzigen Tag lang gezockt sondern mir nur den Kopf über SR:SNES:DRMM (und natürlich auch das nahende Weihnachten) zerbrochen. Naja, heute habe ich außerdem keine einzige Zeile Code geschrieben und gedenke es auch dabei zu belassen, denn Recherchen und Kopfarbeit habe ich sehr wohl geleistet.

Zu der 1536*864px-G’schicht finde ich weder Lösungen noch Indizien das es bei jemand Anderem auch vorkommt. Auch habe ich den QB64 build gewechselt aber das Problem bleibt weiterhin bestehen. Die einzige Lösung wäre (Außer, wie mir gerade einfällt, dem Test auf einem anderen System… hmmm.) das ich im Forum um Hilfe frage aber… die für mich und die vorgesehenen Zwecke relevanten Fenster befinden sich alle noch im kopierten Ausschnitt.

Nach langem Herumgehadere mit mir bleibe ich dem >jetzt für mich<-Ansatz (siehe „Kontrolle erlangen„, Mo.10/12/18) treu und beschliesse das ich jetzt keine elfundrölfzig Jahre herumbastle bis ich _SCREENIMAGE korrekt zu laufen bekomme sondern mit dem weitermache was ich habe.

UPDATE:
Während ich diesen Text geschrieben habe, habe ich nebenbei nach einer .dll-basierenden Lösung gesucht. Dabei bin ich über folgende, mir bis dato unbekannte, Information gestolpert:

„Windows 8 and Windows 10 users have an additional trick that is a little faster. Tap the Windows key + PrtScn and your display will „blink“ as if the shutter of a camera just closed and opened. That indicates that a screenshot has been taken. This time, however, you don’t have to paste it into another program. Instead, the shot is automatically saved in Pictures > Screenshots.“
(Quelle: www.lifewire.com)

Uhm. Ob der Screenshot jetzt im Programm-Folder oder im Screenshot-Folder abgelegt wird, ist egal. Dateien verschieben ist wahrlich keine Hexerei.

Apropos Folder. Eine meiner heute ausgearbeiteten Ideen dreht sich um eben diese:
Bei einer Schulung in der Arbyte wurde mir der HOTFOLDER-Gebrauch näher gebracht, und die Idee mit dem IN bzw OUT Folder kla… adaptiere ich gerne für mein Projekt. Alle auszuarbeiteten .zst kommen in den IN-Folder, das Programm erstellt dann anhand dieser die Liste nach der sie verarbeitet werden. Die finalen Dateien landen dann im OUT-Folder in einem eignem mit Datum und Uhrzeit versehenen Folder. (Inkl. der .zst-Dateien. Das verarbeitete Quelldateien „verschwinden“ stößt mir aufgrund regelmäßig sauer auf. Das liegt aber daran das je nach Workplace, Uhrzeit und Wasserstand der Donau (alias keinem für mich nachvollziehbarem System) Dateien beim drag&drop verschoben oder nur kopiert werden…)

Wichtig wäre btw. auch noch eine Justierungsmöglichkeit.
Es war vor einer halben Ewigkeit als ich am laufenden Band Screenshots für ein geschriebenes Let’s’Play (Final Fantasy I, das fertig zu stellen steht auch noch irgendwo (gaaanz weit unten) auf meiner ToDo-List…) erstellte nur um regelmäßig die Hilfslinien im Photoshop an die Fensterposition anzupassen bis ich eines Tages entdeckte das sich die Fenstergröße verändert hatte. Dies betraf „auch“ den Zoomfaktor mit der die 256×224 Pixel dargestellt wurden. Beim Versuch die ursprüngliche Fenstergröße wiederherzustellen wurde mir bewußt das diese nie einer normalen (x2, x3, x4,…) Zoomstufe entsprach sondern lange vor dem Start des Let’s’Play’s frei mit der Hand gezogen skaliert worden war…

Wo war ich beziehungsweise wo wollte ich hin? Zur Justierungsmöglichkeit.

Damals habe ich auf die harte Tour gelernt das man sich auf keinerlei Werte oder Positionen von Fenstern verlassen darf. Da dieses Extrahierungsprogramm auf fixe Koordinaten setzt wäre es imho grob fahrlässig darauf zu setzen das diese sich nicht verändern.

Meine Idee wäre es die Position der Menüleiste, die des Ansichtsfensters sowie des Speicherdialogs zu kontrollieren. Sollten diese nicht korrekt sein, wird ein Screenshot erstellt und der Benutzer aufgefordert bestimmte Orientierungspunkte neu zu setzen. Da die meisten Schritte per Shortcuts ausführbar sind, sind glaube ich sogar noch weniger Orientierungspunkte notwenig als ich zu Beginn dieses Absatzes annahm. Genaueres werde ich sehen wenn es dann soweit ist. Wichtig war mir nur diesen Brainfart zu verewigen.

Wozu PostIts oder Notizzettel? Ich habe einen Blog… xD

Auflösung

Habe den ganzen Tag damit ver…bracht mein Log vom .txt ins WordPress zu übertragen. Unglaublich wie viel Layout in einfaches ASCII hineininterpretiert werden kann und wie viele Fehler dabei gemacht werden können.

Genug gesudert, zurück zum Programm.
Der Beispielcode in _SCREENIMAGE ist folgender:

desktop& = _SCREENIMAGE
MaxScreenX& = _WIDTH(desktop&)
MaxScreenY& = _HEIGHT(desktop&)
_FREEIMAGE desktop& 'free image after measuring screen(it is not displayed)
SCREEN _NEWIMAGE(MaxScreenX&, MaxScreenY&, 256) 'program window is sized to fit
_SCREENMOVE _MIDDLE

In der ersten Zeile wird von dem Desktop ein Screenshot erstellt und in desktop& gespeichert. Aus diesem dektop& werden Breite (MaxScreenX&) und Höhe (MaxScreenY&) ausgelesen. Daraufhin wird desktop& wieder geleert und das QB64-Programmfenster auf die Desktopgröße vergrößert. In der letzten Zeile wird das QB64-Programmfenster zentriert.
Das totale Gegenteil von Borderless Fullscreen…

Würde _SCREENIMAGE des Beispiels wegen nicht verwendet werden müssen, würde man die Desktopdimensionen über die QB64-Befehle _DESKTOPWIDTH und _DESKTOPHEIGHT einlesen können.
Das aber nur so am Rande bemerkt, da ich ja eigentlich nur wegen _SCREENIMAGE da bin.

Die einfachste Version die Funktionalität des Programms zu testen wäre es desktop& nicht zu leeren und stattdessen per _COPYIMAGE anzuzeigen. Da ich aber sowieso die Screenshots speichern möchte, wende ich mich dem Begriff… es gibt keinen Speicher-Bild-als-Datei-Befehl!?!

Aber es gibt eine von Galleon erstellte SAVEIMAGE SUB die .bmp erstellen kann. Irgendwie bin ich von dieser Lösung nicht wirklich begeistert, aber ein Testlauf sollte zeigen ob durch das .bmp ein Qualitätsverlust entsteht.

Es funktioniert. Das .bmp ist zwar fast 4Mb groß aber Farben und Qualität passen. Allerdings ist es statt den erwarteten 1920×1080 nur 1536*864 groß?
Links oben passt, aber rechts und unten fehlen Daten.

Einen kurzen Test mit dem weiter oben erwähnten _DESKTOPWIDTH und _DESKTOPHEIGHT ergibt das QB64 meint das mein Desktop diese Dimension hat.

Dafür habe ich entdeckt das _SCREENIMAGE(column1, row1, column2, row2) einstellbarer ist. Meine Vermutung das der Bildausschnitt zu groß war wird leider zerschmettert, denn der Koordinatengesteuerte Versuch provoziert einen Fehler. Mit QB64 ist also tatsächlich kein kompletter Screenshot möglich…

Kontrolle erlangen

SEND KEYS“ funktioniert wahnsinnig gut. In „MOUSE AREA“ befindet sich die Anleitung wie man den Mouse Cursor plaziert, das Einzige was mir jetzt noch fehlt ist das Senden von Mouse clicks.

Advanced Brainfart:
Wenn es möglich wäre den in „SEND KEYS“ erzeugten Screenshot aus dem Zwischenspeicher in QB64 zu importieren wäre es (mit kA, wahrscheinlich typisch unendlich hohem Aufwand) möglich diesen auszuwerten um die Sprites sinnvoll abzulegen (Siehe Sonntag 09/12/2018 Punkt#4: „Bild, x-pos, y-pos und Tilenummer“). Sich komplett auf Variabeln zu verlassen ist nicht möglich da die Tilenummer nicht eruierbar ist.

Back to topic:
Die Zeile die ich wahrscheinlich kopieren und modifizieren muss ist diese:


SUB SENDKEYS ALIAS keybd_event (BYVAL bVk AS LONG, BYVAL bScan AS LONG, BYVAL dwFlags AS LONG, BYVAL dwExtraInfo AS LONG)

Zuerst sollte ich mal schauen was zu „keybd_event“ in der „user32.dll“ steht und ob ein Mouse-equivalent existiert. (…) Oder ich finde sofort die „mouse_event function“ und im selben Zug das diese als auch die „Keybd_event function“ durch die „SendInput function“ ersetzt wurden.

Und da wären wir in meinem moralischen Dilemma: Soll dieses Programm >jetzt für mich< funktionieren oder >möglichst immer für möglichst alle<?

Nachdem sich das Projekt „SR:SNES:DRMM“ jetzt schon seit Jahren (Afair Mittwoch 05.10.2016) zieht und keine tatsächlichen Ergebnisse sondern „nur“ Ideen, Brainfarts, Erkenntnisse und ähnliches hervorgebracht hat, bin ich eine Runde egoistisch und wähle >jetzt für mich<.

Sollte es so funktionieren wie ich es gerne hätte und sollte ich es anwenden können und sollte ich Zeit, Lust und Laune haben kann ich es ja immer noch verallgemeinern.
Wie ich bei meinen Abstechern in VBA gelernt habe ist es aber notwendig alle verwendeten Ressourcen zu notieren und zu speichern.
(Der Link zu besten Quelle ever nutzt nichts wenn diese nicht mehr online ist… und deswegen speichere ich ab nun alle relevanten Seiten als .pdf und füge sie am Ende der Beiträge an.)

Okay, zerlegen wir SEND KEYS in die Angaben auf der Microsoft-Seite

void keybd_event(
  BYTE      bVk,	-> A virtual-key code. The code must be a value in the range 1 to 254.
  BYTE      bScan,	-> A hardware scan code for the key.
  DWORD     dwFlags,	-> Controls various aspects of function operation. This parameter can be one or more of the following values.
			   Value 			Meaning
			   KEYEVENTF_EXTENDEDKEY	If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
			   0x0001
			   KEYEVENTF_KEYUP		If specified, the key is being released. If not specified, the key is being depressed. 
			   0x0002
  ULONG_PTR dwExtraInfo	-> An additional value associated with the key stroke.
);
DECLARE DYNAMIC LIBRARY "user32"
    SUB SENDKEYS ALIAS keybd_event (BYVAL bVk AS LONG, BYVAL bScan AS LONG, BYVAL dwFlags AS LONG, BYVAL dwExtraInfo AS LONG)
END DECLARE

CONST KEYEVENTF_KEYUP = &H2
CONST VK_SNAPSHOT = &H2C 'PrtScn key
CONST VK_MENU = &H12 'Alt key
CONST VK_SHIFT = &H10 'Shift key
CONST VK_LWIN = &H5B

PRINT ""
PRINT "SENDKEYS clone example.  Press ENTER to begin..."
PRINT

WHILE INKEY$ <> CHR$(13): WEND

'=== Capture Active window to Clipoard as image (Like Alt+PrtSc)
SENDKEYS VK_MENU, 0, 0, 0					-> drückt Alt key
SENDKEYS VK_SNAPSHOT, 0, 0, 0					-> drückt PrtScn key
SENDKEYS VK_SNAPSHOT, 0, KEYEVENTF_KEYUP, 0			-> läßt PrtScn key los
SENDKEYS VK_MENU, 0, KEYEVENTF_KEYUP, 0				-> läßt Alt key los

Auf der Suche was „VK_LWIN = &H5B“ ist (Antwort: Die Windows-Taste) bei den Virtual-Key-Codes entdeckt das auch die Maustasten vorhanden sind:
https://docs.microsoft.com/de-at/windows/desktop/inputdev/virtual-key-codes

Constant/value    Description
VK_LBUTTON        Left mouse button
0x01
VK_RBUTTON        Right mouse button
0x02

Eine Runde wirres gegoogle weiter darf ich mitteilen das 0x01 anscheinend dem Code &H1 bzw &H01 entspricht. (0x02 ist &H2 bzw &H02).
Was genau das darstellt erchließt sich mir hingegen nicht.
0x01 = bit set / &H1 = decimal 1.???

Okay, theoretisch sollte es also möglich sein, VK_LMB = &H1 und VK_RMB = & &H2 in das Beispiel einzubauen, den Mousecursor mittels SetCursorPos x, y (Eine SUB die in MOUSE AREA erstellt wird.) zu einen bestimmten Punkt zu führen und dann per SENDKEYS VK_LMB, 0, 0, 0 zu drücken?

Sollte funktionieren. Dann basteln wir den Hybrid mal…

Uhm… „CONST KEYEVENTF_KEYUP = &H2“ ? Ich dachte &H2 ist gleichbedeutend mit &H02 alias Right Mouse Button?
Bei den „dwflags“ oben findet sich „0x0002„… hm, vielleicht funktioniert das Ganze doch nicht gaaanz so easy wie ich annahm…

Okay, funktioniert scheinbar ohne „mouse_event“ doch nicht…

Es funktioniert!!! Whoop whoop!

'============================
'KEYBOARD & MOUSE SCRIPT TEST
'-----------[kemoscte.bas]---
'
'Basierend auf SENDKEY.BAS (Coded for QB64 by Dav, JAN/2013) und dem
'"Mouse Area"-Beispiel gefunden auf https://qb64.org/wiki/Windows_Libraries
'
'Sinn und Zweck ist es den Mouse Cursor auszerhalb des Programmfensters auf dem
'Bildschirm zu bewegen, zu klicken und Text einzugeben.
'
'All (d) by -=[d.s.R.]=- 10.Dec.2018

DECLARE DYNAMIC LIBRARY "user32"
    SUB SetCursorPos (BYVAL x AS LONG, BYVAL y AS LONG) 'move cursor position
    SUB SENDKEYS ALIAS keybd_event (BYVAL bVk AS LONG, BYVAL bScan AS LONG, BYVAL dwFlags AS LONG, BYVAL dwExtraInfo AS LONG)
    SUB SENDMOUSE ALIAS mouse_event (BYVAL dwFlags AS LONG, BYVAL dx AS LONG, BYVAL dy AS LONG, BYVAL dwData AS LONG, BYVAL dwExtraInfo AS LONG)
END DECLARE

CONST KEYEVENTF_KEYUP = &H2
CONST VK_SNAPSHOT = &H2C 'PrtScn key
CONST VK_MENU = &H12 'Alt key
CONST VK_SHIFT = &H10 'Shift key
CONST VK_LWIN = &H5B

CONST MOUSEEVENTF_LEFTDOWN = &H2 'The left button is up.
CONST MOUSEEVENTF_LEFTUP = &H4 'The left button is down.
CONST MOUSEEVENTF_RIGHTDOWN = &H8 'The right button is up.
CONST MOUSEEVENTF_RIGHTUP = &H10 'The right button is down.

SHELL _DONTWAIT "notepad.exe"

SLEEP 1 'give time to make notepad the active window...

'=== Say Hi...
SENDKEYS &H48, 0, 0, 0: SENDKEYS &H48, 0, KEYEVENTF_KEYUP, 0 'H
SENDKEYS &H49, 0, 0, 0: SENDKEYS &H49, 0, KEYEVENTF_KEYUP, 0 'i

SetCursorPos 120, 60 '<- Mousecursor direkt ueber "Datei"
SENDMOUSE MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
SENDMOUSE MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
SetCursorPos 120, 120 '<- Mousecursor direkt ueber "Speichern"
SLEEP 1
SENDMOUSE MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
SENDMOUSE MOUSEEVENTF_LEFTUP, 0, 0, 0, 0

END

Link für morgen: SCREENIMAGE
„The _SCREENIMAGE function stores the current desktop image or a portion of it and returns an image handle.“
Ghihihi…

.pdf-Dateien:
001_QB64wiki_windows_libraries_10_12_2018.pdf (702kb)
002_WinDevCenter_keybd_event_function_10_12_2018.pdf (462kb)
003_WinDevCenter_mouse_event_function_10_12_2018.pdf (458kb)
004_WinDevCenter_virtual-key_codes_10_12_2018.pdf (419kb)

Kein Ende in Sicht

Nachgetragenes Vorwort:

Es war einmal ein Projekt namens [SR:SNES:DRMM]. Superlong story short: Ich möchte eine erweiterte Version des SNES Rollenspiels Shadowrun erstellen. Obwohl das Endprodukt aufgrund mangelnder Lizenzen nichts mehr damit zu tun haben soll, möchte ich um Look und Feel zu erhalten damit beginnen das Original möglichst 1:1 nachzustellen.

Da die Grafiken auf dem Modul gepackt sind und ich sie weder komplett oder korrekt im Internet finde, beginnt dieses Projekt damit selbst einen Weg zu finden diese zu extrahieren. (Diese Grafiken werden btw. NICHT in den weiteren Versionen verwendet sondern in höherer Auflösung und detaillierter nachgesetzt/neuerstellt!)

Ambitioniert wie ich war habe ich dazu sofort eine Webseite gebastelt um meine Gedanken/Fortschritte/usw. festzuhalten. Alles zu dokumentieren, die Grafiken für die Seite anzupassen und das ganze dann funktionierend zu schreiben wurde dann aber mehr Arbeit als jene die ich tatsächlich in das Projekt steckte. Also streckte ich bereits nach dem dritten Eintrag die Füße und überlegte Alternativen. Long story short, im Großen und Ganzen ist [SR:SNES:DRMM] schuld daran das ich nun doch WordPress verwende.

Die Undokumentierbarkeit hat mich allerdings nicht abgehalten weiterzumachen. Und wenn auch keine einzige Zeile Code geschrieben wurde, so habe ich mich dennoch intensiv (und erfolgreich!) mit dem „Exportieren“ der Sprites beschäftigt. Das Tool dazu nennt sich „vSNES“ und ist ein… uhm, zSNES-Savestate-Multieditor? kA, man kann jedenfalls anhand der .zst den aktuellen Screen in seine Layer und in seine Sprites aufteilen.

Mir fällt gerade auf das ich mir seit dem letzten Eintrag tatsächlich einen Haufen theoretischen Wissens zum Thema SNES-Grafiken sowie Praxis in dessen Anwendung angeeignet habe. Das hier jetzt alles abzuhandeln wäre… mir zu viel Arbeit. Das ist etwas das ich @wrk wenn ich Zeit dazu aber keine Möglichkeit zum weiterbasteln habe machen und an den relevanten Stellen einfügen werde.

Abschließend noch der Link zur ursprünglichen Seite und weiter gehts mit meinem aktuellen Versuch [SR:SNES:DRMM] zu realisieren. 🙂

Es wird Zeit endlich mal was zu tun. Die nahende Urlaubswoche biete sich an.
Hier mal der Schlachtplan zum „Exportieren“ der Sprites*.
* = Sprites steht hier stellvertretend für alle im Modul gespeicherten Grafiken, egal ob es sich um Sprites, Tiles, Fonts, etc. handelt. Da afaik alles in 8x8px Feldern hinterlegt ist und ich alles extrahiere ist es mir zu diesem Punkt egal um was es sich handelt.

1)Intros & Morgue(visit#1) sind großteils ge-savestate-ed.
⇒ Ein Tool dazu wäre praktisch, aber da dieses dann auch die Steuerung des Charakters ausführen müsste wäre es eher sinnlos.
2)Von jedem .zst werden in vSNES die einzelnen Layer als .png exportiert.
⇒ Da es sich immer um die selben Schritte handelt ist es nervend und sollte eigentlich automatisierbar werden.
3)Die exportierten .png werden auf Unterschiede kontrolliert.
⇒ Tool dazu ist begonnen worden, funktionierte aber nicht wirklich.
4)Die zu den einzigartigen .png gehörenden .zst werden wieder in vSNES geladen, der Cursor geht dann über die einzelnen sprites. Davon werden Screenshots erstellt. (Enthalten Bild, x-pos, y-pos und Tilenummer)
⇒ Absolut monoton, sollte automatisierbar sein.
5)Die Screenshots werden auf einzigartige sprites kontrolliert.
⇒ Ebenfalls wieder automatisierbar.
6)Die einzigartigen Sprites werden aus dem exportierten .png ausgelesen und gesammelt.
⇒ Definitiv automatisierbar.
7)Die gesammelten Sprites werden auf ihre Einzigartigkeit kontrolliert.
⇒ s.o.
8)Party schmeißen das alles Sprites exportiert sind. 🙂

Future-Brainfart:
In Schritt 5 sollte es machbar sein ein „Karte“ mit den Sprites anzulegen.
Diese Karten sollten später kombinierbar sein um die Map leichter nachbildbar zu machen.

Die schlimmste Arbeit (#1, frame für frame savestate-n) ist afair bis zum verlassen der Morgue(visit#1) schon erledigt. Die Auswertung der erhaltenen Savestates ist aber selbst für mich der monotone Arbeiten nicht scheut ein abartig umfangreiches Unterfangen.

Die (das?) notwendigen Tools um diese Aufgaben zu automatisieren sind, zumindest am Papier, supersimpel. Das einzige Problem ist, das es im Hintergrund laufen und Maus und Tatstaur steuern muss während mit diesen bsnes bedient wird.

Selbst herauszufinden wie man .zst ausliest ist mir nicht möglich. (Ich habe erfolglos versucht die Dokumentation zu verstehen.)
Da QB64 die einzige Sprache ist die ich wirklich beherrsche sollte ich nun herausfinden ob und wie dies möglich ist.

Nope, da ist nix. Auch wenn ich mich dunkel an Forumsbeitrag von Galleon selbst erinnere in dem er berichtete ein Tool geschrieben zu haben welches die Tiles bei Zelda & Co. während dem Spielen auslaß.

Egal, es muss ja nicht QB64 sein, denn was ich benötige ist eigentlich ein simples Makro. Nachdem ich erfolglos nach einer Windowsinternen Lösung gesucht und dann diverse Freeware-Programmen ausprobiert habe, widmete ich mich wieder dem QB64-Wiki und siehe da, diesmal wurde ich fündig.

SEND KEYS ⇒ erzeugt auch einen Screenshot
https://qb64.org/wiki/Windows_Libraries#Send_Keys

Wie faul bin ich? ⇒ OPEN ANOTHER PROGRAM
https://qb64.org/wiki/Windows_Libraries#Open_another_Program

Wichtig: MOUSE AREA!
https://qb64.org/wiki/Windows_Libraries#Mouse_Area

Hallo Welt!

Willkommen zur deutschen Version von WordPress. Dies ist der erste Beitrag. Du kannst ihn bearbeiten oder löschen. Und dann starte mit dem Schreiben!