Page 22 of 57

Posted: Wed Jan 18, 2012 7:50 am
by Mixail
SGDK 0.9 Supports 6 buttons?

Posted: Wed Jan 18, 2012 10:54 am
by Stef
Mixail wrote:SGDK 0.9 Supports 6 buttons?
Unfortunately not yet, only 3 buttons joypad are supported right now.

Posted: Wed Jan 18, 2012 10:54 am
by KanedaFr
short answer : no

long answer : not yet.
I have a WIP update for 6 buttons, TPlay, EA and mouse support.
I also bought a pink justifier to add justifier support too (and still looking for a cheap menacer)
But since I can't test it on real hardware, it's waiting on my hard drive for 1 year now :(

Posted: Wed Jan 18, 2012 2:21 pm
by Mixail
KanedaFr wrote:short answer : no

long answer : not yet.
I have a WIP update for 6 buttons, TPlay, EA and mouse support.
I also bought a pink justifier to add justifier support too (and still looking for a cheap menacer)
But since I can't test it on real hardware, it's waiting on my hard drive for 1 year now :(
It is a pity.

Why not to buy Flash cartridge for the test?

Posted: Wed Jan 18, 2012 2:38 pm
by Mixail
What function in SDK 0.9 is similar to function "void sleepFrames (u16 frames);"

Posted: Wed Jan 18, 2012 4:32 pm
by KanedaFr
Mixail wrote:It is a pity.
Why not to buy Flash cartridge for the test?
because I have a SMD but no time to fix it and I keep my money for the hosting ;)
What function in SDK 0.9 is similar to function "void sleepFrames (u16 frames);"
You could easily make it yourself with the help of VDP_waitVSync()

Posted: Wed Jan 18, 2012 5:16 pm
by Mixail
KanedaFr wrote:
Mixail wrote:It is a pity.

You could easily make it yourself with the help of VDP_waitVSync()
sleepFrames (100); ???

VDP_waitVSync();
VDP_waitVSync();
VDP_waitVSync();
...

Posted: Wed Jan 18, 2012 10:51 pm
by KanedaFr
???
seriously! what about a for loop ?!

Posted: Wed Jan 18, 2012 11:01 pm
by Chilly Willy
No, more like

Code: Select all

void sleepFrames(u16 frame)
{
    while (frames--)
        VDP_waitVSync();
}

Posted: Thu Jan 19, 2012 12:38 am
by Chilly Willy
For six button support, try this:

Code: Select all

static u16 readJoypad(u16 joy)
{
    vu8 *pb;
    u16 i, j, k;

    if (joy < 2)
    {
        pb = (u8 *) (0xA10003 + (joy * 2));

        if (portSupport[joy] == JOY_SUPPORT_3BTN)
        {
            asm("move.b  #0x00,(%2)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%2),%0\n\t"
                "move.b  #0x40,(%2)\n\t"
                "lsl.b   #2,%0\n\t"
                "andi.w  #0xC0,%0\n\t"
                "move.b  (%2),%1\n\t"
                "andi.w  #0x3F,%1\n\t"
                "or.b    %1,%0\n\t"
                "eori.b  #0xFF,%0\n\t"
                : "=d" (i), "=d" (j)
                : "a" (pb)
                : );
            return i;
        }
        if (portSupport[joy] == JOY_SUPPORT_6BTN)
        {
            asm("move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.w  %0,%1\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.w  %0,%2\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "andi.w  #0x0F00,%0\n\t"
                "cmpi.w  #0x0F00,%0\n\t"
                "beq.b   common\n\t"
                "move.w  #0x010F,%2\n"
                "common:\n\t"
                "lsl.b   #4,%2\n\t"
                "lsl.w   #4,%2\n\t"
                "andi.w  #0x303F,%1\n\t"
                "move.b  %1,%2\n\t"
                "lsr.w   #6,%1\n\t"
                "or.w    %1,%2\n\t"
                "eori.w  #0x1FFF,%2\n\t"
                : "=d" (i), "=d" (j), "=d" (k)
                : "a" (pb)
                : );
            return k;
        }
    }
    else if (joy < 6)       // teamplay 1
    {
        // not yet supported
        return 0;
    }
    else if (joy < 9)       // teamplay 2
    {
        // not yet supported
        return 0;
    }

    return 0;
}
That should work... it's based on working code and compiles without error - I even examined the generated assembly. However, there's no joystick test example and I'm too lazy to make one. :lol:

Remember that JOY_Init() sets both ports to 3 button mode. You need to call JOY_setSupport(port, JOY_SUPPORT_6BTN) to switch to 6 button reading. The function will then return all the buttons as already defined in joy.h. If you read a 3 button stick in 6 button mode, it still works, but it's slower than using 3 button mode. You can tell 3 button sticks from 6 button by reading the port in 6 button mode - if there really is a 6 buttons stick there, the upper nibble is a 1, otherwise it's a 0. So you might do something like this:

Code: Select all

    JOY_setSupport(PORT_1, JOY_SUPPORT_6BTN);
    JOY_update();
    if ((JOY_readJoypad(JOY_1) & 0xF000) != 0x1000)
        JOY_setSupport(PORT_1, JOY_SUPPORT_3BTN);
That sets port 1 to 6 button, checks if there is a six button pad, and turns it back to 3 button if there isn't.

Posted: Sun Jan 22, 2012 10:10 am
by Mixail
Chilly Willy wrote:For six button support, try this:

Code: Select all

static u16 readJoypad(u16 joy)
{
    vu8 *pb;
    u16 i, j, k;

    if (joy < 2)
    {
        pb = (u8 *) (0xA10003 + (joy * 2));

        if (portSupport[joy] == JOY_SUPPORT_3BTN)
        {
            asm("move.b  #0x00,(%2)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%2),%0\n\t"
                "move.b  #0x40,(%2)\n\t"
                "lsl.b   #2,%0\n\t"
                "andi.w  #0xC0,%0\n\t"
                "move.b  (%2),%1\n\t"
                "andi.w  #0x3F,%1\n\t"
                "or.b    %1,%0\n\t"
                "eori.b  #0xFF,%0\n\t"
                : "=d" (i), "=d" (j)
                : "a" (pb)
                : );
            return i;
        }
        if (portSupport[joy] == JOY_SUPPORT_6BTN)
        {
            asm("move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.w  %0,%1\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.w  %0,%2\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "andi.w  #0x0F00,%0\n\t"
                "cmpi.w  #0x0F00,%0\n\t"
                "beq.b   common\n\t"
                "move.w  #0x010F,%2\n"
                "common:\n\t"
                "lsl.b   #4,%2\n\t"
                "lsl.w   #4,%2\n\t"
                "andi.w  #0x303F,%1\n\t"
                "move.b  %1,%2\n\t"
                "lsr.w   #6,%1\n\t"
                "or.w    %1,%2\n\t"
                "eori.w  #0x1FFF,%2\n\t"
                : "=d" (i), "=d" (j), "=d" (k)
                : "a" (pb)
                : );
            return k;
        }
    }
    else if (joy < 6)       // teamplay 1
    {
        // not yet supported
        return 0;
    }
    else if (joy < 9)       // teamplay 2
    {
        // not yet supported
        return 0;
    }

    return 0;
}
That should work... it's based on working code and compiles without error - I even examined the generated assembly. However, there's no joystick test example and I'm too lazy to make one. :lol:

Remember that JOY_Init() sets both ports to 3 button mode. You need to call JOY_setSupport(port, JOY_SUPPORT_6BTN) to switch to 6 button reading. The function will then return all the buttons as already defined in joy.h. If you read a 3 button stick in 6 button mode, it still works, but it's slower than using 3 button mode. You can tell 3 button sticks from 6 button by reading the port in 6 button mode - if there really is a 6 buttons stick there, the upper nibble is a 1, otherwise it's a 0. So you might do something like this:

Code: Select all

    JOY_setSupport(PORT_1, JOY_SUPPORT_6BTN);
    JOY_update();
    if ((JOY_readJoypad(JOY_1) & 0xF000) != 0x1000)
        JOY_setSupport(PORT_1, JOY_SUPPORT_3BTN);
That sets port 1 to 6 button, checks if there is a six button pad, and turns it back to 3 button if there isn't.

This code doesn't work.

Posted: Sun Jan 22, 2012 5:53 pm
by Chilly Willy
Okay, I'll make an example and check it.

EDIT: Okay - worked out any problems. The assembly was fine, but the Windows gcc included with sgdk doesn't like an empty clobber list, so I stuck in something to get it to pass. Other things I found:

joy.h has BUTTON_X and BUTTON_Z swapped. Reverse them.

You need to wait at least one vblank after setting the port support type for the vblank to automatically call JOY_update() - if you call it yourself, you can wind up with the wrong pad ID since you may wind up calling update just before or just after vblank does, screwing up the six button pad timing for reset for next packet. I wait two vblanks just to be safe.

JOY_init() was setting the directions, but not the values.

So... file changes:

joy.c

Code: Select all

void JOY_init()
{
    vu8 *pb;

    /* set the port bits direction */
    pb = (u8 *) 0xa10009;
    *pb = 0x40;
    pb += 2;
    *pb = 0x40;
    pb += 2;
    *pb = 0x40;
    /* set the port bits value */
    pb = (u8 *) 0xa10003;
    *pb = 0x40;
    pb += 2;
    *pb = 0x40;
    pb += 2;
    *pb = 0x40;

    memset(joyState, 0, sizeof(joyState));

    portSupport[PORT_1] = JOY_SUPPORT_3BTN;
    portSupport[PORT_2] = JOY_SUPPORT_3BTN;

    joyEventCB = NULL;
}
and

Code: Select all

static u16 readJoypad(u16 joy)
{
    vu8 *pb;
    u16 i, j, k;

    if (joy < 2)
    {
        pb = (u8 *) (0xA10003 + (joy * 2));

        if (portSupport[joy] == JOY_SUPPORT_3BTN)
        {
            asm("move.b  #0x00,(%2)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%2),%0\n\t"
                "move.b  #0x40,(%2)\n\t"
                "lsl.b   #2,%0\n\t"
                "andi.w  #0xC0,%0\n\t"
                "move.b  (%2),%1\n\t"
                "andi.w  #0x3F,%1\n\t"
                "or.b    %1,%0\n\t"
                "eori.b  #0xFF,%0\n\t"
                : "=d" (i), "=d" (j)
                : "a" (pb)
                : "0" );
            return i;
        }
        if (portSupport[joy] == JOY_SUPPORT_6BTN)
        {
            asm("move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.w  %0,%1\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "move.w  %0,%2\n\t"

                "move.b  #0x00,(%3)\n\t"
                "nop\n\t"
                "nop\n\t"
                "move.b  (%3),%0\n\t"
                "move.b  #0x40,(%3)\n\t"
                "lsl.w   #8,%0\n\t"
                "move.b  (%3),%0\n\t"

                "andi.w  #0x0F00,%0\n\t"
                "cmpi.w  #0x0F00,%0\n\t"
                "beq.b   common\n\t"
                "move.w  #0x010F,%2\n"
                "common:\n\t"
                "lsl.b   #4,%2\n\t"
                "lsl.w   #4,%2\n\t"
                "andi.w  #0x303F,%1\n\t"
                "move.b  %1,%2\n\t"
                "lsr.w   #6,%1\n\t"
                "or.w    %1,%2\n\t"
                "eori.w  #0x1FFF,%2\n\t"
                : "=d" (i), "=d" (j), "=d" (k)
                : "a" (pb)
                : "0" );
            return k;
        }
    }
    else if (joy < 6)       // teamplay 1
    {
        // not yet supported
        return 0;
    }
    else if (joy < 9)       // teamplay 2
    {
        // not yet supported
        return 0;
    }

    return 0;
}
joy.h

Code: Select all

#define BUTTON_X        0x0400
#define BUTTON_Y        0x0200
#define BUTTON_Z        0x0100
Recompile the library and then here's a joypad test program:

Code: Select all

#include "genesis.h"


static void printButton(char c, u16 state);

static void showPortState();

static u16 posY, posX;


int main(int cold_start)
{
    JOY_setSupport(PORT_1, JOY_SUPPORT_6BTN);
    VDP_waitVSync();
    VDP_waitVSync();
    if ((JOY_readJoypad(JOY_1) & 0xF000) != 0x1000)
        JOY_setSupport(PORT_1, JOY_SUPPORT_3BTN);
    JOY_setSupport(PORT_2, JOY_SUPPORT_6BTN);
    VDP_waitVSync();
    VDP_waitVSync();
    if ((JOY_readJoypad(JOY_2) & 0xF000) != 0x1000)
        JOY_setSupport(PORT_2, JOY_SUPPORT_3BTN);

    VDP_setScreenWidth320();
    VDP_setHInterrupt(0);
    VDP_setHilightShadow(0);
    VDP_setPaletteColor(PAL1, 15, 0x0888);
    VDP_setTextPalette(0);
    VDP_drawText("Current Joy Port State", 10, 1);

    VDP_clearTileMapRect(APLAN, 0, 3, 40, 8);
    showPortState();
    while(1)
    {
        showPortState();
        VDP_waitVSync();
    }
}


static void printButton(char c, u16 state)
{
    char temp[2];
    temp[0] = c;
    temp[1] = 0;
    VDP_setTextPalette(state ? 1 : 0);
    VDP_drawText(temp, posX, posY);
    posX += 2;
}

static void showPortState()
{
    u16 i;

    posY = 5;
    for(i = JOY_1; i <= JOY_2; i++)
    {
        u16 value;

        posX = 2;
        VDP_setTextPalette(0);
        VDP_drawText((i == JOY_1) ? "port 1:" : "port 2:", posX, posY);
        posX += 8;
        value = JOY_readJoypad(i);
        printButton('U', value & BUTTON_UP);
        printButton('D', value & BUTTON_DOWN);
        printButton('L', value & BUTTON_LEFT);
        printButton('R', value & BUTTON_RIGHT);
        printButton('A', value & BUTTON_A);
        printButton('B', value & BUTTON_B);
        printButton('C', value & BUTTON_C);
        printButton('S', value & BUTTON_START);
        if ((value & 0xF000) == 0x1000)
        {
            /* six button pad */
            printButton('X', value & BUTTON_X);
            printButton('Y', value & BUTTON_Y);
            printButton('Z', value & BUTTON_Z);
            printButton('M', value & BUTTON_MODE);
        }
        posY++;
    }
}
Do all that and it will work fine for three and six button pads. Tested and verified on Fusion, Gens/GS, and on real hardware.

Posted: Sun Jan 22, 2012 9:22 pm
by Chilly Willy
Actually, part of the start of that test program could be redone like this:

Code: Select all

    JOY_setSupport(PORT_1, JOY_SUPPORT_6BTN);
    JOY_setSupport(PORT_2, JOY_SUPPORT_6BTN);
    VDP_waitVSync();
    VDP_waitVSync();
    if ((JOY_readJoypad(JOY_1) & 0xF000) != 0x1000)
        JOY_setSupport(PORT_1, JOY_SUPPORT_3BTN);
    if ((JOY_readJoypad(JOY_2) & 0xF000) != 0x1000)
        JOY_setSupport(PORT_2, JOY_SUPPORT_3BTN);
EDIT: Also, that first showPortState() isn't needed, so just make main() this:

Code: Select all

int main(int cold_start)
{
    JOY_setSupport(PORT_1, JOY_SUPPORT_6BTN);
    JOY_setSupport(PORT_2, JOY_SUPPORT_6BTN);
    VDP_waitVSync();
    VDP_waitVSync();
    if ((JOY_readJoypad(JOY_1) & 0xF000) != 0x1000)
        JOY_setSupport(PORT_1, JOY_SUPPORT_3BTN);
    if ((JOY_readJoypad(JOY_2) & 0xF000) != 0x1000)
        JOY_setSupport(PORT_2, JOY_SUPPORT_3BTN);

    VDP_setScreenWidth320();
    VDP_setHInterrupt(0);
    VDP_setHilightShadow(0);
    VDP_setPaletteColor(PAL1, 15, 0x0888);
    VDP_setTextPalette(0);
    VDP_drawText("Current Joy Port State", 10, 1);

    VDP_clearTileMapRect(APLAN, 0, 3, 40, 8);
    while(1)
    {
        showPortState();
        VDP_waitVSync();
    }
}

Posted: Mon Jan 23, 2012 4:25 pm
by Mixail
Chilly Willy Thank you very much.

Posted: Mon Jan 23, 2012 5:57 pm
by Chilly Willy
You're welcome. If you need the mouse, I can work that in as well.