Sonic and Sega Retro Message Board: Sega Mouse - Sonic and Sega Retro Message Board

Jump to content

Hey there, Guest!  (Log In · Register) Help
Page 1 of 1
    Locked
    Locked Forum

Sega Mouse How does it work?

#1 User is offline Sodaholic 

Posted 06 December 2012 - 08:59 PM

  • Colony ship for sale, cheap!
  • Posts: 1004
  • Joined: 05-September 04
  • Gender:Male
  • Location:Ohio
I've been wondering, how does the mouse position tracking work? The wiki doesn't go into very much technical detail at all, and all I can gather is that it seems to use the regular A, B, C (and for the US model) Start buttons as a normal 3 button pad does (just an assumption on my part from what the wiki said of it).

The part I'm interested in is how does it send mouse movement information? Is it mostly hardware side and acts like an Atari paddle and positions are absolute? Or is it just sending relative info for how much it moved every interval, and mouse position is determined/handled by the software? Is it in any way using some form of D-pad commands?

#2 User is offline Chilly Willy 

Posted 07 December 2012 - 12:32 AM

  • Posts: 746
  • Joined: 10-April 09
  • Gender:Male
  • Project:Doom 32X
You need TH and TR set as outputs, with everything else set as inputs. Start with TH and TR set high for a vertical frame period to make sure the mouse is reset to starting a packet read. You then set TH low to start the mouse packet. You then toggle TR and watch TL to see when the mouse is ready. You get a nibble of info on the direction lines with each toggle of TR. You get a header, and then the mouse info. The header is 0x0, 0xB, 0xF, 0xF. The mouse info nibbles are direction-overflow flags, buttons, mouse x high nibble, mouse x low nibble, mouse y high nibble, and mouse y low nibble.

If you're good with C code, here's the code I wrote for sgdk:

static u8 THREELINE_HANDSHAKE(vu8 *pb, u8 ph)
{
    u8 val = 0, hs;

    *pb = ph; /* next phase in protocol */

    /* wait on handshake */
    hs = (ph >> 1) & 0x10;
    while (retry)
    {
        val = *pb;
        if ((val & 0x10) == hs)
            break; /* timeout */
        retry--;
    }

    return val & 0x0F;
}


static s16 start3lhs(u16 port, u8 *hdr, u16 len)
{
    vu8 *pb;
    u16 I;

    retry = 255;
    phase = 0x20; /* selected */

    /* make sure port direction is correct */
    pb = (vu8 *)0xa10009 + port*2;
    *pb = 0x60;

    /* make sure port is deselected to start at first phase */
    pb = (vu8 *)0xa10003 + port*2;
    hdr[0] = THREELINE_HANDSHAKE(pb, 0x60);
    if (retry)
    {
        for (I=1; I<len; I++)
        {
            hdr[I] = THREELINE_HANDSHAKE(pb, phase);
            phase ^= 0x20;
            if (!retry)
                break; /* timeout */
        }
    }
    if (!retry)
        *pb = 0x60; /* timeout - end request */

    return retry ? 0 : -1;
}


static u16 readMouse(u16 port)
{
    vu8 *pb;
    u16 val, I, mx, my;
    s16 sts;
    u8 hdr[4], md[6];

    pb = (vu8 *)0xa10003 + port*2;
    val = (JOY_TYPE_MOUSE << JOY_TYPE_SHIFT);

    sts = start3lhs(port, hdr, 4);
    if ((sts == 0) &&
        (hdr[0] == 0x00) &&
        (hdr[1] == 0x0B) &&
        (hdr[2] == 0x0F) &&
        (hdr[3] == 0x0F))
    {
        /* handle mouse */
        for (I=0; I<6; I++)
        {
            md[I] = THREELINE_HANDSHAKE(pb, phase);
            phase ^= 0x20;
            if (!retry)
                break; /* timeout */
        }
        if (I == 6)
        {
            if (md[0] & 0x04)
                mx = 256; /* x overflow */
            else
                mx = md[2]<<4 | md[3];
            if (md[0] & 0x01)
                mx |= 0xFF00; /* x sign extend */
            if (md[0] & 0x08)
                my = 256; /* y overflow */
            else
                my = md[4]<<4 | md[5];
            if (md[0] & 0x02)
                my |= 0xFF00; /* y sign extend */
            joyAxisX[port] += (s16)mx;
            joyAxisY[port] += (s16)my;

            if (md[1] & 8) val |= BUTTON_START;
            if (md[1] & 4) val |= BUTTON_MMB;
            if (md[1] & 2) val |= BUTTON_RMB;
            if (md[1] & 1) val |= BUTTON_LMB;

            if ((s16)mx < -2) val |= BUTTON_LEFT;
            else if ((s16)mx > 2) val |= BUTTON_RIGHT;
            if ((s16)my < -2) val |= BUTTON_DOWN;
            else if ((s16)my > 2) val |= BUTTON_UP;
        }
    }
    *pb = 0x60; /* end request */

    return val;
}




Most of my examples also have mouse reading code in assembly.

Page 1 of 1
    Locked
    Locked Forum

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users