Arduino GameBoy cart Reader/Writer

Introduzione:

Recentemente, rispolverando la mia collezione di retro games Nintendo, ho notato con mio grande dispiacere che alcune cartucce di gioco (ferme da più di dieci anni) risultavano completamente vuote, prive dei dati di gioco collezionati in età puerile. (all’interno delle cartucce di gioco è presente una batteria tampone che ha lo scopo di mantenere in memoria il salvataggio; quando la batteria si esaurisce, inevitabilmente si perde il salvataggio).

A quel punto sorse spontanea la domanda: come posso fare un backup dei salvataggi dei miei vecchi giochi?

Certo, esistono già dei lettori di cartucce, ma sono difficili da reperire, e spesso molto costosi… così ho optato per una soluzione più economica e amatoriale:

Arduino GameBoy cart reader/writer
Arduino GameBoy cart reader/writer

Arduino sembrava essere l’ideale per questo tipo di progetto, così tentai di costruire un mio proprio prototipo di lettore di cartucce per GameBoy.

Analisi del progetto

[ssbluelist]

  • Il primo passo verso la realizzazione del progetto è quello di aprire una cartuccia di gioco per analizzarne la struttura interna;
  • Secondo passo: estrapolare il Pinout e capire come interfacciare la cartuccia di gioco e la nostra board Arduino;
  • Terzo passo: realizzare la prima interfaccia hardware e software;
  • Quarto passo: riguarda il lato software: riuscire a leggere i dati dalla cartuccia;
  • Quindo passo: realizzare l’interfaccia software dal lato pc in modo da salvare i dati letti dal nostro Arduino;
  • Sesto passo consiste nel scrivere i dati salvati precedentemente nel computer nella cartuccia di gioco;
  • Conclusioni.

[/ssbluelist]

Primo passo: Inside the Gameboy

Per prima cosa diamo uno sguardo all’interno della cartuccia di gioco per analizzarne la struttura:

Interno della cartuccia
Interno della cartuccia

[sstoggles] [sstoggle title=”Componenti”]ROM dove sono contenuti i dati del gioco

RAM dove è contenuto il salvataggio del gioco

MBC controllo dei banchi di memoria, gestisce e alloca grandi spazi di memoria

Timer Chip mantiente la data e l’ora (presente solo in alcune cartucce)

Batteria[/sstoggle][/sstoggles]

Secondo passo: Cartridge Pinout

La cartuccia di gioco presenta un’interfaccia a 32 Pin:

cartridgepin
Cartridge pinout

[sstoggles] [sstoggle title=”PinOut”]VCC – Alimentazione (5 volts)

CLK – Clock

~WR – se Low AND RD Low, possiamo scrivere sulla SRAM

~RD – se low AND WR High, possiamo leggere la ROM e la SRAM

CS_SRAM – se abilitato, seleziona la SRAM in scrittura

A0 – A15 – 16 linee di indirizzo della ROM (a seconda della configurazione anche della SRAM ed altri componenti)

D0 – D7 – le 8 linee dati attraverso le quali leggiamo/scriviamo la ROM/SRAM.

Reset – provoca un Reset dei componenti (abilitato Low)

Audio in – (non in uso)

GND – Massa
[/sstoggle][/sstoggles]

Terzo passo: Arduino Interface

Analizzando la struttura della cartuccia e il suo pinout abbiamo visto come il GameBoy possa allocare solamente indirizzi dati a 16 bit (ricordiamo le 16 linee dati A0-A15). Questo significa (in teoria, ma vedremo che in realtà non è così) che la capacità massima di allocamento è 2^16 byte = 65,536 bytes

Dal momento che questi 16 indirizzi controllano anche l’accesso alla sRAM e a tutti gli altri componenti della cartuccia, in realtà solamente gli indirizzi compresi tra 0x0000 e 0x777f sono dedicati alla ROM  (gli indirizzi sono espressi base esadecimale), per un totale di 32,767 bytes su cui lavorare.

Il primo gioco per GameBoy mai realizzato fu “Tetris“, la cartuccia era provvista solamente di una ROM da 32,767 bytes, una quantità di spazio più che sufficiente per i giochi dell’epoca (lontano 1989).

Il GameBoy prende piede nel vecchio e nel nuovo continente, la tecnologia avanza, e 32kbyte di spazio cominciano ad essere pochi: la Nintendo introduce un nuovo chip nei suoi progetti, L’ MBC (Memory Bank Controller). Questo chip risolse totalmente il problema di spazio all’interno delle cartucce (uno standard mantenuto fino all’avvento del GameBoy Color): come ci suggerisce il nome, infatti, il circuito integrato funge da controllore di banchi di memoria; con opportuni accorgimenti e collegamenti, è in grado di pilotare ROM con 21 linee di indirizzo, allocando fino a 8Megabytes! (ultima versione MBC5)

Quello che ci rimane da fare ora è creare un collegamento tra la cartuccia e il nostro Arduino:

testboard
Prototipo su BreadBoard

Il problema più grande che ho dovuto affrontare è stato quello della mancanza dei pin: la cartuccia, come abbiamo visto, è provvista di 32 pin, mentre Arduino possiede solamente 13 pin digitali (di cui 2 usati per la trasmissione seriale) e 5 analogici, come risolvete tale problema? Shift Registers!

[ideabox]Usando due ShiftRegisters 74LS595N collegati in serie serie, siamo in grado di pilotare fino a 16 uscite digitali utilizzando solamente 2 pin digitali del nostro Arduino (i2c bus).[/ideabox]

Quarto passo: Arduino Software

Ecco forse la parte più difficile, realizzare il software Arduino: prima di tutto schematizziamo il funzionamento del nostro programma e cosa ci interessa che faccia.

  1. Arduino attende l’inserimento della cartuccia.
  2. Una volta rilevata la cartuccia procede verificando il Checksum, per decretarne la validità e il corretto inserimento
  3.  Arduino legge tutti gli attributi dell’Header (tutte le informazioni peculiari della cartuccia: nome gioco, grandezza rom, ram etc.) e le invia al computer.
  4. Il software attende in risposta dal computer uno dei seguenti comandi: Leggi ROM, Leggi sRAM, Scrivi sRam
  5. Ricomincia il ciclo del programma.

Qui un estratto dell’algoritmo usato per il Checksum (situato all’indirizzo 0x014d della ROM):

original source from TheNintendoGameboy:

 x=0:FOR i=0134h TO 014Ch:x=x-MEM[i]-1:NEXT

 from my Arduino software:
 // Wait for serial input
 while (Serial.available() <= 0) {
 //coltrollo cartuccia inserita correttamente (checksum)
 int checksum = readbank0Address(0x014D) ;
 int x = 0;
 for (int addr = 0x0134; addr <= 0x014C; addr++) {
 x = x - readbank0Address(addr) - 1 ; 
 }
 if ((x & 0xFF) == checksum) { digitalWrite(greenled, HIGH);  }
 else digitalWrite(redled, HIGH);
 delay (50) ;

Qui in Allegato il codice sorgente completo.

Quinto passo: Computer Software

Analizzato il lato Arduino, passiamo ora al lato Computer:

Ho realizzato il software computer in Phyton basandomi su quello realizzato da InsideGadgets, ampliandolo, adattandolo alla mia board Arduino e perfezionandolo.

Il software funziona nel seguente modo:

  1. Il software attende la riposta dalla board Arduino.
  2. Una volta rilevata la Board Arduino, il software invia la richiesta dell’Header della cartuccia e stampa a schermo la risposta.
  3. A questo punto l’utente può scegliere tra varie opzioni: Leggi ROM – Leggi sRAM – Scrivi sRAM – Ricomincia loop programma.
  4. Il software invia il comando ad Arduino e salva i dati con il nome di intestazione del gioco della cartuccia
  5. Ricomincia il ciclo del programma.

Qui uno screenshoot del programma in esecuzione:

screenshot

[ssbluelist]
Il necessario:

  1. Interprete python: Download
  2. Plugin python serial 2.6: Download
  3. Sorgente completa del programma per computer: Download

[/ssbluelist]

Conclusioni:

Fonti e ispiratori:

Per qualunqu dubbio o domanda non esitate a commentare 😉

Prima applicazione Windows Phone 7/8: BallsPix!

In questo articolo vi parlerò del mio primo approccio con la piattaforma Windows Phone:

BallsPix Icon
BallsPix! Logo

 

Un drastico cambio di piattaforma mi ha portato a testare nuovi framework e soluzioni; per lo sviluppo di BallsPix ho usato il framework XNA il quale, seppur non testato fino infondo, mi sento di definire promettente, sia dal lato delle possibilità di integrazione, sia dal lato delle performance (davvero incredibile!).

Lo sviluppo non si è rivelato particolarmente difficile: integrare le varie Classi di gioco è stato facile grazie all’ottima gestione del motore di gioco. Sviluppare interamente in XNA comporta però degli “svantaggi”: infatti, a differenza dell’ambiente Silverlight non avremo a disposizione il nostro pannello degli strumenti, ma dovremo creare da noi tutte le interfacce di cui abbiamo bisogno (come slider, bottoni, pannelli, textbox e quant’altro).

Microsoft-XNA-Logo
Logo XNA

Sebbene sia possibile integrare XNA con Silverlight, la scelta di usare un solo framework è stata influenzata da una ricerca di maggiori performance, a sfondo di ricerca e studio).

L’applicazione sfrutta l’accelerometro del dispositivo per modificare la fisica di gioco: le palline seguiranno l’inclinazione dello schermo andando a sbattere sui bordi e subendo il caratteristico “effetto rimbalzo” generato grazie alla gestione del vettore velocità. è inoltre possibile gestire ulteriormente la fisica del gioco interagendo con il controllo della gravità e del rimbalzo!

Enjoy yourself tapping your phone and creating infinte and colorful Balls, shake your phone and watch the balls bouncing around the screen!

You can choose between a lot of different backgrounds and balls, calibrate the sensor and set the Bouncing and Gravity Physics factors!

Take the stress off reaching the maximum number of balls on the screen!

A timer and Ball-counter are built-in

Senza ulteriori indugi vi lascio il link al MarketPlace per scaricare l’applicazione e a qualche screenshot 🙂

Scarica BallsPix! – MarketPlace

[flagallery gid=1 skin=minima_jn align=center name=Gallery]

Primo Esempio: Il bottone

In questo esempio voglio mostrarvi come collegare ed implementare nei vostri progetti un bottone:

Per prima cosa diamo un’occhiata allo schema elettrico: Il bottone presenta quattro estremità (Pin) connessi due a due da contatti interni al pulsante. Abbiamo in realtà, quindi, due contatti indipendenti che andremo a collegare. Nello schema elettrico questo corrisponde alla apertura e chiusura di un circuito: il passaggio dallo stato di quiete delle cariche, al passaggio di una corrente elettrica nel circuito. Quello che vogliamo fare è gestire la variazione di potenziale elettrico avvertita dai pin digitali del nostro microcontrollore, attuata dalla pressione del nostro bottone.

Come potete vedere, oltre al bottone, nel circuito è riportata una resistenza a massa tra il Digital Pine il bottone; questa resistenza è chiamata “resistenza in Pull-Down“, ed è necessaria al fine di mantenere lo stato logico LOW (basso) finchè il bottone non è premuto. Questo tipo di operazione è necessaria nei circuiti logici al fine di mantenere lo stato logico voluto (Low nel caso di pull-down e HIGH nel caso di pull-up) nel caso in cui si voglia interfacciare un circuito aperto ad uno logico (come in questo caso), o nel caso in cui una periferica venga scollegata dal microcontrollore.
La resistenza in pull-up/down sostanzialmente applica una debole tensione al pin dove essa è connessa.

 

Lato software:

Per quanto riguarda il software Arduino, ho scritto un software che riassuma una serie diInterruzioni applicabili all’utilizzo del nostro bottone:
Il bottone attuerà l’accensione di un led, stamperà a schemo un testo tramite porta seriale e incrementerà ad ogni pressione un contatore.

In allegato il codice sorgente: Button.ino
(clicca per ingrandire)

button_ide


Iniziamo dichiarando il pin al quale abbiamo collegato il bottone (nel nostro caso il pin digitale 4) e il LED (nel nostro caso il pin digitale 3)
Codice:

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);    
 Serial.begin(9600); 
}


Nel setup dichiariamo i pin in entrata e in uscita ed inizializziamo la porta seriale:
Codice:

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);    
 Serial.begin(9600); 
}


Nel loop, ad ogni ciclo il microcontrollore controllerà lo stato del pin digitale al quale abbiamo assegnato il bottone in ingresso, se il bottone è stato premuto allora tramite il comando digitalWriteverrà acceso il led, e tramite il comando Serial.print verrà stampata la stringa “Button“.
Inoltre verrà incrementato il valore della variabile i, e inseguito stampato a schemo.
Queste sono solo alcune delle possibilità d’uso del nostro pulsante;
Considerate il bottone come una sorgente di interrupt da impartire al microcontrollore per svolgere qualsiasi tipo di compito.

Codice:

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH); 
    // print some lines to serial port 
    Serial.print("Button");
    // increment variable i and display
    Serial.println(i);
    i++;
    //wait for 0.5 seconds
    delay(500);
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
}

 

Per qualunque chiarimento invito a lasciare un commento nel box sottostante 🙂