Escrevendo em Java para Nintendo DS

imagem

1. Introdução


Tudo começou com o fato de eu encontrar acidentalmente uma lista de programas homebrew (programas desenvolvidos pelos esforços dos usuários para dispositivos não destinados a executar software de usuário) para o Nintendo DS e vi uma linha muito interessante, a saber: “Pstros NDS - MIDP run run na máquina java CLDC compilada para NDS. "

Sendo um grande fã de Java e Nintendo DS, decidi descobrir que tipo de animal é esse e, se possível, tentar escrever meu aplicativo para essa JVM. Aqueles que estão interessados ​​em pedir um gato.

Pstros nds


Depois de baixar o arquivo estimado do site, comecei a pesquisá-lo. Depois de ler o leia-me, descobriu-se que o Pstros NDS é uma porta KVM (Java virtual machine desenvolvida pela Sun Microsystems) para o Nintendo DS. Conforme segue nos artigos na Internet ( artigo 1 , artigo 2 ), esta máquina Java foi projetada para pequenos dispositivos com uma quantidade limitada de RAM e pertence a um subconjunto de plataformas Java - J2ME.

Arquitetura J2ME


O J2ME possui uma arquitetura modular na qual configurações e perfis são os elementos principais.

Uma configuração é uma especificação que descreve as ferramentas disponíveis para o desenvolvimento de uma família específica de dispositivos móveis (um conjunto de recursos da linguagem Java, recursos e capacidades da máquina virtual, bibliotecas mínimas suportadas).

O perfil estende e complementa as funções de configuração para um dispositivo móvel específico. Permite trabalhar com uma tela gráfica, funções de comunicação, periféricos específicos (no nosso caso, é uma tela sensível ao toque).

O diagrama da arquitetura J2ME é apresentado abaixo:

imagem

Iniciar homebrew


Você não pode simplesmente executar um software não certificado da Nintendo no console. Para resolver esse problema, cartuchos flash especiais foram criados (na verdade, provavelmente eles foram criados para lançar cópias piratas de jogos, e o homebrew era um subproduto, mas a história não é sobre isso).

Existem várias opções de cartuchos de flash no AliExpress a preços acessíveis. Para mim, eu pedi o R4i Dual Core. Seu uso é extremamente simples: basta descompactar o arquivo especial na raiz microSD, fazer upload de um arquivo com uma máquina Java no formato jvm, inserir um cartucho de flash no console e você pode usá-lo.

imagem

O primeiro lançamento do KVM


Existem vários exemplos de programas java no arquivo Pstros NDS. Para executar esses programas, você precisa colocá-los em qualquer lugar do cartucho de memória microSD. Após iniciar o kvm.nds, você poderá selecionar arquivos no sistema de arquivos:

imagem

Depois de selecionar o arquivo Hello.class, veremos o seguinte:
imagem

Mais alguns exemplos de aplicativos:

imagem

imagem

Emulador


Conectar um Nintendo DS diretamente a um computador é, até onde eu sei, impossível. Cole constantemente o microSD do computador no dispositivo e volte para ver o resultado por muito tempo. Portanto, para lançamentos de teste do aplicativo, usaremos o popular emulador DeSmuME .

Existem alguns recursos no lançamento de aplicativos homebrew para o DeSmuME. Tanto quanto eu entendo a pergunta, isso decorre do problema de trabalhar com o sistema de arquivos em um cartucho flash.

Para a interação de aplicativos homebrew com o sistema de arquivos, a biblioteca libfat foi gravada. No entanto, há um grande número de cartuchos flash para o Nintendo DS, e todos eles usam comandos específicos de leitura / gravação de arquivos. A biblioteca libfat não pode reconhecer esses comandos e envia uma mensagem de erro ao aplicativo homebrew. Para evitar isso, uma tecnologia foi inventada chamada DLDI (Dynamic-Linked Device Interface). Ele atua como uma camada entre o aplicativo homebrew e o cartucho flash, convertendo comandos específicos de leitura / gravação em comandos que são compreensíveis para as bibliotecas libfat.

Ao tentar iniciar o DeSmuME kvm.nds, obtemos o seguinte erro:

imagem

As perguntas frequentes para o emulador indicam que o patch DLDI será aplicado automaticamente, mas para o acesso correto aos arquivos, você deve especificar o MPCF Flash Card Device no slot GBA, conforme mostrado na figura abaixo:

imagem

Depois disso, a JVM inicia normalmente.

Configurando o ambiente de desenvolvimento


Estudando o archive com jvm, notei o arquivo _rebuild.bat. Seu conteúdo é apresentado abaixo:

Conteúdo _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\*.* .\ 


A partir disso, fica claro como criar aplicativos para jvm e que tipo de ambiente precisamos. No site da Oracle, o arquivo contém as versões de wtk e jdk necessárias. Instale-os de acordo com os caminhos especificados no arquivo bat (ou edite os caminhos no arquivo bat) e você poderá iniciar o desenvolvimento.

Desenvolvimento de aplicações


Pela natureza do meu trabalho, trabalhei muito com a biblioteca para criar a GUI do Swing. Eu gosto desta biblioteca e, por exemplo, decidi escrever sua própria implementação. Eu decidi desenvolver com base na "caixa preta", ou seja, Sabendo como deve ficar do lado de fora, não veja como está organizado dentro. Primeiro, porque a biblioteca que planejei terá significativamente menos funcionalidades (já que a desenvolvo para fins de entretenimento) e, provavelmente, muitas das soluções usadas no Swing simplesmente não serão necessárias para mim. Em segundo lugar, criar sua própria implementação é muito mais interessante.

Como você pode ver no script de construção, você precisará desenvolvê-lo no java 1.1.

Quanto aos requisitos, antes de tudo, eu queria que o usuário da biblioteca suportasse o código Swing típico para chamar o formulário de diálogo:

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

I.e. nesse caso, o formulário da caixa de diálogo é exibido e, até que seja fechado, a execução não irá além de setVisible (true). Ao mesmo tempo, para outros componentes que estão no formulário chamado, o processamento de suas ações do usuário deve continuar.

A primeira versão do esquema de operação da biblioteca é apresentada na figura abaixo:

imagem

Como você pode ver no diagrama, cada ação do usuário é executada em um encadeamento separado. Com essa implementação, o requisito para trabalhar com formulários de diálogo é atendido, no entanto, existe um problema com o fato de o usuário em seus manipuladores poder trabalhar simultaneamente com os mesmos dados de dois threads (por exemplo, clicando rapidamente em dois botões). Isso cria inconveniência adicional associada à necessidade de proteger o acesso a esses dados pelo usuário.

Assumimos que todas as formas são interativas, ou seja, ao mostrar um formulário, é impossível trabalhar com outros formulários. Nesse caso, essa é uma suposição adequada, já que as telas do Nintendo DS não são grandes e exibir várias formas ao mesmo tempo é simplesmente inconveniente.

Nesse caso, o esquema de operação da biblioteca assume o seguinte formato:

imagem

I.e. Cada formulário cria seu próprio fluxo de processamento de ações de aplicativos do usuário. Se um novo formulário for chamado como resultado do processamento de uma ação, o thread que o chamou aguardará o fechamento do formulário e, nesse momento, um novo thread para o processamento de ações do usuário será criado.

Um código de exemplo para trabalhar com a biblioteca é apresentado abaixo:

Exemplo de trabalho
 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(); 


Como no Swing, o layout dos formulários e dos manipuladores de ação do usuário é descrito primeiro e, em seguida, o controle é transferido para a biblioteca, que inicializa o contexto e renderiza e processa cliques na tela de toque.

Outro problema que encontrei é o teclado. Infelizmente, não encontrei uma maneira de chamar o teclado na tela pronto do sistema operacional. Portanto, eu tive que fazer minha própria implementação bastante simplificada. O resultado de seu trabalho é apresentado abaixo:

imagem

Como componentes no momento, implementei apenas Label, TextField e Button. Por exemplo, penso o suficiente; a aparência do formulário descrito acima é mostrada na figura:

imagem

O código fonte completo pode ser encontrado aqui .

Iniciar em um dispositivo real


Copie os arquivos * .class obtidos como resultado da compilação em um cartucho flash, execute kvm.nds e selecione ExampleJNDSWindowsManager.class nele.

O resultado do aplicativo é apresentado no seguinte vídeo:


Conclusão


Concluindo, gostaria de agradecer aos criadores do Nintendo DS, os desenvolvedores da porta JVM do Nintendo DS, os criadores de cartuchos de flash pela oportunidade de desenvolver seu hardware favorito, bem como minha esposa pela ajuda na gravação de vídeos e na edição deste artigo.

Obrigado a todos pela atenção!

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


All Articles