Jump to content
Jagware
RaZ

Joypads, teamtaps and other controllers

Recommended Posts

RaZ    0

Les Jagpads et comment les traiter :

------------------------------------

 

Pour les traiter, traiter les bien !!!

 

Trève de plaisanterie(stupide), cet article va vous expliquer comment récuperer les valeurs des pads (0 et 1) et aussi ceux des autres pads (Team Tap), pour une raison simple c'est pas plus difficile voire c'est exactement pareil !!!

 

En premiere partie, on va vous expliquer comment faire, sur la seconde partie, comment optimiser tout cela et oui sur ce site on vous dit même comment faire des vrais jeux Jag !!! YES !!!

 

Et on envoie la sauce :

 

Pour faire cela c'est tres simple, sisi !!

 

On dispose de deux registres :

 

Appelation officiel Atari, adresse

JOYSTICK ,$f14000

JOYBUTS ,$f14002

 

Vu le nombre de pad et le nombre de possibilités (comptez les touches d'un pad multiplié par 8 (Pour deux team taps !)), Atari a prévu un truc beaucoup plus simple coté gestion. Un registre permet d'indiquer les infos qu'il nous faut, suivant

le pad. Ces infos sont divisés en deux parties, d'abord suivant le pad qu'on veut interroger et ensuite la colonne. Non pas d'erreur les pads son divisés en colonnes, 4 pour etre exact, 3 du keypad et 1 pour les directions (Les fire et pause, Option sont traités un peu a part, vous verrez).

 

Pour résumer on va mettre une valeur dans le registre JOYSTICK et la Jag va nous renvoyer notre valeur dans ce meme registre, c'est cool non ? Quel valeur mettre ? Vu que c'est un peu la berezina dans la doc je vous ais fait un tableau qui va bien.

 

Mais avant de passer au tableau, il faut savoir comment sont organisé ces 4 colonnes (allant de 0 a 3)

 

Si on demande la colonne 3, on va récup les touches :

 

# 9 6 3

 

Si on demande la colonne 2, on va récup les touches :

 

0 8 5 2

 

Si on demande la colonne 1, on va récup les touches :

 

* 7 4 1

 

Si on demande la colonne 0, on va récup les touches :

 

Up Down Left Right (La position du jagpad)

 

 

+--------+-------+-------+-------+-------+
|Colonne | Pad 0 | Pad 1 | Pad 2 | Pad 3 |
+--------+-------+-------+-------+-------+
|  3     |   $7  |  $3   |  $8   |  $f   |
+--------+-------+-------+-------+-------+
|  2     |   $b  |  $2   |  $6   |  $c   |
+--------+-------+-------+-------+-------+
|  1     |   $d  |  $1   |  $5   |  $a   |
+--------+-------+-------+-------+-------+
|  0     |   $e  |  $0   |  $4   |  $9   |
+--------+-------+-------+-------+-------+

 

Ceci est pour soit le joypad 0, soit le premier pad sur le team tap 1, si vous accedez au pad 0, que le team tap soit branché ou pas, cela ne change rien.

 

 

Et je mets donc cette valeur ou et comment ?

 

On va écrire cette valeur dans JOYSTICK ($f14000), sous la forme :

 

 

$810x : x étant la valeur du tableau que vous voulez.

 

(Le 81 n'y faites pas gaffe, cela permet de garder la sortie son active et sélectionner les joy, le zéro c'est pour faire une sélection sur l'autre port) donc en 68000 si vous voulez lire la colonne zéro (position du pad), du pad 0 (On regarde dans le tableau Pad 0, colonne 0 : $e) donc vous faites un :

 

move.w #$810e,JOYSTICK (ou move.w #$810e,$f14000 comme vous voulez)

 

(Vous pouvez utilise JOYSTICK si vous incluez le fichier d'include d'Atari)

 

et maintenant on fait cela :

 

move.w JOYSTICK,d0 (ou move.w $f14000,d0 comme vous voulez)

 

et donc vous avez donc d0 la donnée demandé. Par contre pour ce joy le données sont renvoyés en position 8-11 (4 bit), donc il faut faire un

 

and.w #$0f00,d0

 

pour nettoyer les trucs indésirables, après vous en faites ce que vous voulez !!

 

Petite note, les bits fonctionnent a l'envers, cela veut dire que si le bit vaut zéro la touche est appuyé, cela n'est pas une grande gêne, vous pouvez faire cela pour remettre tout cela en ordre :

 

not.w d0

 

Qui inverse d0, sinon vous adaptez votre code en conséquence, inversez les tests (!) vous faites exactement pareil pour les autres valeurs.

 

 

Cela va toujours ?

 

et on recommence avec l'autre joy, vous savez tout, donc juste le petit tableau qui va vous simplifié la vie :

 

+--------+-------+-------+-------+-------+
|Colonne | Pad 0 | Pad 1 | Pad 2 | Pad 3 |
+--------+-------+-------+-------+-------+
|  3     |   $e  |  $c   |  $1   |  $f   |
+--------+-------+-------+-------+-------+
|  2     |   $d  |  $4   |  $6   |  $3   |
+--------+-------+-------+-------+-------+
|  1     |   $b  |  $8   |  $a   |  $5   |
+--------+-------+-------+-------+-------+
|  0     |   $7  |  $0   |  $2   |  $9   |
+--------+-------+-------+-------+-------+

 

Ces valeurs (en binaire) sont les mêmes que le joy 1 mais lu dans l'autre sens :

 

exemple : %0010 devient %0100 pour le joy 2.

 

ATTENTION ! Mettez vous bien en tete une chose, sur la Jag on a deux ports pour les pads : le 0 et le 1, sur chaque port on peut aller jusqu'a 4 jagpads.

Ce qui fait un total de 8. Donc si je parles du pad 1 sur le port 1, cela correspond au second joy sur le team tap du second port. N'oublies pas qu'on a pris la (sale ?) habitude de compter les zéros en info. Donc a partir de maintenant quand je parles du joy 2, cela concerne le 3 joy branche sur le team tap dans le second port de la Jag (Parce que maintenant on parle que du second port Pad)

 

Donc pour le port 2 en 68000 si vous voulez lire la colonne 1 (*741), du pad 3 (On regarde dans le tableau Pad 3, colonne 1 : $5) donc vous faites un :

 

move.w #$8150,JOYSTICK (ou move.w #$8150,$f14000 comme vous voulez)

 

(Vous pouvez utilise JOYSTICK si vous incluez le fichier d'include d'Atari)

 

et maintenant on fait cela :

 

move.w JOYSTICK,d0 (ou move.w $f14000,d0 comme vous voulez)

 

et donc vous avez donc d0 la donnée demandé. Par contre pour ce joy les données sont renvoyes en position 12-15 (4 bit), donc il faut faire un :

 

and.w #$f000,d0

 

pour nettoyer les trucs indesirables, après vous en faites ce que vous voulez !!

 

Still alive ?

 

Le plus dur est passé, les bouttons ca sert a rien !! Non on va faire un rapide passage sur les bouttons, le principe est exactement le même que pour les touches, Une sélection par JOYSTICK mais par contre la relecture des données se fait par JOYBUTS ($F14002).

 

On va rajoute un truc dans notre tableau (Premier tableau) :

 

+--------+-------+-------+-------+-------+---------------+
|Colonne | Pad 0 | Pad 1 | Pad 2 | Pad 3 | Boutton  10   |
+--------+-------+-------+-------+-------+---------------+
|  3     |   $7  |  $3   |  $8   |  $f   |          xO   |
+--------+-------+-------+-------+-------+---------------+
|  2     |   $b  |  $2   |  $6   |  $c   |          xC   |
+--------+-------+-------+-------+-------+---------------+
|  1     |   $d  |  $1   |  $5   |  $a   |          xB   |
+--------+-------+-------+-------+-------+---------------+
|  0     |   $e  |  $0   |  $4   |  $9   |          PA   |
+--------+-------+-------+-------+-------+---------------+

 

O=Option, C B A Sont les 3 fires, P=Pause x=sans importance

 

Le 1 et le 0 designe les bit 1 et 0 de JOYBUTS.

 

Donc quand vous lisez la colonne 0 d'un joy (Position du pad), après avoir lu JOYSTICK, vous lisez directement en JOYBUTS les 2 premiers bits et vous obtenez P(ause) et (Fire) A, exemple :

 

move.w #$810e,JOYSTICK ; (Selection colonne 0)

move.w JOYSTICK,d0 ; (Recup les donnees)

 

move.w JOYBUTS, d1 ; recup P(ause) et A (Fire)

 

Donc si vous testez le bit 0 de d1, vous pousez savoir si A est pressé. La même règle s'applique pour les bits, ils sont inverses de ce qu'on a l'habitude, donc vous pouvez revenir a la 'normale' par un :

 

not.w d1

 

Pour le second port :

 

+--------+-------+-------+-------+-------+---------------+
|Colonne | Pad 0 | Pad 1 | Pad 2 | Pad 3 | Boutton  32   |
+--------+-------+-------+-------+-------+---------------+
|  3     |   $7  |  $3   |  $8   |  $f   |          xO   |
+--------+-------+-------+-------+-------+---------------+
|  2     |   $b  |  $2   |  $6   |  $c   |          xC   |
+--------+-------+-------+-------+-------+---------------+
|  1     |   $d  |  $1   |  $5   |  $a   |          xB   |
+--------+-------+-------+-------+-------+---------------+
|  0     |   $e  |  $0   |  $4   |  $9   |          PA   |
+--------+-------+-------+-------+-------+---------------+

 

Exactement pareil pour le second port, sauf c'est les bit 3 et 2. Pas d'exemple, je penses que vous etes assez grand pour l'écrire vous même...

 

Et voila !! Vous savez tout sur les joys, puisse cet article, faire qu'on puisse avoir beaucoup plus de jeux multijoueurs sur Jag, on devrait presque imposer les deux joueurs minimun quand le jeu le permet, vous pensez pas ?

 

La seconde partie est la !!!

 

Deux petits trucs pour récuperer quelques cyles. La premiere, regardez bien le registre JOYSTICK, j'ai pas fait gaffe au début, mais la selection est séparé pour les 2 ports, donc vous pouvez lire les deux ports en même temps !!

 

Exemple :

 

move.w #$81e7,JOYSTICK

 

Sélectionne les colonnes 0 des deux ports, pour le traitement :

 

move.w JOYSTICK,d0

move.w d0,d1

 

and.w #$0f00,d0

and.w #$f000,d1

 

(Si on revient a la normale cela donne :

 

move.w #$8107,JOYSTICK

move.w JOYSTICK,d0

and.w #$0f00,d0

 

move.w #$81e0,JOYSTICK

move.w JOYSTICK,d0

and.w #$f000,d0

 

Il y a pas photo !!)

 

Voila dans d0 vous avez les données du premier port et dans d1 les données du second port. Ce qui fait 1 accès exterieur pour deux joys, ce qui évite de trop squatter le bus. Pour 8 pads, cela nous fait que 4 accès au lieu de 8, c'est bon hein !!! C'est pareil pour les bouttons.

 

La seconde technique ?

 

Regardez bien JOYSTICK ET JOYBUTS, mais pas les appelations officielles d'Atari les adresses même : $f14000 et $f14002 elles se suivent et elles font chacune 1 mot (2 octets) ce qui fait un total de 4 octets, vous voyez ou je veux en venir ? Non et bien regardez bien cela :

 

move.l JOYSTICK,d0

 

Je lis JOYSTICK ET JOYBUT d'une seule traite, donc vous avez les touches et les bouttons pressés d'une seule traite. Si vous voulez traiter les bouttons (Fire ABC, Option et Pause) normalement vous faites ceci :

 

move.w #$810e,JOYSTICK

move.l JOYSTICK,d0

move.l d0,d1

swap d1

 

Et ceci remplace :

 

move.w #$810e,JOYSTICK

move.w JOYSTICK,D0

move.w JOYBUTS,D1

 

Au nombre de lignes, je perds sur mon optim et bien gagné mais je gagnes en vitesse et en taille !! Si on comptes les cyles, voila le resultat :

 

move.w #$810e,JOYSTICK ; 20 cycles 8 octets

move.l JOYSTICK,d0 ; 20 cycles 6 octets

move.l d0,d1 ; 4 cycles 2 octets

swap d1 ; 4 cycles 2 octets

 

Ce qui nous fait un total de 48 cycles et 18 octets

 

Et pour l'autre :

 

move.w #$810e,JOYSTICK ; 20 cycles

move.w JOYSTICK,D0 ; 16 cycles

move.w JOYBUTS,D1 ; 16 cycles (Total de 52)

Total de 52 cycles, 16 octets

 

On gagne 4 cycles et 2 octets, ce n'est pas grand chose, mais il y a une chose très importante, dans la version non optimisé on a un total de 3 accès en extérieur, donc au bus, dans la version optim on a 2 accès au bus, cela evite de squatté le bus, et le laisse plus libre pour afficher des sprites, c'est plus efficace.

 

Et donc dans la version optim vous avez dans d1 JOYBUTS comme si vous l'aviez lu comme cela :

 

move.w JOYBUTS,d1

 

Il existe peut etre d'autres moyens d'optimiser, si vous trouvez faites moi s'en part.

 

J'ai trouvé une technique encore plus efficace, écrire la routine Pad au Gpu ou Dsp, cela marche j'ai une routine qui tourne. Je stocke le résultat dans la ram interne du Gpu, ceci pour des raisons de vitesse. Et chaque Vbl on va relire dans la ram interne avec le 68000, par :

 

lea Adr_joy,a0

move.l (a0)+,Joy_0

move.l (a0)+,Joy_1

move.l (a0)+,Joy_2

move.l (a0)+,Joy_3

move.l (a0)+,Joy_4

move.l (a0)+,Joy_5

move.l (a0)+,Joy_6

move.l (a0)+,Joy_7

 

Ou plus efficace :

 

movem.l Adr_joy,d0-d7

movem.l d0-d7,Joy_0

 

Ca va vous avez tout compris ? Sinon TANT PIS !!

 

 

Voili, voila c'est fini pour les joys, un truc pas compris, des idées des bugs (C'est pas possible car avec Atari on est .............. !)

 

Contactez moi sur ce forum, on en discutera.

 

 

GT Turbo (C.V.S.D. Membre de la Jagware Team) ;)

 

P.S. : En lisant ces registres on peut aussi savoir quel type de joy est branché mais vu le nombre de possesseurs de Joy genre Tempest Controller, on s'en passera. Si vous désirez l'info vous savez ou me trouvé

Share this post


Link to post
Share on other sites
GT Turbo    5

Est ce que quelqu'un a déjà essaye de detecter un Team Tap mais en plein milieu d'un code ? Car j'aimerais pouvoir écrire la routine de Teamp Tap finale, et me suis dit que je pourrais meme réagir si on venait a brancher le team tap durant le jeu, et bien la technique de detection officielle est pas terrible, car si on le fait en plein vol cela correspondrait a la touche pause, donc une pause en plein jeu et on a l'impression de se retrouver avec un team tap, c'est sur qu'au boot du jeu 'théoriquement' on garde pas le doigt sur pause mais bon, donc qui a mieux ?

 

GT Dans cette doc de m.. :blink:

Share this post


Link to post
Share on other sites
SCPCD    0
Est ce que quelqu'un a déjà essaye de detecter un Team Tap mais en plein milieu d'un code ? Car j'aimerais pouvoir écrire la routine de Teamp Tap finale, et me suis dit que je pourrais meme réagir si on venait a brancher le team tap durant le jeu, et bien la technique de detection officielle est pas terrible, car si on le fait en plein vol cela correspondrait a la touche pause, donc une pause en plein jeu et on a l'impression de se retrouver avec un team tap, c'est sur qu'au boot du jeu 'théoriquement' on garde pas le doigt sur pause mais bon, donc qui a mieux ?

 

GT Dans cette doc de m.. :blink:

Et qu'est ce qui ce passe si tu consideres que le Team Tap est toujours branché ?

Normalement ca gene pas si dans la configuration du jeu tu sais qu'il n'y a qu'un pad, je me trompe ?

Share this post


Link to post
Share on other sites
GT Turbo    5
Et qu'est ce qui ce passe si tu consideres que le Team Tap est toujours branché ?

Normalement ca gene pas si dans la configuration du jeu tu sais qu'il n'y a qu'un pad, je me trompe ?

 

Pour certains jeux multijoueurs je voulais voir si on pourrait les rajouter 'on the fly', mais c'est pas trop possible, je vais eviter de faire des jeux >2 joueurs ou on peut prendre en cours. Je me demandais si c'était pas mon code qui foirait :whistling:

 

 

GT ;)

Share this post


Link to post
Share on other sites
GT Turbo    5

Quelqu'un a déjà essayer de lire un Teamp Tap au DSP ?

 

Les deux ports Joy standard pas de soucis, mais est ce que cela est possible que le Team Tap est un certain temps de réponse ? Car au 68000 tout va bien mais dès que j'attaques au Dsp, les résultats sont assez funky !!

 

 

GT Trop rapide ? :blink:

Share this post


Link to post
Share on other sites
GT Turbo    5
T'y accède en 16 ou 32 bits ?

 

16 pour l'écriture du registre de sélection et 32 (Les 2 regs joy en meme) pour la lecture des bits des pads. Mais je penses pas que cela vient de la, car le source 68000 fonctionne nickel avec les memes accès. Pour le code j'ai utilisé exactment le meme que pour la lecture des pads 'classiques' vu qu'il n'y a que les codes de sélection qui sont différents.

 

Je me demandais si l'accès était pas trop rapide, lar le team tap d'après le code retransforme celui ci et redirige ce code au bon port, donc ce temps de transformation me donnerait pas les bons résultats. Car j'obtiens des résultats qui colleraient presque excepté qu'il ne concerne pas toujours le bon port, ou corresponde a une autre ligne.

 

Je vais essayer de 'nopper' entre mon écriture de sélection et la lecture pour voir si mon idée ce confirme.

 

 

GT ;)

 

Edit : Erreur, mon code 68000 accède tout en 16, mais mon code joypad classic, accède en 16 (ecriture) et 32 (lecture), cela serait possible que la lecture en 32 me rende la vie si difficile ?

Share this post


Link to post
Share on other sites
SebRmv    2
Edit : Erreur, mon code 68000 accède tout en 16, mais mon code joypad classic, accède en 16 (ecriture) et 32 (lecture), cela serait possible que la lecture en 32 me rende la vie si difficile ?

 

Juste pour dire que j'ai enfin écrit ma routine pour la lecture des 8 pads (au 68000) et je fais bien un accès en écriture en 16 bits et un accès en lecture en 32 bits donc le problème ne doit pas venir de là...

(en revanche, l'explication sur le temps de réaction du team tap me semble plausible)

 

Seb

Share this post


Link to post
Share on other sites
SebRmv    2
SebRmv si tu veux faire des tests de teamtap je suis dispo :)

 

j'en ai 2 + 6 ou 7 pads....

 

Salut,

 

au cas où t'aurais pas checké tes mails aujourd'hui, n'hésite pas...

 

Seb

Share this post


Link to post
Share on other sites
Fredifredo    0

Merci Seb :)

 

Bon j'ai retrouvé 5 pads mais mon team tap doit trainé dans un autre carton ( bah oui j'ai toujours pas emménagé à 100% depuis 6 mois !)

 

Fredifredo l'explorateur

Share this post


Link to post
Share on other sites
SebRmv    2

Merci fred pour le test

 

sinon, GT, je sais pas si tu as vu la page 15 de la partie consacrée au joypads

les bits C1, C2, C3 permettent de déterminer le type de joypad connecté

à la Jag (vois aussi sur la page de Mathias Domin)

 

C1 C2 C3 Controller Type

0 0 0 Reserved

1 0 0 Analog stick

0 1 0 Reserved

1 1 0 Rotary controller

0 0 1 6D controller

1 0 1 head tracker

0 1 1 Reserved

1 1 1 Standard joypad

Share this post


Link to post
Share on other sites
SebRmv    2

ouais désolé

mais Mathias Domin utilise apparemment C1 pour détecter le team tap

un petit examen de son source peut être instructif :P

 

Seb

Share this post


Link to post
Share on other sites
SebRmv    2

alors d'après son programme de test

quand le team tap est branché

on a C1 = 0 sur le 4ème pad du team tap

ça confirme le blabla sur son site

 

Seb

Share this post


Link to post
Share on other sites
Fadest    0

Some people bought a or made a rotary, essentially to play with Tempest 2K hidden mode, because few games can use it.

But managing rotary is really easy. Let's have a look on theory :

7.2    Example digital paddle code
===================================
A digital paddle is read in exactly the same way as a joypad, it is simply the interpretation that is different. In order to read a digital paddle, you will also need some kind of "memory element" - for example a static variable called last_position. Essentially the paddle will give out the following sequences:
- LEFT, NONE, RIGHT, LEFT... for anticlockwise
- RIGHT, NONE, LEFT, RIGHT... for clockwise
As a programmer you simply need to know the last position the paddle was in. If it is the same as the current one, the paddle has not been turned, otherwise you can determine which direction it was turned in from the information above. For example if the last position was with "LEFT" apparently pressed, then if the current position is also LEFT, the paddle has not moved. If the current position is RIGHT, the paddle has been moved clockwise. If there are NONE depressed (i.e. neither left nor right), then the paddle has been moved anticlockwise.
Get it?

Source : http://www.gamesx.com/controldata/ejp_faq.htm

 

So basically, we only need to check current pad status, and keep a trace of old pad status.

Here is a simple implementation or management routine in C, with Removers library (in detailled algorithmic/basic style to remains readable)

 

int old_dataJoypad;    // needed for memory : 0 = none / 1 = left / 2 = right

void rotary()
{
unsigned long dataJoypad;

    read_joypad_state(joypads);    // get state of every jagpads
    
    dataJoypad = joypads->j1;    // we only manage jagpad 1 for this demonstration routine

    if (dataJoypad & JOYPAD_LEFT)
    {
        if (old_dataJoypad == 2) 
        {
            // do whatever you need to move anticlockwise
        }
        else if (old_dataJoypad == 0) 
        {
            // do whatever you need to move clockwise
        }
        old_dataJoypad = 1;
    } 
    else if (dataJoypad & JOYPAD_RIGHT)
    {
        if (old_dataJoypad == 1) 
        {
            // do whatever you need to move clockwise
        }
        else if (old_dataJoypad == 0) 
        {
            // do whatever you need to move anticlockwise
        }
        old_dataJoypad = 2;
    } 
    else
    {
        if (old_dataJoypad == 1) 
        {
            // do whatever you need to move anticlockwise
        }
        else if (old_dataJoypad == 2) 
        {
            // do whatever you need to move clockwise
        }
        old_dataJoypad = 0;
    } 
}

 

You will soon notice that if you call this routine only once in a VBL, it won't work as expected.

This is because the rotary is far more sensible than 50 or 60hz. So between 2 read, you may miss some positions (remember this visual illusion how sometimes wheels seems to turn anticlockwise on TV ? same here).

So we need to put the call of rotary() subroutine into an interruption.

 

// First, interrupts must be initialized via call of function. Basically, put this call in main()
init_interrupts();

// Then, somewhere when we want interrupt to start, we need to use the set_timer firunction, in order to program an automatic call of rotary() :
set_timer(200<<16 | 360,rotary);

 

Just have a look here if you want more explanation on set_timer() :

http://www.os-forum.com/minix/net/general-...p?commentid=284

Basically, first parameter set interruption timer, second is the name of the function to be called.

The parameters I used are empiric, you'd better read explanation in order to calculate which one fit the best to your needs.

 

As you can see, managing rotary on Jaguar is really easy (this applies also to STE & Falcon of course).

Share this post


Link to post
Share on other sites
Zerosquare    10

This documentation is wrong. Encoders don't have 3 different states, they have 4 different states, They behave like a Gray code counter, incrementing for one direction of rotation, and decrementing for the other (explanation on Wikipedia)

 

It's also explained in the Jaguar developer docs, in the section about controllers. According to this, the sequences are :

 

Clockwise rotation is : none, right, left AND right, left.

Anticlockwise rotation is : none, left, left AND right, right.

 

Personally, my code is similar to this :

 

{
    unsigned long dataJoypad;
    unsigned long ph0, ph1, ph0_old, ph1_old; // ph0_old and ph1_old must be initialized, and preserved between calls to the routine

    dataJoypad = joypads->j1;    // we only manage jagpad 1 for this demonstration routine

    ph0 = !(dataJoypad & JOYPAD_LEFT);
    ph1 = !(dataJoypad & JOYPAD_RIGHT);

    if (ph0 ^ ph0_old ^ ph1 ^  ph1_old)
    {
        if (ph0 ^ ph1_old)
        {
             // do whatever you need to move anticlockwise
        }
        else
        {
              // do whatever you need to move clockwise
        }
    }
  
    ph0_old = ph0; 
    ph1_old = ph1;
}

 

(I've not tested it on the Jaguar, it's possible both directions are swapped)

Share this post


Link to post
Share on other sites
Tyrant    0
It's also explained in the Jaguar developer docs, in the section about controllers. According to this, the sequences are :

 

Clockwise rotation is : none, right, left AND right, left.

Anticlockwise rotation is : none, left, left AND right, right.

 

(I've not tested it on the Jaguar, it's possible both directions are swapped)

 

Having fired up teamtap.bin and hooking up one of my rotaries, I can confirm that the directions are in fact reversed.

 

When rotating clockwise the pattern is:

none, left, both, right

and anticlockwise is:

none, right, both, left

 

I seem to remember that this was so the first level of tempest made more sense. If you want the claw to travel clockwise around the level, twist clockwise.

 

-- Tyr (aka Tyrant)

Share this post


Link to post
Share on other sites
Zerosquare    10

I meant the directions being wrong in my code -- the sequence itself is straight from the Jaguar developer manual ;)

 

But it's interesting to know that it works backwards in T2K : since all rotary controllers have been made for playing this game, it's now the standard :)

Share this post


Link to post
Share on other sites
SebRmv    2
// First, interrupts must be initialized via call of function. Basically, put this call in main()
init_interrupts();

// Then, somewhere when we want interrupt to start, we need to use the set_timer firunction, in order to program an automatic call of rotary() :
set_timer(200<<16 | 360,rotary);

 

Great post Fadest :flowers:

(better late than never for me to comment this thread ;))

 

The magic values correspond to PIT0 and PIT1 values

 

The frequency of the interrupt is computed as follows:

 

Frq = (Clock / (PIT0+1)) / (PIT1+1)

 

The set_timer function takes thus as first parameter the long word equal to (PIT0<<16)|(PIT1)

 

The system clock is approximately 26.5 MHz (SCPCD or Zerosquare, could you please recall us the exact value?)

 

Thus, in your case, you generate an interruption at a frequency of about 26500000/201/361 = 365,209961 Hz ie about every 2 ms

(compare to a VBL which is every 20 ms for 50 Hz display)

 

Maybe I should add some words about this in the documentation of my library :whistling:

Share this post


Link to post
Share on other sites
SebRmv    2

Thanks!

 

Share this post


Link to post
Share on other sites
ggn    1

I also posted this on the D-Bug forum a few minutes back, but I thought I'd mention it here, since I don't think there'll be anything different for the Jaguar :). Original text follows in verbatim.

 

 

Recently I've been messing around with Jagpad input and while I sorted it out easily, I wanted to add support for the teamtap as well. Not wanting to reinvent the wheel, I asked around for some advice on the matter. Zerosquare of CVSD pointed me to two solutions for this.

 

One was to use heuristics (i.e. make the user press a jagpad button and see if the button press is shadowed on other pads on the same port - if yes, the user most certainly doesn't have one installed), and the other was in fact a method by Matthias Domin, which reads a seemingly unused bit on the jagpad matrix on jagpad #4. Matthias claimed that if this bit (C1 on the jaguar docs) is inactive (at least on Falcon, jagpad bits are all set to 1 when the user doesn't press any button on the pad), then there's a teamtap installed.

 

That was just what I needed! So I quickly wrote a test program in GFA Basic and sent it to SH3 (I forgot to mention that I don't own a teamtap ;)). And that didn't work 100%. It turns out that this bit can change if there's no teamtap installed and the user presses the pause button. Fortunately we noticed that only bit C1 changes when you insert the teamtap in the port. So Matthias' claim was partly correct. The check that works 100% is:

 

  • if (bit c1 in jagpad #4)=set and (bit c2 in jagpad #4)=set then the user is using a single jagpad without teamtap and pressing pause
  • if (bit c1 in jagpad #4)=unset and (bit c2 in jagpad #4)=set then we have a teamtap! (the trick here is that when a teamtap is installed, then if jagpad #1 pause is set, you don't have any shadowing to the other pads)
  • if (bit c1 in jagpad #4)=unset and (bit c2 in jagpad #4)=unset then we have a normal jagpad, pause is not pressed

 

(note: "unset" means that the bit is in it's natural state and "set" means it's changed. As I mentioned, on the Falcon it's 1 for unset and 0 for set :))

(note #2: there's a 4th combination of bits, but I don't think it's possible to achieve this with a normal teamtap, so it's left out)

 

I hope I didn't screw anything up - after all, I tested at blind (sh3 was my eyes :)). If you find any inaccuracies, please mention them to me so I'll fix the text :)

 

 

Addendum: The shitty GFA program I used to test all of the above. It's not anything brainblasting, but at least it works (it's for port #1 btw) and it displays all ports' pad bits in the same screen.

 

DO
  PRINT AT(0,1)
  PRINT "teamtap port a"
  SDPOKE &HFFFF9202,&HFFFE
  PRINT BIN$(DPEEK(&HFFFF9200),16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFFD
  PRINT BIN$(DPEEK(&HFFFF9200),16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFFB
  PRINT BIN$(DPEEK(&HFFFF9200),16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFF7
  PRINT BIN$(DPEEK(&HFFFF9200),16)'BIN$(DPEEK(&HFFFF9202),16)
  '
  PRINT "teamtap port b"
  SDPOKE &HFFFF9202,&HFFF0
  PRINT BIN$(DPEEK(&HFFFF9200),16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFF1
  PRINT BIN$(x1%,16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFF2
  PRINT BIN$(x2%,16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFF3
  PRINT BIN$(x3%,16)'BIN$(DPEEK(&HFFFF9202),16)
  '
  PRINT "teamtap port c"
  SDPOKE &HFFFF9202,&HFFF4
  PRINT BIN$(DPEEK(&HFFFF9200),16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFF5
  PRINT BIN$(x1%,16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFF6
  PRINT BIN$(x2%,16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFF8
  PRINT BIN$(x3%,16)'BIN$(DPEEK(&HFFFF9202),16)
  '
  PRINT "teamtap port d"
  SDPOKE &HFFFF9202,&HFFF9
  PRINT BIN$(DPEEK(&HFFFF9200),16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFFA
  x1%=DPEEK(&HFFFF9200)
  PRINT BIN$(x1%,16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFFC
  x2%=DPEEK(&HFFFF9200)
  PRINT BIN$(x2%,16)'BIN$(DPEEK(&HFFFF9202),16)
  SDPOKE &HFFFF9202,&HFFFF
  x3%=DPEEK(&HFFFF9200)
  PRINT BIN$(x3%,16)'BIN$(DPEEK(&HFFFF9202),16)
  '
  PRINT
  PRINT "C1=";BTST(x1%,0);", C2=";BTST(x2%,0);", C3=";BTST(x3%,0)
  PRINT "So..."'
  IF BTST(x1%,0)=1 AND BTST(x2%,0)=0
    PRINT "you have a teamtap installed!"
  ELSE
    PRINT "you DO NOT have a teamtap installed!"
  ENDIF
LOOP UNTIL INKEY$<>""

Share this post


Link to post
Share on other sites
Guest
You are commenting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoticons maximum are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×