Fans of Rhythm Heaven (DS) know how lame it is to swipe the stylus across the touch screen. Pretty much every review, if they mentioned any flaws, cited the imprecision of the touch screen swiping as a low point.

I'm back, this time with a LUA script that works much better, has less lag, and has more comments and options. Supported inputs are:

Select (skip tutorials, hold while paused to quit a mini game)
Start (pause)
D-Pad (move a cursor around the touch screen)
L (slow down the cursor's movement speed)
A and/or X (touch the screen at the cursor's location; hold to keep touching the screen)
B (Flick)

Using this control method on my Xbox 360 wired controller, I've finished the first 6 games, and received "superb" rankings on 3 of them. I am just starting to play the game, so the input method cannot yet be blamed for my shortcomings.

In this early version, you have to manually flick with your mouse at the title screen of the game. I suggest just using save states so you don't have to do that each time you start the game.

--Suggested settings:
--DeSmuME_0.9.10_x86.exe
--lua51.dll in same folder (MD5 hash: bbcc1690fe636fa08c30504b511b4901 )
--"Install desmume 0.9.9 and then download lua51.dll and lua5.1.dll from the
--"LuaBinaries 5.1.4 -Release 2" package at http://luabinaries.sourceforge.net/download.html
--Rotation 270 degrees (so it looks normal)
--Magnification filter: Nearest 2x (for a double-size, pixel-perfect screen) or just "normal" (for 1x)
--Sound settings: Synchronous (Synch Method "N"), Interpolation: Cosine
--Start the script with tools->LUA scripting
--Tested on Right Handed mode only
--
--Normal Rhythm Heaven inputs:
--[Start Button] and [Touch Screen]
--Setting up our variables
--lowest value for the main swipe motion
f=f or 32
framecounter=framecounter or 0
--assorted values for the swipe
g=g or 0
i=i or 0
m=m or 0
selectheld=selectheld or 0
startpressed=startpressed or 0
showquittingtext=showquittingtext or 0
--x and y of the cursor
xx=xx or 96
yy=yy or 96
while true do
emu.frameadvance()
--framecounter3 is a timer used in the select to quit statements
framecounter3=framecounter3 or 0
framecounter3=framecounter3+1
if framecounter3 >=300 then
framecounter3=300
end
--gui.text(0,0, string.format(framecounter3))
--gui.text(0,0, string.format(framecounter))
--gui.text(20,0, string.format(g))
--gui.text(40,0, string.format(i))
--gui.text(60,0, string.format(m))
--gui.text(0,10, string.format(selectheld))
--gui.text(0,0, string.format(startpressed))
--gui.text(0,20, string.format(xx))
--gui.text(0,30, string.format(yy))
--Drawing a cursor for d-pad stylus control.
if drawcursor==1 then
--Bigger box
boxsizeconstant=4
gui.box(xx-boxsizeconstant, yy-boxsizeconstant, xx+boxsizeconstant, yy+boxsizeconstant, {r = 0x255, g = 0x255, b = 0x255, a = 0x75}, {r = 0x255, g = 0x255, b = 0x255, a = 0x75})
--Crosshair
gui.line(xx-boxsizeconstant, yy, xx+boxsizeconstant, yy, {r = 0x000, g = 0x000, b = 0x000, a = 0x225})
gui.line(xx, yy-boxsizeconstant, xx, yy+boxsizeconstant, {r = 0x000, g = 0x000, b = 0x000, a = 0x225})
--Smaller box
gui.box(xx-(boxsizeconstant/2), yy-(boxsizeconstant/2), xx+(boxsizeconstant/2), yy+(boxsizeconstant/2), {r = 0x99, g = 0x169, b = 0x255, a = 0x225}, {r = 0x99, g = 0x169, b = 0x255, a = 0x225})
end
--setting our screen borders for the dpad movement. Nothing happens in the outer edges so we leave them off limits unless the L button (slower movement) is held.
border=7
xmin=border
xmax=256-border
ymin=border
ymax=192-border
--dpadmovespeed determines how many pixels to move in one frame with the d-pad
--slow down dpad speed while L button is held
if joypad.get().L then
dpadmovespeed=1
drawcursor=1
framecounter3=0
xmin=0
xmax=256
ymin=0
ymax=192
else
dpadmovespeed=5
end
if joypad.get().up then
xx=xx+dpadmovespeed
drawcursor=1
framecounter3=0
if xx>=xmax then
xx=xmax
end
end
if joypad.get().down then
xx=xx-dpadmovespeed
drawcursor=1
framecounter3=0
if xx<=xmin then
xx=xmin
end
end
if joypad.get().left then
yy=yy-dpadmovespeed
drawcursor=1
framecounter3=0
if yy<=ymin then
yy=ymin
end
end
if joypad.get().right then
yy=yy+dpadmovespeed
drawcursor=1
framecounter3=0
if yy>=ymax then
yy=ymax
end
end
--While held, touch the screen and continue touching. Two buttons to allow you to alternate buttons during fast games.
if joypad.get().A then
stylus.set{x=xx, y=yy, touch=true}
framecounter3=0
end
if joypad.get().X then
stylus.set{x=xx, y=yy, touch=true}
framecounter3=0
end
--Press to hit the skip button and skip practice.
if joypad.get().select then
if startpressed==0 then
stylus.set{x=242, y=30, touch=true}
joypad.set{select=false}
end
end
--Press start then hold select for 3/4 second (45 frames) to quit the current game. (In games with a pause menu that have a quit button.)
--Holding select when the pause menu is not open will send one touch event at where the "quit" button would be. It only does this once, so there are minimal potential for errors.
--This was very challenging to get working, so please quit a lot of games!
if joypad.get().start then
startpressed=1
end
if startpressed==1 then
if selectheld>=45 then
stylus.set{x=130, y=142, touch=true}
joypad.set{select=false}
selectheld=0
joypad.set{start=false}
startpressed=0
end
if joypad.get().select then
showguitext=1
selectheld=selectheld+1
framecounter3=0
else
selectheld=0
end
end
if showguitext==1 then
gui.text(0,0, string.format("Quitting... "))
gui.text(70,0, string.format(selectheld))
gui.text(83,0, string.format("/45"))
end
--Clean up GUI text and cursor after 1 second (60 frames)
if framecounter3>=60 then
showguitext=0
drawcursor=0
end
--startpressed=0
--end
--Flick controls. Note that the main menu of Rhythm Heaven requires a more vigorous (3 frames?) flick than the rest of the game (2 frames). This is set up for as little lag as possible, so it doesn't work on the main menu.
if joypad.get().B then
--if B is being held, ignore inputs. Script should detect a single B button press (or hold), do one single flick, then wait for B to stop being held. If, after the flick, B stops being held, script allows another flick.
g=1
i=0
framecounter2=0
end
if g==1 then
joypad.set{B=false}
joypad.set{A=false}
joypad.set{Y=false}
if framecounter>=2 then
stylus.set{x=f, y=96, touch=false}
f=32
--no clue what I am doing - I guess setting up variables to kill the original variables but I don't know if this is needed. I think I was having problems with
--the script exiting certain "if then" statements because within them I was cancelling the statements that "if" required.
--g=0
i=1
--framecounter=0
framecounter2=1
end
if f>=256 then
f=f
f=32
end
if framecounter>=0 then
stylus.set{x=f, y=96, touch=true}
framecounter=framecounter+1
f=f+63
end
end
if i==1 then
g=0
end
if framecounter2==1 then
framecounter=0
end
end