Écriture en Java pour Nintendo DS

image

Présentation


Tout a commencé avec le fait que j'ai accidentellement trouvé une liste de programmes homebrew (programmes développés par les efforts des utilisateurs pour des appareils non destinés à exécuter des logiciels utilisateur) pour Nintendo DS et j'ai vu une ligne très intéressante, à savoir: «Pstros NDS - exécution de la mise en œuvre MIDP sur la machine java CLDC compilée pour NDS. "

Étant un grand fan de Java et de Nintendo DS, j'ai décidé de comprendre de quel genre de bête il s'agit et, si possible, d'essayer d'écrire mon application pour cette JVM. Ceux qui sont intéressés à demander un chat.

Pstros nds


Après avoir téléchargé les archives précieuses du site, j'ai commencé à les rechercher. Après avoir lu le fichier Lisezmoi, il s'est avéré que Pstros NDS est un port KVM (machine virtuelle Java développée par Sun Microsystems) pour la Nintendo DS. Comme il ressort des articles sur Internet ( article 1 , article 2 ), cette machine Java est conçue pour les petits appareils avec une quantité limitée de RAM et appartient à un sous-ensemble de plates-formes Java - J2ME.

Architecture J2ME


J2ME a une architecture modulaire dans laquelle les configurations et les profils sont les éléments centraux.

Une configuration est une spécification qui décrit les outils disponibles pour le développement d'une famille spécifique d'appareils mobiles (un ensemble de fonctionnalités du langage Java, les fonctionnalités et capacités des machines virtuelles, les bibliothèques prises en charge au minimum).

Le profil étend et complète les fonctions de configuration d'un appareil mobile spécifique. Il permet de travailler avec un écran graphique, des fonctions de communication, des périphériques spécifiques (dans notre cas, il s'agit d'un écran tactile).

Le schéma d'architecture J2ME est présenté ci-dessous:

image

Lancer l'homebrew


Vous ne pouvez pas simplement exécuter un logiciel non certifié Nintendo sur la console. Pour résoudre ce problème, des cartouches flash spéciales ont été créées (en fait, elles ont probablement été créées pour lancer des copies piratées de jeux, et l'homebrew était un sous-produit, mais l'histoire n'est pas à ce sujet).

Il existe de nombreuses options de cartouches flash à des prix abordables sur AliExpress. Pour ma part, j'ai commandé le R4i Dual Core. Son utilisation est extrêmement simple: il suffit de décompresser l'archive spéciale dans la racine microSD, d'y télécharger un fichier avec une machine Java au format jvm, d'insérer une cartouche flash dans la console et vous pouvez l'utiliser.

image

Le premier lancement de KVM


Il existe plusieurs exemples de programmes java dans l'archive Pstros NDS. Pour exécuter ces programmes, vous devez les placer n'importe où sur la cartouche flash microSD. Après avoir démarré kvm.nds, vous pourrez sélectionner des fichiers sur le système de fichiers:

image

Après avoir sélectionné le fichier Hello.class, nous verrons ce qui suit:
image

Quelques exemples d'applications supplémentaires:

image

image

Émulateur


Pour autant que je sache, la connexion directe d'une Nintendo DS à un ordinateur est impossible. Collez constamment la microSD de l'ordinateur à l'appareil et vice-versa pour voir le résultat, trop longtemps. Par conséquent, pour les lancements de test de l'application, nous utiliserons l'émulateur DeSmuME populaire.

Il existe certaines fonctionnalités pour lancer des applications homebrew pour DeSmuME. Pour autant que je comprends la question, cela provient du problème de travailler avec le système de fichiers sur une cartouche flash.

Pour l'interaction des applications homebrew avec le système de fichiers, la bibliothèque libfat a été écrite. Cependant, il existe un grand nombre de cartouches flash pour Nintendo DS, et elles utilisent toutes des commandes de lecture / écriture de fichiers spécifiques. La bibliothèque libfat ne peut pas reconnaître ces commandes et envoie un message d'erreur à l'application homebrew. Pour éviter cela, une technologie a été inventée appelée DLDI (Dynamically-Linked Device Interface). Il agit comme une couche entre l'application homebrew et la cartouche flash, convertissant des commandes de lecture / écriture spécifiques en commandes compréhensibles par les bibliothèques libfat.

Lorsque vous essayez de démarrer DeSmuME kvm.nds, nous obtenons l'erreur suivante:

image

La FAQ de l'émulateur indique que le patch DLDI sera appliqué automatiquement, mais pour un accès correct aux fichiers, vous devez spécifier le périphérique de carte flash MPCF dans l'emplacement GBA, comme indiqué dans la figure ci-dessous:

image

Après cela, la JVM démarre normalement.

Configuration de l'environnement de développement


En étudiant l'archive avec jvm, j'ai remarqué le fichier _rebuild.bat. Son contenu est présenté ci-dessous:

Contenu _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\*.* .\ 


À partir de là, il devient clair comment créer des applications pour jvm et de quel type d'environnement nous avons besoin. Sur le site Web d'Oracle, l'archive contient les versions de wtk et jdk dont nous avons besoin. Installez-les en fonction des chemins spécifiés dans le fichier bat (ou modifiez les chemins dans le fichier bat) et vous pouvez commencer le développement.

Développement d'applications


De par la nature de mon travail, j'ai beaucoup travaillé avec la bibliothèque pour créer l'interface graphique Swing. J'aime cette bibliothèque, donc à titre d'exemple, j'ai décidé d'écrire sa propre implémentation. J'ai décidé de développer sur la base de la "boîte noire", c'est à dire Sachant à quoi il doit ressembler à l'extérieur, ne regardez pas comment il est disposé à l'intérieur. Premièrement, parce que la bibliothèque que j'ai planifiée aura beaucoup moins de fonctionnalités (car je la développe à des fins de divertissement) et, probablement, de nombreuses solutions utilisées dans Swing ne seront tout simplement pas nécessaires pour moi. Deuxièmement, proposer votre propre implémentation est beaucoup plus intéressant.

Comme vous pouvez le voir dans le script de construction, vous devrez le développer sous java 1.1.

En ce qui concerne les exigences, tout d'abord, je voulais que l'utilisateur de la bibliothèque prenne en charge le code Swing typique pour appeler le formulaire de dialogue:

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

C'est-à-dire dans ce cas, le formulaire de dialogue est affiché et jusqu'à ce qu'il soit fermé, l'exécution ne dépassera pas setVisible (true). Dans le même temps, pour les autres composants qui se trouvent sur le formulaire appelé, le traitement de leurs actions utilisateur doit se poursuivre.

La première version du schéma de fonctionnement de la bibliothèque est présentée dans la figure ci-dessous:

image

Comme vous pouvez le voir sur le diagramme, chaque action utilisateur est effectuée dans un thread distinct. Avec cette implémentation, l'exigence de travailler avec des formulaires de dialogue est remplie, cependant, il y a un problème avec le fait que l'utilisateur dans ses gestionnaires peut travailler simultanément avec les mêmes données à partir de deux threads (par exemple, en cliquant rapidement sur deux boutons). Cela crée des inconvénients supplémentaires associés à la nécessité de protéger l'accès à ces données pour l'utilisateur.

Nous supposons que toutes les formes sont interactives, c'est-à-dire lors de l'affichage d'un formulaire, il est impossible de travailler avec d'autres formulaires. Dans ce cas, c'est une hypothèse adéquate, car les écrans Nintendo DS ne sont pas grands, et afficher plusieurs formes à la fois est tout simplement gênant.

Dans ce cas, le schéma de fonctionnement de la bibliothèque prend la forme suivante:

image

C'est-à-dire Chaque formulaire crée son propre flux de traitement des actions de l'application utilisateur. Si un nouveau formulaire est appelé à la suite du traitement d'une action, le thread qui l'a appelé attend la fermeture du formulaire et à ce moment un nouveau thread pour le traitement des actions utilisateur est créé.

Un exemple de code pour travailler avec la bibliothèque est présenté ci-dessous:

Exemple de travail
 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(); 


Comme dans Swing, la présentation des formulaires et des gestionnaires d'action utilisateur sont d'abord décrits, puis le contrôle est transféré à la bibliothèque, qui initialise le contexte et rend et traite les clics sur l'écran tactile.

Un autre problème que j'ai rencontré est le clavier. Malheureusement, je n'ai pas trouvé de moyen d'appeler le clavier à l'écran prêt à l'emploi du système d'exploitation. J'ai donc dû en faire moi-même une implémentation très simplifiée. Le résultat de son travail est présenté ci-dessous:

image

En tant que composants pour le moment, je n'implémentais que Label, TextField et Button. Par exemple, je pense assez; l'apparence de la forme décrite ci-dessus est représentée sur la figure:

image

Le code source complet peut être trouvé ici .

Lancer sur un vrai appareil


Copiez les fichiers * .class obtenus à la suite de la compilation sur une cartouche flash, exécutez kvm.nds et sélectionnez ExampleJNDSWindowsManager.class dedans.

Le résultat de l'application est présenté dans la vidéo suivante:


Conclusion


En conclusion, je voudrais remercier les créateurs de Nintendo DS, les développeurs du port JVM pour Nintendo DS, les créateurs de cartouches flash pour l'opportunité de développer pour leur matériel préféré, ainsi que ma femme pour son aide dans le tournage de vidéos et l'édition de cet article.

Merci à tous pour votre attention!

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


All Articles