Schreiben in Java für Nintendo DS

Bild

Einführung


Alles begann mit der Tatsache, dass ich versehentlich eine Liste von Homebrew-Programmen (Programme, die von Benutzern für Geräte entwickelt wurden, auf denen keine Benutzersoftware ausgeführt werden soll) für Nintendo DS gefunden habe, und ich sah darin eine sehr interessante Zeile: „Pstros NDS - MIDP-Implementierungslauf auf dem für NDS kompilierten CLDC-Java-Rechner. "

Als großer Fan von Java und Nintendo DS habe ich mich entschlossen herauszufinden, was für ein Biest das ist, und wenn möglich zu versuchen, meine Anwendung für diese JVM zu schreiben. Diejenigen, die daran interessiert sind, nach einer Katze zu fragen.

Pstros nds


Nachdem ich das wertvolle Archiv von der Website heruntergeladen hatte, begann ich, es zu recherchieren. Nach dem Lesen der Readme-Datei stellte sich heraus, dass Pstros NDS ein KVM-Port (Java Virtual Machine, entwickelt von Sun Microsystems) für den Nintendo DS ist. Wie aus Artikeln im Internet ( Artikel 1 , Artikel 2 ) hervorgeht, ist diese Java-Maschine für kleine Geräte mit begrenztem RAM ausgelegt und gehört zu einer Untergruppe von Java-Plattformen - J2ME.

J2ME-Architektur


J2ME verfügt über eine modulare Architektur, in der Konfigurationen und Profile die Kernelemente sind.

Eine Konfiguration ist eine Spezifikation, die die verfügbaren Tools für die Entwicklung für eine bestimmte Familie mobiler Geräte beschreibt (eine Reihe von Java-Sprachfunktionen, Funktionen und Funktionen für virtuelle Maschinen, minimal unterstützte Bibliotheken).

Das Profil erweitert und ergänzt die Konfigurationsfunktionen für ein bestimmtes mobiles Gerät. Es ermöglicht die Arbeit mit einem Grafikdisplay, Kommunikationsfunktionen und bestimmten Peripheriegeräten (in unserem Fall ist dies ein Touchscreen).

Das J2ME-Architekturdiagramm ist unten dargestellt:

Bild

Starten Sie Homebrew


Sie können nicht einfach nicht zertifizierte Nintendo-Software auf der Konsole ausführen. Um dieses Problem zu lösen, wurden spezielle Flash-Kassetten erstellt (höchstwahrscheinlich wurden sie erstellt, um Raubkopien von Spielen zu starten, und Homebrew war ein Nebenprodukt, aber in der Geschichte geht es nicht darum).

Bei AliExpress gibt es viele Optionen für Flash-Kassetten zu erschwinglichen Preisen. Für mich selbst habe ich den R4i Dual Core bestellt. Die Verwendung ist äußerst einfach: Entpacken Sie einfach das spezielle Archiv in das microSD-Stammverzeichnis, laden Sie dort eine Datei mit einem Java-Computer im JVM-Format hoch, legen Sie eine Flash-Kassette in die Konsole ein und Sie können sie verwenden.

Bild

Der erste Start von KVM


Es gibt mehrere Beispiele für Java-Programme im Pstros NDS-Archiv. Um diese Programme auszuführen, müssen Sie sie an einer beliebigen Stelle auf der microSD-Flash-Kassette ablegen. Nach dem Start von kvm.nds können Sie Dateien im Dateisystem auswählen:

Bild

Nachdem wir die Datei Hello.class ausgewählt haben, sehen wir Folgendes:
Bild

Einige weitere Beispielanwendungen:

Bild

Bild

Emulator


Es ist meines Wissens unmöglich, einen Nintendo DS direkt an einen Computer anzuschließen. Kleben Sie microSD ständig vom Computer auf das Gerät und zurück, um das Ergebnis zu lange zu sehen. Daher werden wir für Teststarts der Anwendung den beliebten DeSmuME- Emulator verwenden.

Es gibt einige Funktionen beim Starten von Homebrew-Anwendungen für DeSmuME. Soweit ich die Frage verstehe, ist dies auf das Problem zurückzuführen, mit dem Dateisystem auf einer Flash-Kassette zu arbeiten.

Für die Interaktion von Homebrew-Anwendungen mit dem Dateisystem wurde die libfat-Bibliothek geschrieben. Es gibt jedoch eine große Anzahl von Flash-Kassetten für Nintendo DS, die alle bestimmte Lese- / Schreibbefehle für Dateien verwenden. Die libfat-Bibliothek kann diese Befehle nicht erkennen und sendet eine Fehlermeldung an die Homebrew-Anwendung. Um dies zu vermeiden, wurde eine Technologie namens DLDI (Dynamically-Linked Device Interface) erfunden. Es fungiert als Schicht zwischen der Homebrew-Anwendung und der Flash-Kassette und konvertiert bestimmte Lese- / Schreibbefehle in Befehle, die für libfat-Bibliotheken verständlich sind.

Beim Versuch, DeSmuME kvm.nds zu starten, wird der folgende Fehler angezeigt:

Bild

Die FAQ für den Emulator geben an, dass der DLDI-Patch automatisch angewendet wird. Für den korrekten Zugriff auf die Dateien müssen Sie jedoch das MPCF-Flash-Kartengerät im GBA-Steckplatz angeben, wie in der folgenden Abbildung dargestellt:

Bild

Danach startet die JVM normal.

Einrichten der Entwicklungsumgebung


Als ich das Archiv mit jvm studierte, bemerkte ich die Datei _rebuild.bat. Sein Inhalt ist unten dargestellt:

Inhalt _rebuild.bat
SET WTKDIR=c:/wtk22 SET CP=%WTKDIR%/lib/cldcapi10.jar;%WTKDIR%/lib/midpapi20.jar;./classes.zip del .\output\*.* /Q "c:/program files/java/jdk1.5.0_06/bin/javac.exe" -source 1.3 -target 1.1 -bootclasspath %CP% ./src/*.java %WTKDIR%/bin/preverify -classpath %CP% ./src del .\src\*.class /Q copy output\*.* .\ 


Daraus wird deutlich, wie Anwendungen für JVM erstellt werden und welche Art von Umgebung wir benötigen. Auf der Oracle-Website enthält das Archiv die Versionen von wtk und jdk, die wir benötigen. Installieren Sie sie gemäß den in der Bat-Datei angegebenen Pfaden (oder bearbeiten Sie die Pfade in der Bat-Datei), und Sie können mit der Entwicklung beginnen.

Anwendungsentwicklung


Aufgrund meiner Arbeit habe ich viel mit der Bibliothek zusammengearbeitet, um die Swing-GUI zu erstellen. Ich mag diese Bibliothek, deshalb habe ich mich als Beispiel entschieden, eine eigene Implementierung zu schreiben. Ich entschied mich, auf der Basis der "Black Box" zu entwickeln, dh Wenn Sie wissen, wie es draußen aussehen soll, schauen Sie nicht darauf, wie es innen angeordnet ist. Erstens, weil die von mir geplante Bibliothek deutlich weniger Funktionen hat (da ich sie zu Unterhaltungszwecken entwickle) und wahrscheinlich viele der in Swing verwendeten Lösungen für mich einfach nicht benötigt werden. Zweitens ist es viel interessanter, eine eigene Implementierung zu entwickeln.

Wie Sie dem Build-Skript entnehmen können, müssen Sie es unter Java 1.1 entwickeln.

In Bezug auf die Anforderungen wollte ich zunächst, dass der Bibliotheksbenutzer den typischen Swing-Code zum Aufrufen des Dialogformulars unterstützt:

 MyDialogForm myDialogForm = new MyDialogForm(this, true); myDialogForm.setVisible(true); if (myDialogForm.getAnsewer()) { // TODO - do something here } 

Das heißt, In diesem Fall wird das Dialogformular angezeigt. Bis es geschlossen wird, geht die Ausführung nicht über setVisible (true) hinaus. Gleichzeitig sollte für andere Komponenten, die sich im aufgerufenen Formular befinden, die Verarbeitung ihrer Benutzeraktionen fortgesetzt werden.

Die erste Version des Bibliotheksbetriebsschemas ist in der folgenden Abbildung dargestellt:

Bild

Wie Sie dem Diagramm entnehmen können, wird jede Benutzeraktion in einem separaten Thread ausgeführt. Mit dieser Implementierung wird die Voraussetzung für die Arbeit mit Dialogformularen erfüllt. Es besteht jedoch ein Problem damit, dass der Benutzer in seinen Handlern gleichzeitig mit denselben Daten aus zwei Threads arbeiten kann (z. B. durch schnelles Drücken von zwei Schaltflächen). Dies schafft zusätzliche Unannehmlichkeiten, die mit der Notwendigkeit verbunden sind, den Zugriff auf solche Daten für den Benutzer zu schützen.

Wir gehen davon aus, dass alle Formen interaktiv sind, d. H. Wenn ein Formular angezeigt wird, ist es unmöglich, mit anderen Formularen zu arbeiten. In diesem Fall ist dies eine angemessene Annahme, da die Nintendo DS-Bildschirme nicht groß sind und die gleichzeitige Anzeige mehrerer Formulare einfach unpraktisch ist.

In diesem Fall hat das Bibliotheksoperationsschema die folgende Form:

Bild

Das heißt, Jedes Formular erstellt einen eigenen Ablauf für die Verarbeitung von Benutzeranwendungsaktionen. Wenn ein neues Formular als Ergebnis der Verarbeitung einer Aktion aufgerufen wird, wartet der Thread, der es aufgerufen hat, auf das Schließen des Formulars. Zu diesem Zeitpunkt wird ein neuer Thread zum Verarbeiten von Benutzeraktionen erstellt.

Ein Beispielcode für die Arbeit mit der Bibliothek ist unten dargestellt:

Arbeitsbeispiel
 JNDSComponentsForm jNDSComponentsForm = new JNDSComponentsForm(); jNDSComponentsForm.setTitle("Main form"); final JNDSLabel jndsLabel = new JNDSLabel("Simple label", 20, 30); jNDSComponentsForm.addComponent(jndsLabel); JNDSTextField jndsTextField = new JNDSTextField("Hello world", 20, 58, 150); jNDSComponentsForm.addComponent(jndsTextField); JNDSButton jndsButtonDialogForm = new JNDSButton("Show dialog form", 20, 90); JNDSAction jndsActionImplDialogForm = new JNDSAction() { public void action() { final JNDSDialogForm jndsDialogForm = new JNDSDialogForm(); jndsDialogForm.setTitle("Dialog form"); JNDSButton jndsButtonClose = new JNDSButton("Close", 10, 130); jndsButtonClose.setClickAction(new JNDSAction() { public void action() { jndsDialogForm.setVisible(false); } }); jndsDialogForm.addComponent(jndsButtonClose); JNDSLabel jndsLabelDialogForm = new JNDSLabel("This is Dialog Form!", 70, 80); jndsDialogForm.addComponent(jndsLabelDialogForm); jndsDialogForm.setVisible(true); } }; jndsButtonDialogForm.setClickAction(jndsActionImplDialogForm); jNDSComponentsForm.addComponent(jndsButtonDialogForm); jNDSComponentsForm.setVisible(true); JNDSWindowsManager.instance().run(); 


Wie in Swing wird zuerst das Layout von Formularen und Benutzeraktionshandlern beschrieben, und dann wird die Steuerung an die Bibliothek übertragen, die den Kontext initialisiert und Klicks auf dem Touchscreen rendert und verarbeitet.

Ein weiteres Problem, auf das ich gestoßen bin, ist die Tastatur. Leider habe ich keine Möglichkeit gefunden, die vorgefertigte Bildschirmtastatur des Betriebssystems aufzurufen. Daher musste ich meine eigene, stark vereinfachte Implementierung durchführen. Das Ergebnis ihrer Arbeit ist unten dargestellt:

Bild

Als Komponenten habe ich momentan nur Label, TextField und Button implementiert. Zum Beispiel denke ich genug; Das Aussehen der oben beschriebenen Form ist in der Abbildung dargestellt:

Bild

Den vollständigen Quellcode finden Sie hier .

Starten Sie auf einem realen Gerät


Wir kopieren die * .class-Dateien, die als Ergebnis der Kompilierung erhalten wurden, auf die Flash-Kassette, führen kvm.nds aus und wählen darin ExampleJNDSWindowsManager.class aus.

Das Ergebnis der Anwendung wird im folgenden Video dargestellt:


Fazit


Abschließend möchte ich den Entwicklern von Nintendo DS, den Entwicklern des JVM-Ports für Nintendo DS, den Entwicklern von Flash-Kassetten für die Möglichkeit, für ihre Lieblingshardware zu entwickeln, sowie meiner Frau für ihre Hilfe beim Aufnehmen von Videos und Bearbeiten dieses Artikels danken.

Vielen Dank für Ihre Aufmerksamkeit!

Source: https://habr.com/ru/post/de468971/


All Articles