Programmazione Homebrew Wii, Basi per la programmazione Homebrew Wii

« Older   Newer »
  Share  
ryujiandy
view post Posted on 14/1/2009, 17:40




Installazione dell'ambiente di lavoro.

Per cominciare serve l'ambiente di lavoro con librerie e compilatori, nel caso degli homebrew per wii è il DevkitPRO, che a sua volta per comodità lo dividiamo in 3 parti essenziali, il compilatore (DevkitPRO), le librerie (libogc) e gli esempi.
Il linguaggio base che si utilizza per la programmazione è il C e C++, quindi non si può pensare di alzarsi una mattina e creare un programma Homebrew, ma si necessita di una conoscenza della struttura e di come funzionano i linguaggi di programmazione.

Installazione DevKitPRO su linux:
La struttura tree dell'ambiente è semplice da creare e non vi è una locazione fissa da seguire l'importante che ci sia una gerarchia ben precisa nelle varie parti dell'ambiente:

DevKitPRO
devkitPPC
wii-examples
wiiload
libogc


La cartella DevKitPRO la si può creare sia nella propria home o come sorgente di sistema nella cartella opt l'importante è che durante il settaggio di .bashrc viene indicato l'indirizzo assoluto come riportato da esempio:

~/.bashrc:
CODICE
export DEVKITPRO=/[color=#0000BF](percorso)[/color]/devkitPRO # sostituire il presente con il tuo percorso effettivo
export DEVKITPPC=$DEVKITPRO/devkitPPC
PATH=$PATH:$DEVKITPPC/bin
PATH=$PATH:$DEVKITPRO/wiiload/lin32

export WIILOAD=tcp:192.168.1.10 # sostituire con il tuo Wii IP (opzionale)



Poi basta riavviare l'applicazione digitando su terminale:
CODICE
source ~/.bashrc



Ora per vedere se il tutto è andato a buon fine si può provare a compilare un esempio aprendo il terminale:
CODICE
cd /(percorso)/devkitPRO/wii-examples/template


e dando il comando:
CODICE
make


se avete settato nel bashrc il wiiload avete la possibilità di inviare direttamente il programma già compilato
direttamente sul vostro Wii dando il comando da terminale:
CODICE
make run


Installazione DevKitPRO su Windows:
Per installare l'ambiente di lavoro su windows per fortuna si dispone di un programma che ci semplifica molto lavoro infatti basta scaricare:
DevKitPRO Win32

Vi premetto che purtroppo io non lavoro volentieri con win32 per questo siete costretti a trovarvi da soli la documentazione necessaria per l'installazione dell'ambiente.

Se vuoi scaricare il tutorial clicca qui

Ciriciao e al prossimo tutorial.

Makefile, basi di C

Questo secondo tutorial riguarderà makefile, una base molto importante per la compilazione del linguaggio di programmazione C, utilizzando il modello di esempio trovati in DevKitPro impareremo a trattare con errori di compilazione.

Quando si sta compilando il codice sorgente, il programma deve sapere ciò che per la compilazione serve, le librerie per includere opzioni di compilazione, ottimizzazioni, ecc, e questo è ciò che un makefile è utilizzato.

Makefile
Un Makefile si trova di solito nella directory principale del codice sorgente che avete. Prendiamo il codice sorgente del modello GameCube di esempio:
/(percorso)/devkitPRO/wii-examples/gamecube/template
In questa directory si vedrà un file di nome "Makefile". Se si apre con NotePad, sarete in grado di vedere le diverse parti di un makefile.

La parte più importante di un makefile per questa esercitazione è la seguente righa:


CODICE
include $(DEVKITPPC)/gamecube_rules


Con "gamecube_rules" stiamo dicendo al nostro compilatore che il codice sorgente scelto per la compilazione verrà eseguito sul GameCube. Basta cambiare in "wii_rules" per compilare su Wii.
In pratica cambiando il parametro del tipo di compilazione non facciamo altro che interagire su libbrerie di file che ci aiutano con codici già pronti ad interagire con la nostra wii o gamecube che sia.


CODICE
SOURCES     :=    source
DATA        :=    data


Queste due righe vanno ad indicare la locazione del nostro codice (/source) e la locazione dei file aggiuntivi tipo immagini, video o musiche che andiamo ad utilizare (/data) per la compilazione dell'applicazione


CODICE
LIBS    :=    -logc –lm


Questa è una riga molto importante perchè indica le librerie aggiuntive che servono alla compilazione del nostro codice.
Ad Esempio se il nostro codice utilizza una musica in mp3 noi dobbiamo indicare al compilatore la libreria da utilizza in questo caso "lmad"


CODICE
LIBS    :=    -lmad -logc –lm

L'ordine di come includere le tue librerie è importante, anche come alcune librerie di riferimento e se non le hai nel giusto ordine, il compilatore si lamenta.

Nozioni di programmazione C

Quindi, abbiamo rapidamente visto le parti più importanti di makefile, ora siamo pronti ad imparare alcune basi del linguaggio di programmazione C (che è di natura simile alla maggior parte degli altri linguaggi di programmazione). Se volete imparare molto di più sulla programmazione C vi consiglio di guardarvi un po' in rete per trovare qualche manuale in modo da saperne di più (ma molto probabilmete vedrò in futuro di farne uno io).

In primo luogo vediamo di capire cosa siano le variabili. Una variabile, come suggerisce il nome è un simbolo che può cambiare il suo valore. Nell'esempio qui sotto si vede come si assegna alla variabile test un valore numerico intero "0".


CODICE
int test = 0;


Ci sono diversi tipi di variabili in C, che comprendono:

1) Booleano può essere vero o falso. Ad esempio
CODICE
bool test = false;


2) int/long è intero che può variare da -2147483648 a 2147483648. Ad esempio
CODICE
int test = 5;


3) float è un valore numerico con decimali variabili e comprende tra /- 3.4e +/- 38 (~7 decimali). Ad Esempio
CODICE
float test = 3.14159;


4) double è un altro valore decimale comprendente un dalore da +/- 1.7e a +/- 308 (~15 decimali). Ad esempio
CODICE
double test = 3.1415926535897;


5) char sta ad indicare i caratteri ASCII. Ad esempio
CODICE
char test = "a";


Un'altra parte importante sono gli operatori di confronto e i cicli (if, else, while e for)

CODICE
int test = 5;
if (test == 5) { //istruzioni }
else { //oppure istruzioni }


In questo esempio vediamo come settiamo ad una variabile intera "test" il valore di "5" e poi con l'operatore di confronto "if" facciamo eseguire un' "//istruzione" se il valore è uguale "==" a "5" nel caso in cui settiamo la variabile ad un'altro valore come ad esempio "4" allora il confronto non risulta più vero e quindi viene eseguita tramite "else", "//oppure istruzioni".
Da notare che il nostro programma esegue tutte le istruzioni dell'operatore di confronto racchiuse tra le parentesi graffe e nel caso che il confronto non sia vero, verranno eseguite le istruzioni racchiuse nelle parentesi graffe dopo "else".
Da ricordare ancora che le istruzioni che vengono dopo "//" non verranno eseguite perchè il compilatore le interpreta come delle righe di commento.
Il doppio segno uguale (==) è ciò che noi chiamiamo un operatore. Ci sono molti operatori, alcuni includono:
<= Mezzo inferiore o uguale a
>= Significa più o uguale a
!= Significa non uguale a


CODICE
int test = 0;
while (test < 5) {
     printf(“ok”);
     test++
}


In quest'altro esempio vedremo il funzionamento del ciclo "while", esso dopo che abbiamo definito la variabile sempre intera di "test" non fa altro che ripetere un ciclo, da notare nuovamente le parentesi graffe, finchè il confronto di "test" rimane inferiore a "5".
L'istruzione "printf" non farà altro che stampare su video la scritta racchiusa tra virgolette nel caso di caratteri alfanumerici oppure si può stampare su video il valore di test tramite la funzione "printf"


CODICE
printf ("test=", test);


Infine per far terminare il ciclo dobbiamo incrementare il valore di test tramite l'istruzione "test++" che equivale ad "test=test+1;".

Il ciclo for è simile al ciclo while, tranne che si saprà prima di entrare nel circuito, quante volte ci verrà eseguito il ciclo.


CODICE
int test;
for (test = 0; test < 5; test++) {
     printf(“ok”);
}

Da notare in questo esempio dopo aver definito la variabile "test" non gli abbiamo assegnato un valore, questo perchè nel ciclo "for" gli viene assegnato il valore di partenza "0", poi c'è il confronto, questo finchè vero verrà eseguito il ciclo di istruzioni sempre racchiuso nelle parentesi graffe, ed infine l'incremento.

Ora mi sembra il momento di spiegare le basi delle array, un array può essere definito come una "collezione organizzata di oggetti".
Forse facendo un paio di esempi sarà più facile capire


CODICE
int miaarray[50];
miaarray[0] = 1234;


Come sempre definiamo che tipo di variabile array e la quantità di array che intediamo usare, e poi possiamo cominciare a dare i vari valori, notate che la prima array ha il valore "0" ed è sempre tra parentesi quadre.
Un altro modo di definire le array è:


CODICE
int miaarray[50] = {1234, 0, 89, 55};


Come potete notare in una sola riga ho definito il tipo di array, la quantità e ho già inserito i primi 4 valori.
Da ricordare che il numero delle array definito è sempre il valore scritto più "1", questo perchè la prima parte da "0".

Un altro elemento importante sono le funzioni, queste ci aiutano a risparmiare nella stesura del programma, facendo come al solito un esempio, vediamo come possiamo creare una funzione che ci risparmi la stampa su schermo di "ok"

CODICE
void miafunzione () {
     printf(“ok”);
}


per richiamare la nostra funzione basta scrivere:


CODICE
miafunzione();


In questo modo possiamo richiamare la funzione ogniqualvolta sia necessario.
Nel caso invece si voglia stampare il valore di una variabile il nostro programma si presenterà in questo modo:


CODICE
int miafunzione (int numero) {
     printf(“%­i”, numero);
     return numero;
}


Come potete vedere questo caso di funzione (un po' più complesso), non fa altro che stamparci a video il valore della variabile "numero" quando viene richiamata tramite la funzione:


CODICE
miafunzione(5);


Quindi ho assegnato il valore "5" alla nostra variavile "numero" ed il risultato sarà la stampa di "5".
Sicuramente vi state chiedendo cosa vuol dire "%­i", è il cambiamento tipo della variabile. Qui sotto vi elenco i vari tipi di cambiamento che sono possibili:
%d, %­i Intero decimale
%f Valore in virgola mobile
%c Un carattere
%­s Una stringa di caratteri
%­o Numero ottale
%­x, %­X Numero esadecimale
%­u Intero senza segno
%f Numero reale (float o double)
%e, %E Formato scientifico
%% Stampa il carattere %

Credo che per il momento possa bastare visto che in fondo mi sono protratto anche più del dovuto, nella prossiama diciamo così "lezione" cercherò di spiegare come creare il nostro primo programma basandoci sugli esempii Wii.

Se voui scaricare il tutorial clicca qui
 
Top
ryujiandy
view post Posted on 15/1/2009, 10:35




Leggere il codice sorgente

Dopo aver visto le basi della programmazione C, siamo finalmente pronti a compilare il nostro primo programma Homebrew, comunque vi consiglio di ricercare un po' in internet guide più dettagliate sulla programmazione C, questo perchè sia per motivi di spazio che di tempo vi ho solo riassunto la complessità del sistema di programmazione.
Prendo come esempio un modello di esempio del wii e non più del camecube.

Example-Wii

Aprendo con un editor il file "template.c" situato nella cartella "/(percorso)/DevkiPRO/wii-example/template/source/" vedrete la sorgente del codice.
Da notare subito

CODICE
#include <stdio.h>
#include <stdlib.h>
#include <gccore.h>
#include <wiiuse/wpad.h>



Questi non sono altro che file inclusi nella nostra sorgente. Una serie di funzioni precompilate che semplificano la stesura del nostro codice.
Esistono 2 modi di inclusione il primo come nell'esempio quando i file non sono nella cartella corrente e il seconto come da notare qui sotto quando sono nella stessa cartella.

CODICE
#include "esempio.h"



Ora analiziamo i varii file:


CODICE
#include <stdio.h>


Contiene gli standar delle librerie Input e Output che ci permette di stampare il testo a schermo, leggere e scrivere file.


CODICE
#include <stdlib.h>


Dichiara funzioni e costanti di utilità generale: allocazione della memoria, controllo dei processi, conversione tra tipi e così via.


CODICE
#include <gccore.h>
#include <wiiuse/wpad.h>


Sono le librerie per il funzionamento del programma sullo standard del Wii, l'uso del pad ecc.

Queste quattro librerie sono il minimo indispensabile per il buon funzionamento delle applicazioni Homebrew.


CODICE
static void *xfb = NULL;
static GXRModeObj *rmode = NULL;


Le seguenti variabili al momento le tralasciamo perchè servono solamente a mostrare il video sullo schermo.


CODICE
int main(int argc, char **argv) {


Questa riga è la riga principale del nostro codice al di sotto di questa vi troviamo tutti i comandi e variabili che il nostro programma deve svolgere.
la maggior parte del codice sottostante sono funzioni video e quindi le tralasciamo perchè le tratteremo più in la, quindi saltiamo alla seguente riga:

CODICE
printf("Hello World!");



Se avete letto attentamente la guida precedente capirete subito che questa riga non fa altro che stampare a video la scritta "Hello Woprd!".

CODICE
while(1) {



Poi vi è la creazione di un ciclo infinito.

CODICE
WPAD_ScanPads();



Questa funzione racchiusa nella precedente libreria "wiiuse/wpad.h" dice al sistema che vogliamo utilizzare il controller Wii e quindi mette in ascolto i pulsanti premuti o rilasciati sul wiimote, questo è sempre necessario inserirlo in un ciclo quando abbiamo bisogno di un imput dal controller.

CODICE
u32 pressed = WPAD_ButtonsDown(0);



Questa riga darà un valore "True" alla variabile "pressed" quando verrà premuto un bottone sul controller.

CODICE
if ( pressed & WPAD_BUTTON_HOME ) exit(0);



Qui ci troviamo davanti ad un controllo della variabile "pressed" e se il bottone premuto sia l'"home", quindi se questi 2 parametri risultano veri ("True"), darà il comando di uscire dall'applicazione.

CODICE
VIDEO_WaitVSync();



Questa funzione non fa altro che aspettare la sincronizzazione verticale dello schermo, la utilizziamo nel caso in cui ci sono state molte visualizzazioni grafiche altrimenti rischiamo di far sfarfallare lo schermo accelerando gli fps.

CODICE
}



Chiusura del ciclo infinito.

CODICE
return 0;



Tutti i programmi C devono ritornare a 0 alla fine del programma. Se non ritorno a 0 allora il compilatore si lamentano perché non sanno dov'è la fine del programma.


Compilazione del codice sorgente

Sappiamo che il codice non fa altro Scrivere su schermo la scritta "Hello Word!" ed attendere finchè non viene premuto il tasto Home per uscire dall'applicazione.

Ora però prima di poter avviare il nostro esempio sulla consol dobbiamo compilare la sorgente, aprite un terminale ed entrate nella cartella dove è situato il "Makefile"


CODICE
cd /(percorso)/DevkitPRO/wii-example/template


e digitate il comando:

CODICE
make



Adesso abbiamo compilato la nostra sorgente e se non avete commesso errori durante la creazione dell'ambiente il risultato sarà:

CODICE
template.c
linking ... template.elf
output ... template.dol



Da notare che il risultato sono 2 file, uno in formato ".dol" e l'altro ".elf", questi possono essere poi utilizzati nel canale Homebrew della wii, se in caso si rivoglia ricompilare la sorgente è necessario dare prima il comando "clean" che ripulisce le tracce della precedente compilazione, questo per evitare eroori se abbiamo cambiato parti della sorgente.


Errori di compilazione

Ora trattiamo gli errori del compilatore, di solito quando durante la compilazione (dopo il comando "make") ci da sempre il file e la riga dell'errore, nella maggior parte dei casi è la dimenticanza di ";" dopo ogni riga di comando.

CODICE
/source/template.c: In function 'main':
/source/template.c:21: error: expected ';' before 'rmode'


Il compilatore ci dice che nella funzione "main" (la funzione principale del codice) si è verificato l'errore e ci conduce in prossimità della linea in questione.

Il compilatore può anche dare avviso di cose che ancora lavorare, ma ci avverte cosa dobbiamo guardare Ad esempio:

CODICE
/source/template.c: In function 'main':
/source/template.c:52: warning: unused variable 'test'


Questo avviene quando viene dicharata una variabile intera e poi viene utilizzata come alfanumerica

Ora abbiamo un po' di fondamenti per la creazione e la compilazione di applicazioni per il nostro wii, comunque sto partendo dal presupposto che tu abbia già installato il canale Homebrew sulla tua consol Wii, questo rende più semplice provare i programmi.
In caso contrario di consiglio di installare il canale.

Per provare "template.elf" o "template.dol" bisogna creare una cartella nella nostra scheda SD, da non dimenticare che la nuova cartella deve essere sotto "apps" e che il file deve essere rinominato in "boot.elf" o "boot.dol" a seconda del caso e se volete creare una icona in formato ".png" di dimensioni standard 128x48 e un file "meta.xml" dove inserire le informazioni, qui sotto vi riporto il file ".xml" di esempio:

CODICE
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <app version="1">
        <name>Nome del programma</name>
        <coder>Nome o gruppo del creatore del programma.</coder>
        <version>Versione del programma</version>
        <release_date>data di rilascio ne formato: YYYYmmddHHMMSS</release_date>
        <short_description>Questo viene visualizzato nel menu principale del Homebrew Channel,
                           spazio utilizzato per aggiungere 4 parole di spiegazione del
                           programma</short_description>
        <long_description>Descrizione del programma con le eventuali funzioni o comandi di
                          controllo</long_description>
      </app>



Per oggi è tutto alla prossima.

Se vuoi scaricare il tutorial clicca qui

Controller Pad

Benvenuti alla 4 parte riguardante la programmazione Homebrew per la consol Wii, spero che abbiate già letto le 3 parti precedenti riguardanti l'ambiente di lavoro e le basi di programmazione C, questo tutorial comprenderà principalmente le librerie riguardanti le funzioni di controllo dei comandi dei Pad Wii e GameCube.

Come esempio per semplificare la spiegazione prendo in considerazione una sorgente che abbiamo già visto in precedenza e che vi incollo qui sotto:

CODICE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>

static u32 *xfb;
static GXRModeObj *rmode;

void Initialise() {
       VIDEO_Init();
       PAD_Init();
       rmode = VIDEO_GetPreferredMode(NULL);
       xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
       console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
       VIDEO_Configure(rmode);
       VIDEO_SetNextFramebuffer(xfb);
       VIDEO_SetBlack(FALSE);
       VIDEO_Flush();
       VIDEO_WaitVSync();
       if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}

int main() {
       Initialise();
       printf("Hello World!\n");
       return 0;
}


Come già avevamo visto ci sono le librerie che includiamo per il funzionamento di input/output, ecc.
poi troviamo la funzione per l'inizializazione del video e poi nella funzione principale "int main()" troviamo il richiamo della funzione di inizializazione e poi la stampa di "Hello Word!", insomma tutte cose che già abbiamo trattato nelle lezioni precedenti.

Se volete compilare il codice avete bisogno del file "Makefile" riportato qui sotto, tenendo conto delle regole già trattato in precedenza:

CODICE
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
endif

include $(DEVKITPPC)/gamecube_rules

#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET                :=        $(notdir $(CURDIR))
BUILD                :=        build
SOURCES                :=        source
DATA                :=        data  
INCLUDES        :=        include

#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------

CFLAGS        = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS        =        $(CFLAGS)

LDFLAGS        =        -g $(MACHDEP) -Wl,-Map,$(notdir $@).map

#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS        :=        -logc -lm

#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS        :=

#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------

export OUTPUT        :=        $(CURDIR)/$(TARGET)

export VPATH        :=        $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
                                       $(foreach dir,$(DATA),$(CURDIR)/$(dir))

export DEPSDIR        :=        $(CURDIR)/$(BUILD)

#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES                :=        $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES        :=        $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES                :=        $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES                :=        $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES        :=        $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))

#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
       export LD        :=        $(CC)
else
       export LD        :=        $(CXX)
endif

export OFILES        :=        $(addsuffix .o,$(BINFILES)) \
                                       $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
                                       $(sFILES:.s=.o) $(SFILES:.S=.o)

#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE        :=        $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
                                       $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
                                       -I$(CURDIR)/$(BUILD) \
                                       -I$(LIBOGC_INC)

#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS        :=        $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
                                       -L$(LIBOGC_LIB)

export OUTPUT        :=        $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean

#---------------------------------------------------------------------------------
$(BUILD):
       @[ -d $@ ] || mkdir -p $@
       @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile

#---------------------------------------------------------------------------------
clean:
       @echo clean ...
       @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol

#---------------------------------------------------------------------------------
run:
       psoload $(TARGET).dol

#---------------------------------------------------------------------------------
reload:
       psoload -r $(TARGET).dol


#---------------------------------------------------------------------------------
else

DEPENDS        :=        $(OFILES:.o=.d)

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)

#---------------------------------------------------------------------------------
# This rule links in binary data with the .jpg extension
#---------------------------------------------------------------------------------
%.jpg.o        :        %.jpg
#---------------------------------------------------------------------------------
       @echo $(notdir $<)
       $(bin2o)

-include $(DEPENDS)

#---------------------------------------------------------------------------------
# This rule links in binary data
#---------------------------------------------------------------------------------
%.bin.o        :        %.bin
#---------------------------------------------------------------------------------
       @echo $(notdir $<)
       @$(bin2o)

%.mod.o        :        %.mod
#---------------------------------------------------------------------------------
       @echo $(notdir $<)
       @$(bin2o)

-include $(DEPENDS)

#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------


La Differenza per richiamare il controller Wii o GameCube è solamente dovuta ad una "W", cioè nel caso si dichiari un richiamo del controller GameCube la parte iniziale della funzione è "PAD_", nel caso del controller WII "WPAD_".
Allora cominciamo meglio con esempii più pratici per capire meglio come funziona l'uso dei PAD, prendiamo al momento in considerazione quello del GameCube, per prima cosa abbiamo bisogno di una scansione della periferica tramite il comando:

CODICE
PAD_ScanPads ();


Senza questo comando il controller sarà del tutto inutile, perchè non verrà rilevato dal sistema.
Innanzitutto bisogna tenere conto che ci sono tre diversi stati di rivelazione:

CODICE
PAD_ButtonsDown(0) //controllo se il pulsante è stato premuto
PAD_ButtonsHeld(0) //controllo se il pulsante è stato tenuto basso
PAD_ButtonsUp(0) //controllo se il pulsante è stato rilasciato

In questo esempio vogliamo verificare se un determinato pulsante è stato premuto, per questo utiliziamo la funzione "PAD_ButtonsDown()" come illustrato di seguito.

CODICE
u16 buttonsDown = PAD_ButtonsDown(0);


Assegnamo alla variabile "buttonsDown" la funzione "PAD_ButtonsDown(0)" per verificare se il pulsante è stato premuto, da notare lo "0" tra parentesi, sta ad indicare il controller che andiamo ad utilizzare, in questo caso il primo, se invece vogliamo controllare il secondo allora dobbiamo sostituire il valore con "1" e così via.
Ora dobbiamo verificare se il pulsante è stato premuto e se abbiamo premuto il pulsante "A" allora vogliamo che il sistema ce lo scriva:

CODICE
if( buttonsDown & PAD_BUTTON_A ) {
    printf("Il pulsante A è stato premuto.\n");
}


Possiamo dire che la variabile "buttonsDown" sia una variabile boolean, cioè se il pulsante non è stato premuto assume il valore di "0" (falso), al contrario assume un valore (vero). Lo stesso principio vale per gli altri pulsanti, se vogliamo sapere quali siano gli altri pulsanti basta andare nel file:

CODICE
/(percorso)\devkitPro\libogc\include\ogc\pad.h

per vedere tutti i pulsanti e funzioni a disposizione riguardanti il controller GameCube.
Ora vogliamo verificare se il pulsante viene tenuto premuto e quando il pulsante viene rilasciato, il codice che riporto di seuito è simile a quello precedente con la differenza che sto utilizzando le rimanenti due funzioni elencate in precedenza:

CODICE
u16 buttonsHeld = PAD_ButtonsHeld(0);
if (buttonsHeld & PAD_BUTTON_A ) {
   printf("Il pulsante A viene premuto.\n");
}
u16 buttonsUp = PAD_ButtonsUp(0);
if (buttonsUp & PAD_BUTTON_A ) {
   printf("Il pulsante A è stato rilasciato.\n");
}


Ora passiamo ai 2 joysticks presenti sul controller del GameCube, questi li possiamo richiamare tramite le seguenti funzioni:

CODICE
PAD_SubStickX(0) //Joystick giallo asse orizontale
PAD_SubStickY(0) //Joystick giallo asse verticale
PAD_StickX(0) //Joystick asse orizontale
PAD_StickX(0) //Joystick asse verticale

Quando si usa il joystick non è necessario richiamare "buttonsDown" o qualsiasi altra cosa.
La funzione del joystick assume un valore che comprende da -18 a +18 sia sull'asse "X" (orizonatle) che sull'asse "Y" (verticale), qui sotto vi illustro un esmpio per capire meglio il funzionamento.

CODICE
if (PAD_StickY(0) > 18) {
   printf(“Joystick mosso verso l'alto.\n”);
}
if (PAD_StickY(0) < -18) {
   printf(“Joystick mosso verso il basso.\n”);
}


Bisogna tenere conto che la funzione per il joystick è come la funzione "PAD_ButtonsHeld" cioè si avrà un valore finche il joystick ha un movimento altrimenti torna automaticamente a "0" (falso).
Ora vediamo il nostro codice con tutte le nuove nozioni che abbiamo visto fino ad ora, il seguente codice va inserito dopo la riga del comando "printf" e quindi avremo:

CODICE
while(1) {
   PAD_ScanPads();
   u16 buttonsDown = PAD_ButtonsDown(0);
   if( buttonsDown & PAD_BUTTON_A ) {
       printf("Il pulsante A è stato premuto.\n");
   }
   u16 buttonsHeld = PAD_ButtonsHeld(0);
   if (buttonsHeld & PAD_BUTTON_A ) {
       printf("Il pulsante A viene premuto.\n");
   }
   u16 buttonsUp = PAD_ButtonsUp(0);
   if (buttonsUp & PAD_BUTTON_A ) {
       printf("Il pulsante A è stato rilasciato.\n");
   }
   if (PAD_StickY(0) > 18) {
       printf("Joystick mosso verso l'alto.\n");
   }
   if (PAD_StickY(0) < -18) {
       printf("Joystick mosso verso il basso.\n");
   }
   if (buttonsDown & PAD_BUTTON_START) {
       exit(0);
   }
}


Ora basterebbe compilare il nostro piccolo programmino per avere i risultati che abbiamo appena visto, questo però funzionano solo sul Pad del Gamecube, per avere gli stessi risultati sul PAD wii dovremo innanzitutto cambiare il file di compilazione "Makefile" andando a sostituire alla riga:

CODICE
include $(DEVKITPPC)/gamecube_rules


da vedere la scritta "gamecube_rules", a noi serve "wii_rules", e in più dobbiamo aggiungere le librerie Wii e Bluetooth:

CODICE
LIBS    :=    -lwiiuse -lbte -logc -lm


Ora sul nostro programma dobbiamo includere le librerie del Pad aggiungendo in alto la riga

CODICE
#include <wiiuse/wpad.h>

Ora dobbiamo come detto in principio aggiungere la "W" alla funtione "Pad_" e visto che il Wiimote non ha il joystick elimineremo questi controlli e quindi il nostro codice sarà:

CODICE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
#include <wiiuse/wpad.h>
static u32 *xfb;
static GXRModeObj *rmode;
void Initialise() {
   VIDEO_Init();
   WPAD_Init();
   rmode = VIDEO_GetPreferredMode(NULL);
   xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
   console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
   VIDEO_Configure(rmode);
   VIDEO_SetNextFramebuffer(xfb);
   VIDEO_SetBlack(FALSE);
   VIDEO_Flush();
   VIDEO_WaitVSync();
   if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
int main() {
   Initialise();
   printf("Hello World!\n");
   while(1) {
       WPAD_ScanPads();
       u16 buttonsDown = WPAD_ButtonsDown(0);
       if( buttonsDown & WPAD_BUTTON_A ) {
           printf("Il pulsante A viene premuto.\n");
       }    
       u16 buttonsHeld = WPAD_ButtonsHeld(0);
       if (buttonsHeld & WPAD_BUTTON_A ) {
           printf("Button A is being held down.\n");
       }
       u16 buttonsUp = WPAD_ButtonsUp(0);
       if (buttonsUp & WPAD_BUTTON_A ) {
           printf("Il pulsante A è stato rilasciato.\n");
       }
       /*if (PAD_StickY(0) > 18) {
           printf("Joystick mosso verso l'alto.\n");
       }
       if (PAD_StickY(0) < -18) {
           printf("Joystick mosso verso il basso.\n");
       }*/
       if (buttonsDown & WPAD_BUTTON_HOME) {
           exit(0);
       }
   }
   return 0;
}


Ora se andiamo a compilare ed ad esegure il programma sulla nostra consol avremo lo stesso risultato prercedente solo con il Wiimote.
Vi aspetto alla prossima con la libreria per il puntatore del Wiimote.

Ciriciao a presto

Se vuoi scaricare il tutorial clicca qui
 
Top
ryujiandy
view post Posted on 19/1/2009, 15:00




Ragazzi per comodità le prossime lezioni verranno pubblicate sul mio nuovo blog's
il link lo trovate in firma oppure cliccate qui.

la quinta lezione è già pubblicata e la trovate al seguente link
Lezione 5, Il cursore

Ciriciao e a presto
 
Top
2 replies since 14/1/2009, 17:34   637 views
  Share