Mini2440 – Emulando Atari com Linux embarcado
- por Sergio Prado
Nesta nossa área cheia de novidades e desafios constantes, fica difícil acompanhar tudo o que acontece sem realmente gostar e se divertir com o trabalho. Sempre que eu preciso encarar um novo desafio (seja pessoal ou profissional), é aí que busco minhas forças. Paixão pelo trabalho é fundamental para manter a disciplina e buscar aquela energia extra que realmente faz a diferença.
E seguindo esta filosofia de “aprendizado com diversão”, pensei no que ainda poderia explorar no kit FriendlyARM mini2440, que não tivesse sido feito, e que fosse desafiador, estimulante e divertido.
Tive então a idéia de emular o Atari 2600. Sim, aquele console antigo, mas que (pelo menos para mim) traz boas lembranças dos tempos de infância. Minha idéia foi transformar a mini2440 em um console Atari 2600, usando um display LCD de 3.5″ como saída de vídeo, um joystick USB como controle e um cartão SD para ler as ROMs (jogos).
Escolhi usar o Stella (http://stella.sourceforge.net/), um emulador de Atari multi-plataforma e liberado sob a licença GPL. Meu primeiro passo foi dar uma olhada nos pré-requisitos do projeto, que basicamente são estes:
-
Requisitos de Hardware
- 32M de RAM: OK, o kit tem 64M.
- Display gráfico de 16 bits: o display é de 3.5″ e suporta modo gráfico de 16 bits.
- Entrada para joystick: temos a porta USB.
- Arquitetura i386, MIPS, PPC: Ops, nada de ARM? Será que funciona?
-
Requisitos de software:
- Linux 2.6: OK!
- GNU C++ 4.x: precisaremos habilitar a toolchain C++ no Buildroot.
- SDL V1.2.10 ou maior: precisaremos habilitar o SDL no Buildroot.
Não me parecia nada de outro mundo. Escolhi o Buildroot como sistema de build para gerar minha imagem final. Bastaria seguir este meu artigo, configurar e adicionar o pacote do Stella, e habilitar algumas opções adicionais, como toolchain C++ e a biblioteca SDL.
NEM TUDO SÃO ROSAS
Pois é, nem tudo são rosas. O que achei que levaria uma tarde me tomou muito mais tempo. Nada funcionou de primeira. Quer uma lista de alguns desafios que encontrei?
1. O vídeo não renderizava em modo paisagem. O driver de framebuffer do display LCD suportava apenas 240×320, enquanto que o Stella roda apenas com resoluções a partir de 320×240. Depois de dias debugando e estudando o driver do display, a biblioteca SDL e a aplicação Stella, encontrei uma solução bem simples: setar uma variável de ambiente usada pela biblioteca SDL para rotacionar o display! Sim, foram dias de análise para resolver o problema com uma linha de código em shell script! Mas no fim, adquiri bastante conhecimento na camada de vídeo do Linux.
$ export SDL_VIDEO_FBCON_ROTATION=CW |
2. Com a correção da renderização do vídeo, causei um problema com o touchscreen. Como eu rotacionei o display, os valores lidos pelo touch ficaram deslocados. Precisei escrever um patch que fizesse esse hack na biblioteca SDL.
--- sdl-1.2.14-orig/src/video/fbcon/SDL_fbevents.c 2009-10-12 20:07:15.000000000 -0300 +++ sdl-1.2.14/src/video/fbcon/SDL_fbevents.c 2011-04-23 16:20:31.623212774 -0300 @@ -741,11 +741,14 @@ static void handle_tslib(_THIS) { struct ts_sample sample; - int button; + int button, aux; while (ts_read(ts_dev, &sample, 1) > 0) { button = (sample.pressure > 0) ? 1 : 0; button <<= 2; /* must report it as button 3 */ + aux = 240 - sample.x; + sample.x = sample.y; + sample.y = aux; FB_vgamousecallback(button, 0, sample.x, sample.y); } return; |
3. Também tive problemas com o som, que não funcionava com o driver padrão em modo OSS. Resolvi o problema habilitando o biblioteca ALSA no Buildroot, e criando alguns links simbólicos para os arquivos de dispositivo do driver de som.
Package Selection for the target Audio and video libraries and applications [*] alsa-lib |
$ mkdir -p /dev/snd/ $ ln -s /dev/pcmC0D0c /dev/snd/pcmC0D0c $ ln -s /dev/pcmC0D0p /dev/snd/pcmC0D0p $ ln -s /dev/controlC0 /dev/snd/controlC0 $ ln -s /dev/timer /dev/snd/timer $ chmod 0660 /dev/pcmC0D0c $ chmod 0660 /dev/pcmC0D0p $ chmod 0660 /dev/controlC0 $ chmod 0660 /dev/timer |
Para testar o som com a biblioteca ALSA:
$ aplay /usr/share/sounds/alsa/Front_Center.wav |
4. O joystick funcionou de primeira, mas estranhamente causava erro de segmentação de memória na aplicação Stella ao tentar usar o direcional. Então descobri que precisava habilitar a interface de joystick no kernel.
Device Drivers Input device support [*] Joystick interface [*] Joysticks/Gamepads [*] Classic PC analog joysticks and gamepads |
5. Além disso, enfrentei alguns pequenos desafios como colocar o pacote Stella no Buildroot (desenvolvi um patch para corrigir um erro de cross-compilação). Também precisei habilitar e configurar o hotplug no kernel o mdev no Buildroot para identificar e montar automaticamente o cartão SD no boot.
Realmente foi um projeto que deu trabalho, mas é o tipo de experiência que vale a pena, pois é um aprendizado não se consegue apenas lendo livros ou artigos na internet.
No final, criei um script para facilitar todo o processo para quem também quiser “brincar”. Disponibilizei este script, junto com todos os arquivos necessários para compilar e gerar a imagem, em um projeto no github, que pode ser acessado aqui.
GERANDO A IMAGEM
Para gerar a imagem, execute os comandos abaixo:
$ git clone git://github.com/sergioprado/Mini2440-Atari-System.git $ cd Mini2440-Atari-System $ ./prepare.sh $ cd buildroot-2011.02/ $ make |
O processo de compilação deve levar de 1 a 2 horas, dependendo da sua máquina. Após compilar, você terá disponível em output/images as imagens do kernel e do rootfs disponíveis:
$ ls output/images/ rootfs.ext2 rootfs.jffs2 rootfs.tar uImage |
Para gravar o kernel e o rootfs, você pode se basear neste artigo aqui. Mude apenas a configuração da variável “bootargs” do U-Boot, conforme abaixo:
MINI2440 # setenv bootargs 'root=/dev/mtdblock3 rootfstype=jffs2 console=ttySAC0,115200 mini2440=3tb' MINI2440 # saveenv |
TESTANDO
No primeiro boot, você precisará configurar a interface touchscreen, pressionando a caneta nos pontos indicados pela ferramenta de configuração. Após configurar o touchscreen, a aplicação Stella já inicia automaticamente, e você poderá configurar seu joystick em “Options->Input Settings” se quiser.
Depois, escolha um jogo e divirta-se! Estes são os meus favoritos:
Obs: Não quero entrar aqui nos méritos legais de usar um emulador com ROMs. Apenas para constar, você precisa ter o jogo para poder baixar a ROM e usá-la em um emulador.
Gravei também um vídeo onde podemos ver o boot da mini2440 e alguns jogos em ação. Só não reclamem das habilidades do jogador! Coloquei minha esposa para jogar enquanto gravava. O problema foi tirar o controle dela depois… :)
E para concluir, o que podemos tirar de aprendizado neste projeto?
Primeiramente, se você quer aprender, precisa colocar a mão na massa! Só assim para transformar seu conhecimento em habilidades. Com um pouco de criatividade, disciplina e persistência, você consegue aprender coisas que talvez não aprenderia em um emprego formal.
Em segundo lugar, perceba a importância do código livre para este projeto. Tudo o que fiz foi usando software e ferramentas de código aberto. Ter em mãos o código do kernel do Linux e das bibliotecas foi essencial para solucionar alguns dos problemas que encontrei no meio do caminho. Escrevendo este artigo, disponibilizando o projeto e motivando as pessoas a fazerem o mesmo, espero estar contribuindo de volta com a comunidade.
Um abraço!
Sergio Prado