Sega Genesis Dev Kit (SGDK)

SGDK only sub forum

Moderator: Stef

Mixail
Very interested
Posts: 133
Joined: Thu Nov 18, 2010 4:47 pm

Post by Mixail »

SGDK 0.9 Supports 6 buttons?
Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef »

Mixail wrote:SGDK 0.9 Supports 6 buttons?
Unfortunately not yet, only 3 buttons joypad are supported right now.
KanedaFr
Administrateur
Posts: 1154
Joined: Tue Aug 29, 2006 10:56 am
Contact:

Post 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 :(
Mixail
Very interested
Posts: 133
Joined: Thu Nov 18, 2010 4:47 pm

Post 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?
Mixail
Very interested
Posts: 133
Joined: Thu Nov 18, 2010 4:47 pm

Post by Mixail »

What function in SDK 0.9 is similar to function "void sleepFrames (u16 frames);"
KanedaFr
Administrateur
Posts: 1154
Joined: Tue Aug 29, 2006 10:56 am
Contact:

Post 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()
Mixail
Very interested
Posts: 133
Joined: Thu Nov 18, 2010 4:47 pm

Post 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();
...
KanedaFr
Administrateur
Posts: 1154
Joined: Tue Aug 29, 2006 10:56 am
Contact:

Post by KanedaFr »

???
seriously! what about a for loop ?!
Chilly Willy
Very interested
Posts: 2993
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy »

No, more like

Code: Select all

void sleepFrames(u16 frame)
{
    while (frames--)
        VDP_waitVSync();
}
Chilly Willy
Very interested
Posts: 2993
Joined: Fri Aug 17, 2007 9:33 pm

Post 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.
Mixail
Very interested
Posts: 133
Joined: Thu Nov 18, 2010 4:47 pm

Post 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.
Chilly Willy
Very interested
Posts: 2993
Joined: Fri Aug 17, 2007 9:33 pm

Post 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.
Chilly Willy
Very interested
Posts: 2993
Joined: Fri Aug 17, 2007 9:33 pm

Post 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();
    }
}
Mixail
Very interested
Posts: 133
Joined: Thu Nov 18, 2010 4:47 pm

Post by Mixail »

Chilly Willy Thank you very much.
Chilly Willy
Very interested
Posts: 2993
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy »

You're welcome. If you need the mouse, I can work that in as well.
Post Reply