Category Archives: AutoHotKey

PhaseShift and Frets On Fire X Song Packs

127
Filed under Arcade, AutoHotKey, Frets On Fire, Games, Guitar, Stepmania

PhaseShift is an excellent freeware (not open source yet, as far as I can tell, but here’s hoping) version of the RockBand genre of games. It’s even more interesting in that it can interoperate with guitar controllers, game drum kits, vocals, keyboards, MIDI, and even step pads (for Dance Dance Revolution style games, all at the same time!).

Very cool stuff.

What’s even better is that it can read both Frets on Fire songs as well as Stepmania format songs.

Mostly.

There are a ton of great song packs available out on the web, and most that I’ve found work seamlessly with PhaseShift. However, I’ve run into a bunch that do not.

The problem appears to be with the NOTES.MID file (the file that contains all the midi notes that is used by the game to show the onscreen “notes”).

After some digging using a hex editor (my favorite right now is Tiny Hexer), I discovered that in all the cases that failed, the NOTES.MID file appears to contain extranous junk. In many cases, it was a string of keyboard key names, in others it was code snippets. I’m guessing that whatever MIDI editor was used to generate those MID files didn’t properly clear garbage out or compact memory.

At any rate, FoFix appears to ignore the extra junk but PhaseShift does not.

Enter EOF

EOF is a song editor for “fretting” songs for use with rhythm games like Frets On Fire and PhaseShift. The latest version even has specific features to take advantage of elements of PhaseShift that don’t exist in Frets On Fire.

I found that simply using FILE – IMPORT MIDI and importing the NOTES.MID file into EOF, then immediately SAVING the file (and clicking YES to the prompt of “The file hasn’t changed, Save Anyway?”), fixed the problem for every single song I tried it on.

It worked so good in fact, that I wrote up a simple script in AutoHotKey to just run through all the files in a directory and perform those magic steps on them

/*
Convert songs via EOF
*/


F12::
Reload
return


F11::
loop, 1 {
    ;match anywhere in title
    SetTitleMatchMode, 2
    IfWinExist \Songs\
    {
        WinActivate
    }
    else
    {
        msgbox No Window
        return
    }

    ;Copy full path name
    sleep 500
    SendPlay ^+C
    sleep 500
    SendPlay ^+C
    ;msgbox %clipboard%

    ;Over to EOF
    IfWinExist EOF -
    {
        WinActivate
    }
    else
    {
        msgbox No EOF
        return
    }


    sleep 500
    SendInput {F6}{F6}
    sleep 500
    SendInput %clipboard%{enter}
    sleep 1000
    Send ^s
    sleep 500
    Send ^s!FS
    sleep 200
    SendInput Y
    sleep 200
    SendInput Y


    ;Back to DirOpus
    IfWinExist \Songs\
    {
        WinActivate
    }
    else
    {
        return
    }

    sleep 500
    SendPlay {down}

}

Change the loop value from 1 to some count if you want to run it through more than one song at a time.

To explain:

The F12 key I’ve mapped to a reload just to make editing this script easier. It’s not necessary for actually running the script.

The F11 key hooks to the secret sauce.

I used the SEARCH feature in Directory Opus to list only the NOTES.MID files from all songs in all subdirectories of a folder I was targeting. If you don’t have DirOpus, you’ll need to recode the script to accommodate some other logic for getting the list of full pathnames to process.

The script starts by activating the DirOpus window and copying the full path to the selected NOTES.MID file.

Then it switches to EOF, (which needs to already be loaded), and performs the FILE – IMPORT function, pasting in the filename of NOTES.MID.

It then immediately does a FILE – SAVE (and supplies a few Y keypresses to answer the “save anyway” prompt.

And finally, it switches back to DirOpen and moves down to the next file.

It’s a hack to be sure. But it worked a treat for me.

Rock on!

Uniquely Identifying RawInput Devices in AutoHotKey

18
Filed under AutoHotKey, Hardware, MP3s

NOTE: My take on this has changed slightly, as a result of some feedback. See the end of this post and the "Better Alternate Solution” for details.

I recently completed restoration of an old 1930’s era console radio into a fully modern touch-screen mp3-playing networked jukebox, and have been putting the finishing touches on the loaded software configuration for a few weeks.

Jukebox Original CL Photo

WP_000576

Radio as we found it, stuffed at the back of a barn/storage area

After the conversion, that touchscreen you see automatically folds and the top lowers back down to it’s original position when not in use

There were 3 knobs on the original unit. The actual knobs were long gone, but the holes were still there and I wanted some old-school tactile controls for this thing, as well as the touchscreen.

A few ebay searches and junk drawers scavanges later, and I had 3 very serviceable knobs for the front. You can see them in the photo, the two large dial knobs and the one small brass knob on the center plate.

WP_000498

Now that that was taken care of, I had to determine

  1. What I wanted them to do
  2. How to make them actually do that

Believe it or not, the “what” has actually turned out to be harder than the “how”

All About the “How”

Realistically, the what doesn’t much matter from a technical standpoint. Controlling volume, track playback etc is pretty trivial stuff with most software these days. So I’ll focus on the “how”.

I’d used a macro application called AutoHotKey on several occasions, and, while it’s programming language is quirky to put it mildly, it does get the job done, particularly when the job consists of converting one type of computer input into another.

In my case, each of those knobs it connected, via a typical encoder wheel, to the inputs of a standard 3 button optical mouse with middle wheel. Yes, you heard that right, there are three mice lurking in that cabinet (a forth if you count the real mouse that I use when working on it).

The Three Blind Mice

If you’ve ever hooked up 2 or more mice to a Windows PC, you know that they all control the single cursor. There’s no clear way to tell one mouse’s input from the other. Windows does that intentionally because it generally makes sense.

However, underneath the covers, there’s an API that exposes all input devices uniquely, meaning you CAN actually tell whether one mouse or another is being moved, clicked, scrolled or what not. It’s called the “RawInput” API, and it’s been there ever since Windows XP (and possibly even earlier, though I’m not sure of that).

Unfortunately, the RawInput functions are not the easiest functions to deal with in the world. Lots of C-style structure parsing and pointer juggling.

AHKHID to the Rescue

Fortunately though, for AutoHotKey users, a user named “theGood” posted AHKHID.ahk, an AutoHotKey script of functions to make working with HID devices (Human Interface Devices) at the RawInput level relatively straightforward.

I’d been able to craft up a script to detect which of my mice were been wheeled and clicked and react accordingly, so things were good.

Until I unplugged the mouse I used for working on the jukebox, and the keyboard.

When I booted it back up, boom, nothing worked right.

An ID isn’t an ID

I had been using the function AHKHID_GetDevIndex, as in:

id := AHKHID_GetDevIndex(h)

in order to retrieve a device ID and I’d assumed that ID would consistently identify a device. And I’d assumed wrong. Unplugging my actual mouse and keyboard had caused the devices to get renumbered on reboot, a common issue with Windows applications.

A Nasty Solution

The AHKHID script includes a function called AHKHID_GetDevName() that retrieves a unique “device name”, but that “name” is huge, consisting of a number of segments of hex number, plus an additional entire GUID, something along these lines:

USB\VID_045E&PID_00DD&REV_0173&MI_00{745a17a0-74d3-11d0-b6fe-00a0c90f57da}

Obviously, this could be used for a key, but it’s a bit unwieldy.

So, to shorten the key name a bit and make it easier to work with, I came up with AHKHID_GetDevKey()

AHKHID_GetDevKey(i, IsHandle = false) {
    ;generate a unique name from the DevName (which is huge, and usually includes a useless GUID)
    devname := AHKHID_GetDevName(i, IsHandle)
    StringReplace, devname, devname, Hid#Vid_, , All
    StringReplace, devname, devname, USBVid_, , All
    StringReplace, devname, devname, KODAK, , All
    StringReplace, devname, devname, &Pid_, , All
    StringReplace, devname, devname, &MI_, , All
    StringReplace, devname, devname, #7&, , All
    StringReplace, devname, devname, #, , All
    StringReplace, devname, devname, &, , All
    StringReplace, devname, devname, \, , All
    StringReplace, devname, devname, ?, , All
    p := Instr(devname, "{")
    if p > 0
    {
        p := p - 1
        StringLeft, devname, devname, p
    }
    ;remove last 5 0's if that's what's there
    if SubStr(devname, -4) = "00000"
    {
        p := StrLen(devname) - 5
        StringLeft, devname, devname, p
    }
    StringUpper, devname, devname
    Return devname
}

The idea here is to essentially strip out all the characters that wouldn’t help to make the string any more unique anyway. It’s a tad brute-force, but it’s easy to understand and it works.

So that insane name could end up a relatively benign:

045E00DD017300

Which is a perfectly reasonable unique key in my book.

An Alternate Solution

After I’d put this together and gotten it in use, I realized a potentially even better solution: just calculate a CRC-32 for the full Device Name. It turns out another user has already built a CRC-32 algorithm in AHK script, so doing so would be trivial. Granted, you might still get collisions with a CRC, but it’s reasonably unlikely.

A Better Alternate Solution

Well, after posting this, I got a comment on the AutoHotKey forums that, essentially, was pointing out that the “VID_” and “PID_” strings that my routine removes, actually can have an impact on the uniqueness of the name. The poster also indicated that the GUID at the end of the name also aided in the uniqueness.

While neither of those two claims held true in my specific case (on the 3 machines I tested on), I don’t doubt them in the list.

Which got me to thinking if there’s a better solution.

And there is. Our old friend, the hash function.

In reality, the CRC-32 approach that I suggest above can certainly be considered a form of hash function, and a pretty good one at that.

But, if you’re really gunning for just about ironclad uniqueness, at 64 or 128 bit hash is what you need, and there’s a couple of implementations that already exist for AutoHotKey.

Grab one of those, run it against the GetDevName value, and convert to a string value and you have a relatively short and manageable, unique and consistent HID device ID.

Wrap Up

I love Visual Basic, and VB.net in particular, but AutoHotKey makes many tasks concerned with translating one type of input into another (converted joystick input to mouse input, or keyboard keystrokes, for instance) so easy, it just often doesn’t make sense to build a dedicated app for the purpose.

It’s definitely an application to key handy in your toolbox.