Friday, September 22, 2006

WiFi pour ma carte mère

Roulement de tambour et plein feu sur les poursuites: j'ai réussi à connecter ma DS au reste du monde! Une vraie aventure ... D'abord parce que les réseaux sécurisés de l'Unif ne laissent évidemment que peu de chance à un jeu fait-maison, et également parce qu'aucun des jeux officiels que j'ai ne sont prévus pour se connecter à un portail.

Mais bon, j'avais quelques atouts:
- mon stick USB WiFi Topcom (chip zd1201), qui est merveilleusement bien reconnu par Linux (ubuntu gutsy) dès qu'on télécharge les fichiers firmware appropriés (et qu'on les installe dans /lib/firmware/),
- le concierge dont le gamin a une DS avec Mario Kart (tout à commencé par là, en fait)
- forums.gbadev.org qui m'ont pointé vers "test_wifi_lib.nds"

Donc, première étape: faire fonctionner la clé WiFi en mode "access point" plutôt que "client" ... c'est aussi simple que de charger le module avec "ap=1", ç.a.d.

sudo rmmod zd1201
sudo rmmod firmware_class
sudo modprobe zd1201 ap=1
Comme c'est un peu lourd à la longue de retirer les modules après avoir inséré la clé pour les re-charger avec le nouveau paramètre, on peut aussi éditer n'importe quel fichier dans /etc/modprobe.d pour lui ajouter
#this is in /etc/modprobe.d/wlan
options zd1201 ap=1
Ensuite, on démarre la nouvelle interface avec
sudo iwconfig wlan0 essid "gamerz"
sudo ifconfig wlan0 192.168.6.1 netmask 255.255.255.0
Ca fait bizarre de blogger ça comme ça. A ma dernière conférence, j'y connaissait encore rien à tous ces brols de WiFi, n'ayant jamais joué avec ... De nouveau, on peu règler tout ça dans un fichier de config une fois que ça marche bien:
# add this into /etc/network/interfaces
iface wlan0 inet
address 192.168.6.1
netmask 255.255.255.0
network 192.168.6.0
wireless_essid gamerz
ESSID, c'est le "nom" de notre réseau, que l'on verra dans les outils de détections ... Mettez ce que vous voulez, pourvu que ce soit original ... et évitez "tsunami", tant qu'à faire...

Bon, à ce stade-ci, on peut déjà ouvrir un ethereal et voir ce qui se passe quand une DS essaie de se connecter chez nous ... c'est à dire pas grand-chose... Elle va essayer d'obtenir une adresse IP, mais à moins qu'on ne lui en donne une, c'est rapé. donc, faisons un sudo apt-get install dhcpd (dhcpd, c'est le nom barbare du programme qui donne les adresses réseau :P), et offrons-nous un petit fichier /etc/default/dhcp:
INTERFACES="wlan0"
Seule l'interface wifi doit être listée, évidemment ... pas question de venir offrir une nouvelle adresse IP à votre routeur ADSL ^_^. Ensuite, il faut un peu de config:

# this is /etc/dhcpd.conf
option domain-name-servers 123.45.67.89;

subnet 192.168.6.0 netmask 255.255.255.0 {
option routers 192.168.6.1;
group {
host myDS {
fixed-address 192.168.6.3;
hardware ethernet 00:ca:fe:ba:be:00;
}
host friendDS {
fixed-address 192.168.6.4;
hardware ethernet 00:de:ad:be:ef:00;
}
}
}

Bon, si vous n'avez jamais ouvert le panneau de contrôle pour les cartes réseau, on est mal parti, mais rapidement, 123.45.67.89 est l'adresse de votre serveur de nom. Demandez-le gentiment à votre PC (e.g. "dig google.com", puis lisez la ligne ";;SERVER: 123.45.67.89") et utilisez le même.
192.168.6.1, ce sera l'adresse côté WiFi de votre PC, et c'est lui qui devra relayer les paquets... Les consoles DS auront par exemple les adresses 192.168.6.3 et 192.168.6.4 (oui, tous les numéros en 192.168.*, vous pouvez les reprendre tels quels)

Restent les fameuses "hardware ethernet", aussi connues sous le nom d'adresses MAC ou adresses physiques. Chaque carte réseau (sur un routeur, un PC, une DS, clé USB, etc.) a la sienne et elle est unique. Avec wifi_lib_test de Stephen Stair, il suffira de demander "DS infos", mais avec un jeu comme mario Kart DS, pas le choix: vous devez épier la source des paquets DHCP et reprendre la même valeur.

Si tout c'est bien passé, tapez

sudo /etc/init.d/dhcp3-server start

Et vous êtes prêt à donner une adresse IP à votre DS ... à ce stade, ça vaut la peine de laisser tourner "tail -f /var/log/messages" ou "tail -f /var/log/syslog.0" dans un autre terminal pour voir comment les choses se passent ...

Attention: tout ceci n'est pas sans risque: en suivant tous ces conseils, vous venez d'ouvrir une porte sur votre PC, que des hackers du voisinage pourrait bien utiliser vos dépens. Si vous tenez vraiment à continuer sur cette voie et activer le "forwarding" de paquets par le noyau Linux (et ainsi vous connecter à Internet depuis votre DS à travers votre PC), documentez-vous d'abord sur les firewalls linux, et soyez sûr de votre coup... un filtrage des adresses MAC serait un minimum, mais configurer un firewall proprement, c'est tout un art et ça dépend de votre réseau

sudo echo 1 > /proc/sys/net/ipv4/ip_forward

Enfin, guidedog peut s'avérer bien utile pour vous aider à mettre en place le NAT sur votre PC linux ^_^

Wednesday, September 13, 2006

fighting with rotoscale hardware

sometimes, you realise you should have put more times reading the specs. That happens with my IXP2400 processor, but also with the NDS.
After the fight-against-blending story, i tried to put the grid of my sprite editor on a "rot/scale" background so that you could opt for 16x16, 32x32 or whatever edition size you prefer (though beside 24x24, i don't see what else we could have). That came just after a slight modification that was intended to fully useable 'upper' screen.

But the result was a rather black stuff. It took me hours of tests with the flash card (the emulator didn't help finding out what was going wrong, as in the blending case) to finally figure out that, while you have 8-bit per tile only on rotoscale layers, you still must write 16 bits at a time, or your access pattern is lost.

Il y a des jours où on se dit qu'on devrait lire les manuels plus en détail. C'est ce qui arrive régulièrement avec mon Network Processor IXP2400, mais aussi avec la nintendo. Après l'épisode "je me bats contre des fantômes transparents", j'ai essayé de mettre la grille du "Sprite Editor" sur un calque zoomable (rot/scale), histoire que l'on puisse aussi bien éditer des blocs 16x16 ou 32x32 ... Et ça juste après avoir modifié le code pour permettre l'utilisation de l'écran supérieur ...

Résultat? Du noir. C'est tout.

J'ai passé des heures à monter/démonter ma carte SD (comme dans le cas de la transparence, l'émulateur n'est pas vraiment utile ici non-plus) pour finalement me rendre compte d'une erreur débile. Même si les calques avec zoom n'utilisent que 8 bits par "tuile", on est quand même obligé d'écrire dans la mémoire vidéo par mots de 16 bits d'un coup... sans ça, les données se perdent :P

Monday, September 11, 2006

Cute Pixels ...

Cute pixels from Indigo Art...
I really like how he did amiga-like tiles for a "green level". Just using 32 colours for the whole stuff. Very efficient. The "ground", for instance, is mainly using colors #966d42 and #b68e50 with a "back" colour that has a more "purple" taste: #774953 ... That nicely allows you to do shadows of trees (hidden branches,etc) using #623551 and #392232. Another thing i like much is how the grass is given a "curvy" look by using only two-pixel bar of #c8d551 (yellow green) over #7fbc43 green. The effect is even reinforced using a nice blue-green (#197c3e) for grass shadows (as well as back leaves that can even pick #335955 and #304942). and #f5f08d gives the shiny pixels where grass catches the light a bit more (and there aren't many of them, as you can see...
De biens jolis pixels venant de "Indigo Art" ... j'aime vraiment le style Amigaesque de ces blocs pour une "green zone". Et tout ça sur moins de 32 couleurs! chapeau. Le sol, par exemple, avec deux teintes et un fond tirant sur le pourpre, ce qui donne bien mieux que les teintes habituelles pour les ombres des arbres, etc.
J'aime bien aussi le look "courbe" de son herbe, avec une barre de 2 pixels plus clairs au milieu, renforcé par un vert plus jaune pour les reflets et un vert-bleu pour les ombres...

Maybe you wonder why you've had that many #rrggbb color codes in the previous paragraph? that's just because it's lunchtime and i need to take notes of all those values until i have a "palette editor" for my DS-based "pixel factory" ... Another trick i like quite much is how the ground itself is given is given a rounded shape (thanks to layer transparency, of course), and how Dan Fessler has been using a pretty wide "suspended grass" to break the monotony... I tried something alike to add some snow to castle walls in some blocks of mine a couple o' days ago, but i was clearly using too small patterns, making them "unguessable" for the player.

Ah, vous vous demandez pourquoi tous ces #rrggbb dans la version anglaise? c'est les codes de couleur. On est sur le temps de midi et je prends note de tout ça en attendant d'avoir un éditeur de palettes pour ma DS. Autre chose qui donne bien dans les blocs de Dan Fessler, c'est le look arrondi du sol lui-même (grâce aux pixels transparents) et la manière dont les touffes d'herbes suspendues sont utilisées pour casser la monotonie. J'avais essayé de faire pareil dans le "chateau enneigé" que je dessinais il y a quelques jours, mais apparament, j'utilisait un motif trop petit, et on ne voyait pas de la neige, mais juste des erreurs de dessin.

Note, too, that the whole "ground" pattern is pretty large (40 pixels, actually) ... that makes me thing i was unhappy with the fact the nintendo DS has 8x8 tile size and that most of my previous pixart on the PC was using 20x20 blocs ... since it takes a rather long time to make "good" tiles for ground, etc (i mean, tiles that can be repeated smoothly in both dimensions), thinking all that previous work was "lost" made me rather frowning... but as i was looking at that grass more closely, it just appeared that we had light-pattern repeating, sometimes at the edge, sometimes in the middle of the block ... which suggested the actual block pattern wasn't Nx16 but something more built out of 8x8 tiles directly. And after i counted the tiles, my mind suddenly reminded me i should practice maths in base-10 more often :P 8x5 == 40 == 20x2.

Et si on y regarde de plus près, le bloc de terre et relartivement large (40 pixels). Ce qui me rappelle mes précédents spritesets sur PC (avec le GameMaker) qui utilisait des blocs de 20x20, alors que la DS fonctionne avec des "tuiles" de 8x8 ... Tout ce travail perdu? ce serait trop bête... Alors que si on en colle 2 l'un à côté de l'autre, ça donne 40 pixels, soit 5 tuiles (oui, je sais, je devrais réapprendre à compter en base 10).

There are still two things worth of bloggin about those blocks. First, the grass has a shadow, which suggests it's bushy and falls over the ground. Second, the "ground pattern" itself, despite looking random, is given some inherent coherency by the "tall rectangles" shape...

The general aspect of the map has something else pretty nice. It gives you a depth feeling. I think with a bit of tweaking, we could easily have a Bilou game where you can just "fall off" from one platform to the one below (which isn't actually "below" you, but rather more "below and a bit closer to the player" ... That'd be just more natural than a mario-like level design).

Deux autres choses à blogger à propos de ces blocs. D'abord l'ombre de l'herbe, qui suggère un aspect un peu "buissonneux" et qui retombe par-devant le sol. Ensuite le motif du sol lui-même, qui malgré son apparence aléatoire, possède une sorte de "cohérence" grâce aux formes généralement rectangulaires et verticales ...
La construction de la carte elle-même est assez chouette. Elle donne un effet de profondeur grâce au sol qui devient plus uniforme, ce qui -- avec un rien d'ajustement -- pourrait mener à un jeu Bilou où il est possible de se 'laisser tomber' d'une plate-forme vers celle qui est en-dessous (en fait, pas vraiment en-dessous, mais plutôt "en dessous et un chouya plus proche du joueur. Ce qui est plus logique que les designs "à la Mario" avec des blocs qui flottent dans les airs).

Oh, and before you click on another page, just have a look at those so-amiga-stylish golden coins ... #ffffff:#faf078:#efbb1c:#d07c28:#ab4625 made it pretty well, no. They remind me of "fury of the furries" game ^_^

Et juste avant que vous ne partiez vers une autre page, jettez un oeil à ces pièces d'or si typiquement amiga-esques ... Elles me rappellent 'Fury of the Furries' ^_^

original artwork found on http://www.spriteart.com/indigo/ ...

Saturday, September 09, 2006

Alpha blending.

Okay, i'm trying to make sense of the alpha-blending bits of the nintendo DS. I'd like a blended grid for my editor ;)

So, let's see the specs first:

4000050h 2 R/W BLDCNT Color Special Effects Selection (BLEND_CR)
4000052h 2 W BLDALPHA Alpha Blending Coefficients (BLEND_AB)
4000054h 2 W BLDY Brightness (Fade-In/Out) Coefficient (BLEND_Y)
Bion. Voyons voir comment marche l'alpha-blending -- c'est à dire la transparence sur les fonds -- sur la console DS (j'aimerais bien pouvoir "estomper" la grille de mon sprite editor, si vous voulez tout savoir). Trois registres jouent un rôle dans les "effets spéciaux" (fade-in/fade-out et blending) : BLEND_CR, BLEND_AB et BLEND_Y. Je suis reparti de la démo Complex2D du devkitpro pour étudier comment ça marche.

You have 3 registers responsible of "special effects", including fade-in, fade-out and alpha blending. The latter one is the one we want (mixing two layers to have one of them appearing "translucent" and seeing the second one through. Clearly, we want it for fogs, clouds, mirrors, ghosts and plenty other reasons ;)

So, let's take the Complex2D demo from devkitpro and spice it up a little bit.

//set up the sub display
videoSetModeSub(MODE_0_2D |
DISPLAY_SPR_1D_LAYOUT |
DISPLAY_SPR_ACTIVE |
DISPLAY_BG0_ACTIVE |
DISPLAY_BG1_ACTIVE );

//set up two backgrounds to scroll around
SUB_BG0_CR = BG_COLOR_256 | (1 << SCREEN_SHIFT) | BG_PRIORITY(0);
SUB_BG1_CR = BG_COLOR_256 | (2 << SCREEN_SHIFT) | BG_PRIORITY(1);
BG_PALETTE_SUB[0] = RGB15(10,10,10);
BG_PALETTE_SUB[1] = RGB15(0,16,0);
BG_PALETTE_SUB[2] = RGB15(0,0,31);
vramSetMainBanks(VRAM_A_MAIN_BG, VRAM_B_MAIN_SPRITE, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE);

There is two background layers, one being green-checker (BG0) and the other one being blue-checker (BG1). Each checker's "dark" squares are actually see-through pixels (purely transparent), which you achieve with color 0. Moreover, you have the 'backdrop' layer (here a dark-grey colour) that is seen when all pixels of all layers use color 0 (you typically never see the backdrop in a game, for instance).

Dans cette démo, on construit deux damiers, l'un vert (BG0) et l'autre bleu (BG1). Les cases "noires" de ces damiers sont en fait des pixels complètement transparents (couleur #0) et la couleur de fond (le "backdrop" -- que l'on préfère ne jamais voir dans un jeu vidéo) est gris-foncé.

//load the maps with alternating tiles (0,1 for bg0 and 0,2 for bg1)
for(iy = 0; iy < 32; iy++)
for(ix = 0; ix <32; ix++) {
map0[iy * 32 + ix] = ((ix ^ iy) & 2)>>1;
map1[iy * 32 + ix] = ((ix ^ iy) & 2);
}

//fill 2 tiles with different colors
for(i = 0; i < 64 / 2; i++) {
BG_GFX_SUB[i+32] = 0x0101;
BG_GFX_SUB[i+32+32] = 0x0202;
}


So far, we'll use SUB_BLEND_AB=0x1010, which is full intensity for both layers. If one is blue, the other red and that blending occurs, we should see purple somewhere. The initial priority is set to green-over-blue and we slowly scroll the green checker over the blue one. No blending is activated so far.

  • with SUB_BLEND_CR=BLEND_ALPHA|BLEND_SRC_BG0|BLEND_SRC_BG1; we do not change much things, as both layers are used as "blending source" but no layer is definde "transparent".

  • SUB_BLEND_CR=BLEND_ALPHA|BLEND_SRC_BG0|BLEND_DST_BG1; is more interesting. The green checker is still over the blue one, but it no longer "hides" blue pixels. Instead, it mixes with them to produce
    light-blue.

  • SUB_BLEND_CR=BLEND_ALPHA|BLEND_DST_BG0|BLEND_SRC_BG1; and SUB_BLEND_CR=BLEND_ALPHA| BLEND_DST_BG0|BLEND_DST_BG1|BLEND_SRC_BACKDROP appear such as the initial (no destination) blending.


Now, if we swap the priorities (e.g. blue checker-BG1 over green checker-BG0), the first setting (SRC_BG0|SRC_BG1) still show both layers opaque, but now that's (DST_BG0|SRC_BG1) that shows
alpha-blending while (SRC_BG0|DST_BG1) only shows opaque pixels.

In other words:
  • the source layer(s) must be over destination layer(s) to have some blending displayed. that means the priority of source layers should be numerically lower than the priority of destination layers.

  • the source layer is what is going to be translucent, the destination(s) is what is going to be seen through (and yes, i find this rather confusing).

En clair, le layer 'source' doit être par-dessus le layer "destination" pour que l'effet soit visible. Cela signifie que la priorité du layer "source" doit être numériquement inférieure à celle du layer "destination". Et oui, la libnds appelle "source" le layer qui sera transparent et "destination" le layer que l'on voit à travers l'effet. C'est perturbant, mais c'est comme ça.
J'ai parlé de transparence 50/50, mais une valeur 0x1010 pour BLEND_AB correspond plutôt à une composition additionnelle: R = 1*Ra + 1*Rb, V = 1*Va + 1*Vb ... ce qui peut être perturbant aussi. Supposons qu'on veuille faire un nuage ou un fantôme (qui sera donc notre source), on prendra une valeur de 1 pour le multiplicateur des layers-destination (histoire que le fantôme n'assombrisse jamais le décor) mais le fantôme étant du blanc pur, on ne l'affichera qu'à 50%, ce qui donnera BLEND_AB = 0x0810.

Note that calling 0x1010 a 50/50 blending is a bit exagerated. what it means is that you end up with a pixel whose values are R = 1*Ra + 1*Rb, G = 1*Ga +1*Gb and B = 1*Ba + 1*Bb. That may be a bit confusing too.
For clouds/ghosts, you want the cloud-carrying layer to be the source. The other layers should keeps they alpha-blending value to 1 (so that the cloud doesn't "darken" them), but the cloud itself (bright white) should e.g. only affect by 0.5, so that your grey tower appearslightgrey where the cloud is. That leads to e.g. BLEND_AB=0x0810.

The full demo code is available here.
Btw, See also liranuna's witch demo for alpha-blending of sprites over backgrounds.

Friday, September 08, 2006

SpriteEditor DS

Les choses prennent forme. Je peux éditer un sprite avec un outil 'crayon' ou 'block', et grâce au code de la "libfat" de chism & dragonminded, je peux charger et sauver mes sprites sur la carte SD.
J'ai rajouté hier une fonction "copier le sprite" en utilisant un truc venant de SCUMMVM (le moteur de jeux pointer-cliquer de Lucas Arts).

Un pression sur l'écran correspond à un clic simple, alors qu'une pression pendant que le bouton "L" est enfoncé correspond à un "clic droit". Pour la grille, celà correspond à prélever la couleur comme couleur en cours, et sur la table de sprites, à enregistrer la zone de travail.

Things starts getting in place ... i can edit the sprite (of course) using both 'pencil' and 'block' mode, and thanks to the "libfat" code from chishm and dragonminded, i can read sprite tables from the SD flash card and write them back. Yesterday, i've also been adding the "copy sprite" feature, using a trick found in SCUMMVM for DS (the maniac-mansion editor).

When you just click the screen, that's a regular click (GUI_CLICKED event in my engine), and if you click while pressing the "L" key, that's a GUI_ALT_CLICKED. So we now have a touchscreen with "left" and "right" click :P Right-clicking the grid is used to "pick" a color and right-clicking the sprite table is used to "save" the sprite edited.

Oh, and another goodie: just click "beyond" the current table to "extend" it with the newly saved sprite ...

Now the next step will be showing animations and supporting multi-layer sprites (with layer merging).

PS: avant ce post, il y avait mon skyblog. Les messages relatifs à la programmation DS ont été rassemblés dans ce post-anniversaire