You are not logged in.
Pages: 1
I've been sitting on this for a while(years) now and decided to clean it up a bit and post it. This script allows you to play Metroid Prime hunters with a controller with smooth camera movement.
Some small snippets(like subweapon switching) were borrowed from https://forums.desmume.org/viewtopic.php?id=10957 .
This may only work on the Windows version of DeSmuME, I'm not sure.
This requires the US ROM with a SHA1 hash of 90164D1AC127EE5F9815EA4AE7DE798C7B5FC629
Clear any controller input you may have set up in DeSmuME before using.
By default it's set up for an Xbox style controller but the controls are easily customizable.
left stick - move
right stick - aim
left or right trigger - shoot/scan
bumpers - cycle subweapon forward/back
start - start
d-pad up(hold) - scan visor
d-pad down - morphball
d-pad left - presses back arrow on messages
d-pad right - presses forward arrow on messages
B - presses OK on messages
A - jump
X - morphball boost
Y - cycle weapon(beam/missile/subweapon)
select(hold) - virtual stylus
while virtual stylus is active
right stick - move the virtual stylus
right bumper - tap the screen
left bumper - toggle manual touchscreen input
The way aiming works is the center of the screen is continually pressed and the script injects stylus movement into the game's memory. If you need to manually use the touchscreen then use select+left bumper to toggle aiming on or off. That shouldn't be necessary with the existence of the virtual stylus, though.
Use with the U.S. version of the game.
joyid = 0 --change this if your preferred controller isn't being picked up
deadzone = 0.15 --Adjust analog stick deadzones
cooldown=0
weapon=0
subweapon=0
togglestylus=false
toggleaim=false
vcurx=128
vcury=96
key = {}
joy = {}
--Set the controls here
morphkey = "joy.down" --morph ball switch
visorkey = "joy.up" --scan visor switch(hold)
okkey = "joy.2" --ok button in messages
leftkey = "joy.left" --left arrow in messages
rightkey = "joy.right" --right arrow in messages
weaponkey = "joy.4" --weapon cycle
subweaponkey1 = "joy.5" --subweapon cycle back
subweaponkey2 = "joy.6" --subweapon cycle forward
leftstickx = "joy.x" --must be analog stick axis
leftsticky = "joy.y" --must be analog stick axis
rightstickx = "joy.u" --must be analog stick axis
rightsticky = "joy.r" --must be analog stick axis
shootkey = "joy.z" --may be either analog axis or button
boostkey = "joy.3" --morph ball boost
vstyluskey = "joy.7" --virtual stylus(hold)
jumpkey = "joy.1" --jump
startkey = "joy.8" --start
--https://www.lua.org/pil/14.1.html
function getfield (f)
local v = _G -- start with the table of globals
for w in string.gfind(f, "[%w_]+") do
v = v[w]
end
return v
end
while true do
joysend = {}
key=input.get()
joy = controller.get(joyid)
if getfield(vstyluskey) then
toggleaim = true --this exists to just delay the pressing of the screen when you release the virtual stylus key
if vcury>0 then
gui.drawbox(vcurx-1, vcury-1, vcurx+1, vcury+1, "#000000", "#FFFFFF")
else
gui.drawbox(vcurx-1, vcury, vcurx+1, vcury+1, "#FFFFFF") --workaround for vcury=0, as it would draw to the top screen
gui.pixel(vcurx, vcury, "#000000")
end
if getfield(subweaponkey2) then
stylus.set{x=vcurx, y=vcury, touch=true}
end
if getfield(subweaponkey1) and cooldown==0 then
togglestylus = not togglestylus
print('Touchscreen input allowed = ' .. tostring(togglestylus))
cooldown = 20
end
tmp = getfield(rightstickx)
if tmp and math.abs(tmp)>deadzone then
vcurx = vcurx + (tmp * 5)
end
tmp = getfield(rightsticky)
if tmp and math.abs(tmp)>deadzone then
vcury = vcury + (tmp * 5)
end
if vcurx<0 then vcurx=0 end
if vcurx>255 then vcurx=255 end
if vcury<0 then vcury=0 end
if vcury>191 then vcury=191 end
else
if getfield(morphkey) then --Morph
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=231, y=167, touch=true} emu.frameadvance() emu.frameadvance()
end
if getfield(visorkey) then --Visor
if cooldown == 0 then
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
end
cooldown = 10
stylus.set{x=128, y=173, touch=true}
end
if getfield(okkey) then --OK (in scans and messages)
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=128, y=142, touch=true} emu.frameadvance() emu.frameadvance()
end
if getfield(leftkey) then --Left arrow (in scans and messages)
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=71, y=141, touch=true} emu.frameadvance() emu.frameadvance()
end
if getfield(rightkey) then --Right arrow (in scans and messages)
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=185, y=141, touch=true} emu.frameadvance() emu.frameadvance()
end
if getfield(weaponkey) and cooldown==0 then --Switch weapon (beam->missile->subweapon->beam)
cooldown=20
weapon=(weapon+1)%3
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=85+40*weapon, y=32, touch=true} emu.frameadvance()
stylus.set{x=85+40*weapon, y=32, touch=true}
end
if (getfield(subweaponkey1) or getfield(subweaponkey2)) and cooldown==0 then --Switch subweapon (previous and next)
cooldown=20
weapon=2
if getfield(subweaponkey1) then subweapon=(subweapon-1)%6 end --previous
if getfield(subweaponkey2) then subweapon=(subweapon+1)%6 end --next
subX=93+25*subweapon subY=48+25*subweapon
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=232, y=34, touch=true} emu.frameadvance()
stylus.set{x=232, y=34, touch=true} emu.frameadvance()
stylus.set{x=subX, y=subY, touch=true} emu.frameadvance()
stylus.set{x=subX, y=subY, touch=true}
end
tmp = getfield(leftstickx)
if tmp and tmp < -deadzone then
joysend.left = true
elseif tmp and tmp > deadzone then
joysend.right = true
end
tmp = getfield(leftsticky)
if tmp and tmp < -deadzone then
joysend.up = true
elseif tmp and tmp > deadzone then
joysend.down = true
end
tmp = getfield(rightstickx)
if tmp and math.abs(tmp)>deadzone and togglestylus==false then
memory.writedword(0x020DE526, (tmp * 4))
toggleaim=false
end
tmp = getfield(rightsticky)
if tmp and math.abs(tmp)>deadzone and togglestylus==false then
memory.writedword(0x020DE52E, (tmp * 6))
toggleaim=false
end
if getfield(boostkey) then
joysend.R = true
end
tmp = getfield(shootkey)
if tmp then
if type(tmp) == "number" then
if math.abs(tmp) > deadzone then
joysend.L = true
end
elseif type(tmp) == "boolean" then
joysend.L = true
end
end
if getfield(jumpkey) then
joysend.B = true
end
if getfield(startkey) then
joysend.start = true
end
end
if cooldown>0 then
cooldown=cooldown-1
else
ball = memory.readbyte(0x020DA818) == 0x02 --Is this a good way of detecting morph ball status??
if ball==false and togglestylus==false and toggleaim==false then
stylus.set{x=128, y=96, touch=true} --Required for aiming
end
end
joypad.set(1,joysend)
emu.frameadvance()
end
video recorded while using this script: https://files.catbox.moe/o6r3r5.webm
Last edited by windwakr (2021-10-14 00:45:27)
Offline
Updated the script to include a "virtual stylus" for navigating stuff like your ship and the main menu. When holding select(on an xbox style controller) a virtual stylus will be displayed. It can be moved with the right stick and touch the screen with the right bumper. You can still toggle manual touchscreen input if needed with select + left bumper.
Last edited by windwakr (2021-04-02 01:47:21)
Offline
I'm actually new to adjusting scripts in DesMume and I'm a visual learner, so I was wondering if you could post of video of how to do this? (I'm sure you would get a lot of views on youtube as well considering no one has done this.)
I always wanted to play Metroid prime hunters but trying to use my right hand for my laptop's mouse and my left hand for the controller is a horrible gaming experience.
Thank you in advance for your time!
Offline
I'm actually new to adjusting scripts in DesMume and I'm a visual learner, so I was wondering if you could post of video of how to do this? (I'm sure you would get a lot of views on youtube as well considering no one has done this.)
I always wanted to play Metroid prime hunters but trying to use my right hand for my laptop's mouse and my left hand for the controller is a horrible gaming experience.Thank you in advance for your time!
What are you having trouble with?
To run Lua scripts you will need the correct dlls in the folder with your DeSmuME exe. A Lua setup guide copied from here:
Download the Lua DLL that matches your Desmume: - https://sourceforge.net/projects/luabin … s/Dynamic/
lua-5.1.5_Win32_dll14_lib.zip for x86 Desmume
lua-5.1.5_Win64_dll14_lib.zip for x86-64 DesmumeExtract lua5.1.dll from the .zip file to the same folder where your DeSmuME_0.9.11_x86.exe or DeSmuME_0.9.11_x64.exe is
Rename lua5.1.dll to lua51.dll
Copy the script from my post into a text file and rename the extension to ".lua". In DeSmuME once the game is running go to "Tools -> Lua Scripting -> New Lua Script Window...". In the new window that pops up hit browse and select the script you saved and it will start running.
If you want to adjust the controls then use this lua script to identify your controller and its buttons
dpad = {"up", "down", "left", "right"}
sticks = {"x", "y", "z", "r", "u", "v"}
function showControllers()
gui.box(0, 0, 256, 192, "#808080")
gui.box(0, -192, 256, 0, "#808080")
for i=0,15 do
cont = controller.get(i)
if type(next(cont)) ~= "nil" then
gui.text(0, (18*i)-143, i)
xoffs = 14
for ii=0,32 do
col = "#606060"
tmp = tostring(ii)
if cont[tmp] ~= nil then
if cont[tmp] == true then col = "#FF0000" end
gui.text(xoffs, (18*i)-143, tmp, col) --goes off screen if controller has more than ~20 buttons.
xoffs = xoffs + string.len(tmp)*6 + 2
end
end
xoffs = 14
for idx, name in ipairs(dpad) do
col = "#606060"
if cont[name] ~= nil then
if cont[name] == true then col = "#FF0000" end
gui.text(xoffs, (18*i)-143+9, name, col)
xoffs = xoffs + string.len(name)*6 + 4
end
end
for idx, name in ipairs(sticks) do
col = "#606060"
if cont[name] ~= nil then
if math.abs(cont[name]) > 0.25 then col = "#FF0000" end
gui.text(xoffs, (18*i)-143+9, name, col)
xoffs = xoffs + string.len(name)*6 + 2
end
end
end
end
end
gui.register(showControllers)
You should see output similar to this, but different depending on your controller and how many of them you have hooked up.
The white number on the left is the controller id. When you press a button it will turn red to help you identify which button corresponds to which number.
In the main script you can then adjust joyid and the controls with the values you find here.
Last edited by windwakr (2021-04-05 19:55:15)
Offline
Also, it looks like input in Lua was broken for the last month in DeSmuME builds, but is now fixed. If you get an error when trying to run one of the scripts then make sure you have an up-to-date build of the emulator.
Last edited by windwakr (2021-04-06 06:06:50)
Offline
I apologize heavily for resurrecting this post but I'm at my wits end. So far I've gotten everything to work by right analog stick aiming.
I use a PS5 controller and have managed to remap everything properly and even with the virtual stylus the right analog stick works perfectly. It's just when it comes to aiming in the game and looking around it just will not work. I even tried using DS4Windows and Steam to help treat it as an xbox controller but still no luck. I don't have any other country to test this with sadly.
I'm not really smart when it comes to scripting so I don't know what I'm supposed to do to fix this or if there is a fix. Again, everything is working fine with the buttons except that one thing, aiming/looking around. If anyone has an answer that would be appreciated.
Also I apologize if I violated a rule on necroing old posts. I didn't see the rule anywhere but I may have missed it.
Offline
What region game are you using? This was only tested on the US version. It has hardcoded memory addresses that it injects values at that probably won't work with other regions.
EDIT: Specifically the first release, not Rev 1. The working ROM has the SHA1 hash 90164D1AC127EE5F9815EA4AE7DE798C7B5FC629
Last edited by windwakr (2021-10-14 00:44:30)
Offline
Thank you for the response! Okay, so it is the US region but after struggling to figure it out it's apparently Rev 1. I assume that's the reason.
Since I know nothing about scripting or LUA there's not much I can do in this regard to figuring it out so I'll likely just have to try out the mouse and keyboard script.
Thank you again for your reply. I appreciate it.
Offline
This version of the script should work with US Rev 1. I have not extensively tested it, though.
joyid = 0 --change this if your preferred controller isn't being picked up
deadzone = 0.15 --Adjust analog stick deadzones
cooldown=0
weapon=0
subweapon=0
togglestylus=false
toggleaim=false
vcurx=128
vcury=96
key = {}
joy = {}
--Set the controls here
morphkey = "joy.down" --morph ball switch
visorkey = "joy.up" --scan visor switch(hold)
okkey = "joy.2" --ok button in messages
leftkey = "joy.left" --left arrow in messages
rightkey = "joy.right" --right arrow in messages
weaponkey = "joy.4" --weapon cycle
subweaponkey1 = "joy.5" --subweapon cycle back
subweaponkey2 = "joy.6" --subweapon cycle forward
leftstickx = "joy.x" --must be analog stick axis
leftsticky = "joy.y" --must be analog stick axis
rightstickx = "joy.u" --must be analog stick axis
rightsticky = "joy.r" --must be analog stick axis
shootkey = "joy.z" --may be either analog axis or button
boostkey = "joy.3" --morph ball boost
vstyluskey = "joy.7" --virtual stylus(hold)
jumpkey = "joy.1" --jump
startkey = "joy.8" --start
--https://www.lua.org/pil/14.1.html
function getfield (f)
local v = _G -- start with the table of globals
for w in string.gfind(f, "[%w_]+") do
v = v[w]
end
return v
end
while true do
joysend = {}
key=input.get()
joy = controller.get(joyid)
if getfield(vstyluskey) then
toggleaim = true --this exists to just delay the pressing of the screen when you release the virtual stylus key
if vcury>0 then
gui.drawbox(vcurx-1, vcury-1, vcurx+1, vcury+1, "#000000", "#FFFFFF")
else
gui.drawbox(vcurx-1, vcury, vcurx+1, vcury+1, "#FFFFFF") --workaround for vcury=0, as it would draw to the top screen
gui.pixel(vcurx, vcury, "#000000")
end
if getfield(subweaponkey2) then
stylus.set{x=vcurx, y=vcury, touch=true}
end
if getfield(subweaponkey1) and cooldown==0 then
togglestylus = not togglestylus
print('Touchscreen input allowed = ' .. tostring(togglestylus))
cooldown = 20
end
tmp = getfield(rightstickx)
if tmp and math.abs(tmp)>deadzone then
vcurx = vcurx + (tmp * 5)
end
tmp = getfield(rightsticky)
if tmp and math.abs(tmp)>deadzone then
vcury = vcury + (tmp * 5)
end
if vcurx<0 then vcurx=0 end
if vcurx>255 then vcurx=255 end
if vcury<0 then vcury=0 end
if vcury>191 then vcury=191 end
else
if getfield(morphkey) then --Morph
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=231, y=167, touch=true} emu.frameadvance() emu.frameadvance()
end
if getfield(visorkey) then --Visor
if cooldown == 0 then
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
end
cooldown = 10
stylus.set{x=128, y=173, touch=true}
end
if getfield(okkey) then --OK (in scans and messages)
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=128, y=142, touch=true} emu.frameadvance() emu.frameadvance()
end
if getfield(leftkey) then --Left arrow (in scans and messages)
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=71, y=141, touch=true} emu.frameadvance() emu.frameadvance()
end
if getfield(rightkey) then --Right arrow (in scans and messages)
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=185, y=141, touch=true} emu.frameadvance() emu.frameadvance()
end
if getfield(weaponkey) and cooldown==0 then --Switch weapon (beam->missile->subweapon->beam)
cooldown=20
weapon=(weapon+1)%3
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=85+40*weapon, y=32, touch=true} emu.frameadvance()
stylus.set{x=85+40*weapon, y=32, touch=true}
end
if (getfield(subweaponkey1) or getfield(subweaponkey2)) and cooldown==0 then --Switch subweapon (previous and next)
cooldown=20
weapon=2
if getfield(subweaponkey1) then subweapon=(subweapon-1)%6 end --previous
if getfield(subweaponkey2) then subweapon=(subweapon+1)%6 end --next
subX=93+25*subweapon subY=48+25*subweapon
stylus.set{touch=false} emu.frameadvance() emu.frameadvance()
stylus.set{x=232, y=34, touch=true} emu.frameadvance()
stylus.set{x=232, y=34, touch=true} emu.frameadvance()
stylus.set{x=subX, y=subY, touch=true} emu.frameadvance()
stylus.set{x=subX, y=subY, touch=true}
end
tmp = getfield(leftstickx)
if tmp and tmp < -deadzone then
joysend.left = true
elseif tmp and tmp > deadzone then
joysend.right = true
end
tmp = getfield(leftsticky)
if tmp and tmp < -deadzone then
joysend.up = true
elseif tmp and tmp > deadzone then
joysend.down = true
end
tmp = getfield(rightstickx)
if tmp and math.abs(tmp)>deadzone and togglestylus==false then
memory.writedword(0x020DEDA6, (tmp * 4))
toggleaim=false
end
tmp = getfield(rightsticky)
if tmp and math.abs(tmp)>deadzone and togglestylus==false then
memory.writedword(0x020DEDAE, (tmp * 6))
toggleaim=false
end
if getfield(boostkey) then
joysend.R = true
end
tmp = getfield(shootkey)
if tmp then
if type(tmp) == "number" then
if math.abs(tmp) > deadzone then
joysend.L = true
end
elseif type(tmp) == "boolean" then
joysend.L = true
end
end
if getfield(jumpkey) then
joysend.B = true
end
if getfield(startkey) then
joysend.start = true
end
end
if cooldown>0 then
cooldown=cooldown-1
else
ball = memory.readbyte(0x020DB098) == 0x02 --Is this a good way of detecting morph ball status??
if ball==false and togglestylus==false and toggleaim==false then
stylus.set{x=128, y=96, touch=true} --Required for aiming
end
end
joypad.set(1,joysend)
emu.frameadvance()
end
Offline
That seems to work. Thank you so much. You really didn't need to go through this extra effort but I sincerely appreciate that you did.
Offline
we should fix whatever problems make it hard to use lua in desmume (dont you have to scrounge up the dll or something) and then include some good scripts in the repository as part of a perks pack for next time we make a release (whenever that may be...)
Offline
Hi....The hardest parts are tracking down the API for the emulator, and observing a bundle to peruse regulator input. When you have those two things, utilizing them is really clear, and I (or another person on these sheets) ought to have the option to help you through it.
DeSmuME's API should be distributed some place... if not it'd be totally unusable. Like I said... if you ask on that emu's discussions, somebody ought to have the option to guide you to something you can utilize.
With respect to the bundle, that may be trickier... as I'm not even certain if one exists. What you need is an overall Lua bundle for getting regulator input - it doesn't need to be explicitly for DeSmuME. What's more, truth be told, there most likely isn't something explicitly for DeSmuME.
Offline
Somebody please help me, I can't for the life of me get this working, as soon as I start the lua script the controls go crazy, the camera starts spinning in circles and I can't do anything. I'm using the latest desmume and the dll files are there, i'm using DS4 Windows and a ps4 controller which is recognized as a xbox 360 controller. I'm really not sure what im doing wrong and I have honestly spent most of this day looking into this to no avail. Please help
Offline
Somebody please help me, I can't for the life of me get this working, as soon as I start the lua script the controls go crazy, the camera starts spinning in circles and I can't do anything. I'm using the latest desmume and the dll files are there, i'm using DS4 Windows and a ps4 controller which is recognized as a xbox 360 controller. I'm really not sure what im doing wrong and I have honestly spent most of this day looking into this to no avail. Please help
Try adjusting the joyid number at the top of the script and see if that helps. It accepts values 0 to 15.
Last edited by windwakr (2021-12-29 18:54:58)
Offline
Sorry for the necromancy, but I just found this and it's awesome!
Is there a way to get the camera controls to work with a mouse? I would love to play this with a mouse and keyboard as well.
Offline
This is really awesome! Just tested today and confirm it worked just fine. Much better than playing with the original stylus or the non-sensitive DPAD mode.
It's also mentioning there are lots of good FPS games on DS that rely upon stylus for aiming, such as Dementium, Moon, four Call of Duty games, etc. Having these games working with controllers by this same approach would be great. Might check the possibility of porting this script to these games later (might need to pass through Lua's learning curve).
Oh, a feedback from my end: The Lua script didn't work when I tried using the latest stable version v0.9.11. I got both x64 versions of Desmume and Lua DLL, but when trying to run the Lua script, I kept getting the following error:
mph.lua:46: attempt to index global 'controller' (a nil value)
script stopped.
Looks like it's having trouble detecting my controllers, even though I have a single xbox360 controller plugged in. The same error also occurred with the Desmume x432r version with HD support, and makes sense since it's based on older versions of the emulator.
My solution for this problem was: Instead of getting the v0.9.11 stable version (which is mentioned to have some problems), I got the latest build from this link, as mentioned in the Downloads section. With that version, my controllers were detected properly, and I managed to play the game with it.
Hope it helps.
Last edited by Solid One (2022-04-04 01:38:08)
Offline
I'm a first time poster and kind of a moron when it comes to these things but I followed the instructions to the letter and only get this output:
...n\Desktop\OG NDS\DeSmuME v.0.9.11\huntersControl.lua:46: attempt to index global 'controller' (a nil value) script stopped.
The lua51.dll is correct, I'm using the latest version of x64 DeSmuME, I tried other games and other scripts (such as a free camera script) but LUA scrips just won't run for me at all. I know there's probably a very simple and dumb solution for what I'm experiencing if anyone could point it out for me?
Thanks
Edit: just read the above post
Last edited by eeMcCutcheon (2022-05-01 00:08:19)
Offline
I realize this is necroposting, however this thread is the first one that pops up on search results when it comes to this subject. I've created a script with some custom libraries that add some solid keyboard and mouse controls to the game. I figured I'd share it here since this is likely where people will find it and if anybody else down the line wants to try out the game with keyboard and mouse controls, this just might be the first publicly posted way.
Offline
Pages: 1