Mega Mouse unused nibbles research

For anything related to IO (joypad, serial, XE...)

Moderator: BigEvilCorporation

Sik
Very interested
Posts: 880
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Mega Mouse unused nibbles research

Post by Sik » Fri Jul 12, 2019 9:36 am

The first three nibbles of a Mega/Sega Mouse packet are always 1011 1111 1111, however technically only the first one is meant to be used to identify a mouse (or 1101 if it's a tablet). I was wondering how much compatibility would be broken if those two nibbles were repurposed (e.g. to give mouse wheel input when using an USB-to-MD adapter or whatever).

I did these tests by taking BlastEm's source code and modifying the mouse output to feed wrong values for those two bytes. This means I couldn't test any Mega CD games though, so it's possible something got missed :/ (anybody willing to test those is welcome)

Games tested:
  • Body Count
  • Fun'n'Games
  • Janou Touryuumon
  • Jimmy White's Whirlwind Snooker
  • Lemmings 2
  • Lord Monarch
  • Marble Madness (Tengen)
  • Nobunaga no Yabou
  • Nobunaga's Ambition
  • Richard Scarry's Busytown
  • Shangai II - Dragon's Eye
  • Two Tribes - Populous II
  • Wacky Worlds
Jimmy White's Whirlwind Snooker is utterly broken even with valid packets (it fails to handle the mouse going too fast, etc.), so let's ignore that one.

As for everything else… they all Just Work™. Yeah, all of them ignore whatever is in those two 1111 nibbles, they only care about the 1011 one. On the other hand, SGDK seems to want all three nibbles to be exactly 1011 1111 1111 (whoops)… Looks like the packet is just ignored if they don't match at least (instead of completely dropping the mouse), though it also will look as if no buttons are pressed. I hope there isn't much breakage out there if somebody decides to add mouse wheel or something in their own version of the mouse (・-・;)

Most games need (and/or can take) the mouse in the first port. Fun'n'Games is the exception, requiring it in the second port (and a controller in the first port, which you need to get past the title screen).


tl;dr
  • The two 1111 1111 nibbles in the mouse packet are meant to be ignored and only the 1011 should be used for identification. Do not rely on the 1111 1111 nibbles to detect a mouse.
  • Changing the values of those two nibbles doesn't look like it'd break anything significant, which may come in handy if somebody builds an adapter or builds new mouses and wants to add support for mouse wheel or whatever else (a way to toggle extensions off is probably still a good idea).
Last edited by Sik on Tue Jul 16, 2019 11:43 pm, edited 1 time in total.
Sik is pronounced as "seek", not as "sick".

Chilly Willy
Very interested
Posts: 2768
Joined: Fri Aug 17, 2007 9:33 pm

Re: Mega Mouse unused nibbles research

Post by Chilly Willy » Fri Jul 12, 2019 7:40 pm

The SGDK thing is my fault... and not my fault. All the code I've seen for handling the mouse looks for those two F nibbles, so my code did too. This will work on any mouse that's 100% compatible... but won't work if someone makes something that uses those two nibbles AND doesn't return F by default (when not pushing a button or moving a wheel etc). I do think you're right about changing the SGDK to not check for those nibbles.

At line 686, just take out the compares in the if statement

Code: Select all

    sts = start3lhs(port, hdr, 4);
    if ((sts == 0) &&
        (hdr[0] == 0x00) &&
        (hdr[1] == 0x0B) &&
        (hdr[2] == 0x0F) &&
        (hdr[3] == 0x0F))
    {
        /* handle mouse */
Also in my code for the Dune mouse patch, there's a check there

At line 167,

Code: Select all

; get header
        moveq   #1,d2               ; two bytes (four nibbles) in header
        bsr.w   do_tlh
; check header
        cmpi.w  #$0BFF,d0           ; check for mouse
        bne.w   mouse_err
should be changed to

Code: Select all

; get header
        moveq   #1,d2               ; two bytes (four nibbles) in header
        bsr.w   do_tlh
; check ID
        lsr.w   #8,d0
        cmpi.b  #$0B,d0             ; check for mouse
        bne.w   mouse_err
If a device used those two nibbles, you'd pull the two nibbles out of the header read and add them to the packet read. Pretty simple. I think we can leave those as ignored header bytes for now as nothing is using them, and since this is for a mouse, we'd ignore those nibbles in any case.

Sik
Very interested
Posts: 880
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: Mega Mouse unused nibbles research

Post by Sik » Sat Jul 13, 2019 7:27 am

Yeah, I told Stef to remove those two comparisons from that check.

Something interesting: the first nibble determines if it's a mouse (1011) or a tablet (1101), with the rest of the packet being the same for both, presumably. Meanwhile the Sega Graphic Board on Master System has a completely different format despite Sega Graphic Board looking exactly the same as the tablet shown in Beep (either that was a mock-up, or this predates the mouse protocol). The interesting part is that the information in the packet is mostly the same (aside from lack of sign/overflow) but there are two nibbles that makes up a "pressure" byte, and if it's 0xFD or higher it pretty much makes the cursor follow the pen on the tablet (you also have to press a button to make it draw >.>). I wouldn't be surprised if they're the pressure value for the tablet and mouse returns 0xFF to pretend to be always pressing.

I have absolutely no clue why they bothered with pressure instead of making it a "button", as it seems to have practically no useful resolution lol.


EDIT: by the way before I forget, if you don't mind about d0's value (and seems you don't since you slapped a bit shift) then maybe this is faster (OK, I'm just being nitpicky :​P)

Code: Select all

; get header
        moveq   #1,d2               ; two bytes (four nibbles) in header
        bsr.w   do_tlh
; check ID
        and.w   #$FF00,d0
        cmpi.w  #$0B00,d0           ; check for mouse
        bne.w   mouse_err
Sik is pronounced as "seek", not as "sick".

Chilly Willy
Very interested
Posts: 2768
Joined: Fri Aug 17, 2007 9:33 pm

Re: Mega Mouse unused nibbles research

Post by Chilly Willy » Sat Jul 13, 2019 1:04 pm

Oh, yeah. That's much faster. And D0 doesn't matter or I wouldn't have put in the shift. :D

It IS a little bigger, so maybe you'd choose one over the other depending on space vs speed.

Stef
Very interested
Posts: 2977
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mega Mouse unused nibbles research

Post by Stef » Mon Jul 15, 2019 7:46 am

I just pushed changes so it now ignores the FF part of the header :-)
Still someone reported (in SGDK Discord server) that menacer support (and probably justifier as well) is broken is last SGDK. It looks like that joytest binary from December 13th 2014 is ok, but I saw you pushed important changes on December 24th 2014. I don't know if these changes broken justifier support but at least I didn't saw majors changes since then..
The problem is that I can't test that code myself as I don't own any of those peripheral (except on emulators but I don't trust them too much for special peripherals ^^).

Chilly Willy
Very interested
Posts: 2768
Joined: Fri Aug 17, 2007 9:33 pm

Re: Mega Mouse unused nibbles research

Post by Chilly Willy » Mon Jul 15, 2019 1:40 pm

Ugh... I'll take a look at it, but it means digging out my TIMM and the light guns. Now all I need is somewhere to put it...

Are you sure about that date? The only change in the joy.c file around that time was a MINOR change to the mouse code on Dec 23, 2014.

Code: Select all

            else
                my = md[4]<<4 | md[5];
            if (md[0] & 0x02)
-                my |= mx ? 0xFF00 : 0xFFFF; /* y sign extend */
+               my |= my ? 0xFF00 : 0xFFFF; /* y sign extend */
            joyAxisX[port] += (s16)mx;
            joyAxisY[port] += (s16)my;
Oh, another thing... the current test code is hardcoded to enable the Phaser and disable port 2 light guns.

Code: Select all

#if 1
    JOY_setSupport(PORT_2, JOY_SUPPORT_PHASER);
#endif

#if 0
    value = JOY_getPortType(PORT_2);
    switch (value)
    {
        case PORT_TYPE_MENACER:
            JOY_setSupport(PORT_2, JOY_SUPPORT_MENACER);
            break;
Phaser support would need to be turned off and port 2 turned on to properly test menacer and justifier support via the test app.

Stef
Very interested
Posts: 2977
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mega Mouse unused nibbles research

Post by Stef » Tue Jul 16, 2019 8:42 am

Oh i meant the 23 dec 2014 commit :
https://github.com/Stephane-D/SGDK/comm ... 4809afa177

From the changelog:
* added Sega Phaser support (Chilly Willy).
* updated Joy sample to add Phaser test (Chilly Willy).
And you can see that many changes were made to joy.c file.
But i guess you tested them at this point...

Here's what reported Diode:
I've been trying pinpoint the problem with the menacer. Although I have a real Menacer, I have been testing on an emulator today.

Type detection DOES work, I don't know why it didn't seem to be earlier.

I noticed that the original sample files were written before VDP_Init(); and Joy_Init(); seem to have been added/required, and that calling JOY_setSupport(PORT_2, JOY_SUPPORT_MENACER); freezes the VDP and requires a VDP_ResetScreen before the screen will update. If VDP_Init() is called AFTER support is set, it will retrieve values for a split second and then stop, but screen updates will continue. This doesn't happen when resetting a frozen VDP that was called before setting Menacer support.

The Justifier currently works, but is extremely crash prone, often causing the VDP to freeze within seconds.
I also noticed that the Justifier behaves the same way even when support is set for the Menacer, provided that there is no VDP_resetScreen call after it.
Not sure how interpret that though... I tried to add some safety (about interrupt level restoration for instance as changing support can change interrupt level) but it seems to not have made any changes.

Sik
Very interested
Posts: 880
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: Mega Mouse unused nibbles research

Post by Sik » Tue Jul 16, 2019 12:53 pm

As dumb as this may sound but… what's the setting for the HV counter? Is it running or latched? Because I wouldn't be surprised if the lightgun code wants the HV counter latched, while unrelated code may expect it to be running.
Sik is pronounced as "seek", not as "sick".

Chilly Willy
Very interested
Posts: 2768
Joined: Fri Aug 17, 2007 9:33 pm

Re: Mega Mouse unused nibbles research

Post by Chilly Willy » Tue Jul 16, 2019 2:19 pm

I dug out my TIMM, but I'm looking for the box with my light guns now. :D

I'm inclined to think it's something interfering with the light gun resources in his code rather than the code itself. Certain things are needed for light guns to work.

Code: Select all

                SYS_setExtIntCallback(externalIntCB);
                pb = (vu8 *)0xa10009 + port*2;
                *pb = 0x80;                     /* enable TH->HL */
                val = VDP_getReg(0);
                VDP_setReg(0, val | 0x02);      /* set M3, enable HV counter latch */
                val = VDP_getReg(11);
                VDP_setReg(11, val | 0x08);     /* set IE2, enable external int */
                SYS_setInterruptMaskLevel(1);   /* External int allowed */
Light guns need the external int set to a handler that can handle the light gun interrupt. The controller port TH->TL level change int must be enabled. The VDP must latch the HV counters and enable the external int. If those VDP setting are changed in VDP_init(), then the light gun must be set after VDP_init(). Joytest is more the older style, not using VDP_Init or Joy_Init... I should probably update it and make sure things still work.

While the light gun points at the screen, the joyAxisX and joyAxisY arrays hold the h and v counter values. When not pointed at the screen, the joyAxisX and joyAxisY arrays are set to -1 to make it easy to distinguish between onscreen and offscreen.

A quick look at VDP_init shows that it would turn off light gun settings, so setting the support type should be done after VDP_init. It should also be done after JOY_init.

Are there other VDP functions that affect register 0 and 11 that may need to watch the current settings for light guns? It's possible a VDP function updated that now clears something the light gun expects to be set. Or perhaps there's some Z80 handling code that assumes the int level is always 3 when light gun code needs it to be 1?

EDIT: Don't see any int level issues in SGDK, but his code might have some. Found all my light guns, but the battery cover for my Menacer is missing... fell off during shipping or packing. :( Maybe I'll find it later, but I've got the Phaser and the Justifiers. If I get them working, I'm sure the Menacer works, too. Found a bunch of Genesis controllers, including my extra Mega Mouse. Found my SMS and SMS controllers, including the track ball and Phaser. Found the extension cords I bought for the Genesis and Saturn intending to make a few into Saturn to Genesis adapter cables. God, that was hot work, and a royal pain, and I'm missing one of the most important parts of my Menacer. :x

Found my PSP AV cable, but still no PSP! I'm really starting to worry that it got stolen during the move. Also found the battery pack for my Nomad, complete with decomposing batteries.

Chilly Willy
Very interested
Posts: 2768
Joined: Fri Aug 17, 2007 9:33 pm

Re: Mega Mouse unused nibbles research

Post by Chilly Willy » Tue Jul 16, 2019 10:27 pm

Found the problem - you're using the vcounter in the vblnk callback for timing. When the light gun code sets the counters to latch, it hangs your code. If you disable the code that sets the counters to latch, everything's peachy... except the lightgun value varies quite a bit as the counters aren't latched anymore. You need to bypass your timing code if a light gun is in use to avoid this issue.

EDIT: BTW, adding VDP_init() and JOY_init() to the start of joytest seems to be fine, so you should probably change the local copy to add that.

Sik
Very interested
Posts: 880
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: Mega Mouse unused nibbles research

Post by Sik » Tue Jul 16, 2019 11:44 pm

Added Lemmings 2 to the list (spoiler: same deal as every other game that isn't Jimmy White).
Sik is pronounced as "seek", not as "sick".

Stef
Very interested
Posts: 2977
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mega Mouse unused nibbles research

Post by Stef » Wed Jul 17, 2019 10:13 am

@Chilly Willy> Thanks for having investigated the issue. I will change the timer code to take care of that :)
I have to admit i don't know too much about that HV latching, i though it was "temporary", just the time you read out the HV value from the Int2 callback then the latch was released (probably by writing according register to VDP). Is that the case ?

About VDP_init() / JOY_init() call at start, they are not needed, SGDK call them on reset internally before giving hand to main() method.

Stef
Very interested
Posts: 2977
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Mega Mouse unused nibbles research

Post by Stef » Wed Jul 17, 2019 11:08 am

After having checked my code, the HV counter latching shouldn't have been a problem as i didn't used the HV Counter for passive wait in usual code, i'm using it mainly for CPU usage statistics.. Anyway i modified the getSubTick() method to take care of that, hoping it will be enough to resolve these problems !

Chilly Willy
Very interested
Posts: 2768
Joined: Fri Aug 17, 2007 9:33 pm

Re: Mega Mouse unused nibbles research

Post by Chilly Willy » Wed Jul 17, 2019 5:02 pm

joytest.zip
(1.28 KiB) Downloaded 14 times
I couldn't tell you why it was hanging, but it was. And the new code fixes the issue. The new functions for checking and setting latched counters is a good idea in any case. Here's the joytest main.c file - I changed it a bit to make it clear that you can compile with it set to auto detect the peripherals, or force the setting of trackball or phaser. Since those are SMS controllers, they don't autodetect. The code also defaults to autodetect. I also set it to use VDP_init() and JOY_init().

Tested with the phaser and justifiers, which work properly. I also checked the trackball... which for some reason now thinks the ball is constantly moving in some direction (random). I don't know if it's the trackball, or the library. Need to find something that uses the trackball and verify it's not the trackball. It decodes the buttons correctly, and it decodes moving the ball if you actually move it, so there's nothing wrong with the decoding code that I can tell. It's just that when you aren't moving the ball, it thinks it's moving anyway. Very weird. :shock:

But lightguns work again.

EDIT: Trackball works fine... but not on my Nomad. On the Nomad, it seems to act like it's always in Control mode, even when it's set to Sport mode (trackball needs to be in Sport mode - Control mode is what is making it constantly move, although I have no idea why or even what the difference in the two modes are).

Sik
Very interested
Posts: 880
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: Mega Mouse unused nibbles research

Post by Sik » Wed Jul 17, 2019 5:15 pm

I imagine Control mode is basically "emulate a D-pad"? Especially since the Master System controller calls it Control Pad (the term Direction Pad came with the Mega Drive). (EDIT: yeah, it toggles whether it acts like a normal controller or a trackball)
Stef wrote:
Wed Jul 17, 2019 10:13 am
I have to admit i don't know too much about that HV latching, i though it was "temporary", just the time you read out the HV value from the Int2 callback then the latch was released (probably by writing according register to VDP). Is that the case ?
Nope. Basically, the HV counter is frozen (from the 68000's viewpoint) and it's updated whenever TH goes from high to low (i.e. whenever IRQ2 would have to fire). The whole point of this mode is to make life easier when programming lightguns.
Sik is pronounced as "seek", not as "sick".

Post Reply