Open ghost opened 3 years ago
Heya! So there are three things going on here:
window.process_input
will override the keymap with the user input for the SDL window, so you need to not call it if you want to do input manually.Here's the code that's working for me:
from desmume.emulator import DeSmuME
from desmume.controls import Keys
emu = DeSmuME()
emu.open('/home/marco/dev/skytemple/skytemple/skyworkcopy.nds')
window = emu.create_sdl_window()
frame = 0
emu.input.keypad_rm_key(Keys.KEY_A)
while not window.has_quit():
frame += 1
if frame == 1660:
emu.input.keypad_add_key(Keys.KEY_A)
print("Press A")
if frame == 1662:
emu.input.keypad_rm_key(Keys.KEY_A)
emu.cycle()
window.draw()
Hello again!
Thank you very much, the last part with the window.process_input
was my issue (and maybe the pre-pressed A also), but I had to modify your code a bit since it seems that window.process_input()
is necessary. Without it, the touch_set_pos crashes the game (black screen). Also, with or without the touch_set_pos, the "quit" (i.e. the X) fails to work if you don't include window.process_input()
. Therefore, I included it after my touch screen interactions, but before my keyboard interactions, every frame.
Also, I verified and it seems that it works with or without keymask. It makes sense that this would work when I was trying headless since I was removing the window.process_input()
.
Here is what I ended up using as a test:
from desmume.emulator import DeSmuME
from desmume.controls import keymask, Keys
emu = DeSmuME()
emu.open('D:\\Dropbox\\Speed Run\\DeSmuME 9.11\\Roms\\ROMs\\NA\\0561 - Harvest Moon DS (U)(Legacy).nds')
window = emu.create_sdl_window()
frame = 0
emu.input.keypad_rm_key(Keys.KEY_A)
while not window.has_quit():
frame += 1
if frame == 405:
emu.input.touch_set_pos(100, 100)
if frame == 406:
emu.input.touch_release()
if frame == 405+150:
emu.input.touch_set_pos(100, 100)
if frame == 406+150:
emu.input.touch_release()
window.process_input()
if frame == 1660:
emu.input.keypad_add_key(Keys.KEY_A)
print("Press A")
if frame == 1662:
emu.input.keypad_rm_key(Keys.KEY_A)
emu.cycle()
window.draw()
I personally can't get the custom key processing working correctly. Here's a simplified extract of my program using it (which is intended to fully handle keypress processing, not just arbitrarily enter keys):
from desmume.emulator import DeSmuME
from desmume.controls import keymask, Keys
from blessed import Terminal # Using blessed for rendering as well as keypress handling
term = Terminal()
emu = DeSmuME()
emu.open("/home/minabsapi/Lab/Projects/0008/files/basis/ROMs + saves/POKEDUN_SORA_C2SP01_00.nds") # Replace with your ROM path
emu_win = emu.create_sdl_window()
frame = 0
running = True
halt = False
emu_keys_map = {
"KEY_UP" : Keys.KEY_UP,
"KEY_DOWN" : Keys.KEY_DOWN,
"KEY_LEFT" : Keys.KEY_LEFT,
"KEY_RIGHT" : Keys.KEY_RIGHT,
"8" : Keys.KEY_X,
"4" : Keys.KEY_Y,
"2" : Keys.KEY_B,
"6" : Keys.KEY_A,
"7" : Keys.KEY_L,
"9" : Keys.KEY_R,
"1" : Keys.KEY_START,
"3" : Keys.KEY_SELECT,
}
emu_pressed_key = Keys.KEY_NONE
emu_pressed_key_frame = 0
# ...
got_key = lambda key: key.name if key.is_sequence else key
def clear():
global term
print(term.clear + term.home)
# ...
# ...
# for x in emu_keys_map:
# emu.input.keypad_rm_key(emu_keys_map[x])
# ...
with term.cbreak():
while not halt:
# ...
key = term.inkey(timeout=0.0075)
if key:
if got_key(key) == 'KEY_ESCAPE':
clear()
print(
"""
Are you sure you want to exit?
y: yes
n: no
"""
)
key = term.inkey()
while got_key(key) not in ['y', 'n']:
key = term.inkey()
if got_key(key) == 'y':
halt = True
break
clear()
elif got_key(key) == '0': # For debugging purpose
emu.input.keypad_rm_key(Keys.NO_KEY_SET)
if running:
try:
emu_pressed_key = emu_keys_map[got_key(key)]
emu.input.keypad_add_key(emu_pressed_key)
emu_pressed_key_frame = frame
except KeyError:
pass
# ...
emu.cycle()
emu_win.draw()
frame += 1
if frame - emu_pressed_key_frame == 4:
emu.input.keypad_rm_key(emu_pressed_key)
Trying this on the Pokémon Mystery Dungeon: Explorers of Sky ROM, this configuration creates a buggy mess where
...
for x in emu_keys_map:
emu.input.keypad_rm_key(emu_keys_map[x])
...
emu.input.keypad_rm_key(Keys.NO_KEY_SET)
which doesn't even make sense. (Press 0 to try)
Oof, this is all very odd. I'll have to see when I find some time to investigate your issue.
Meanwhile I investigated myself and found what's wrong.
First,
The keymask command isn't actually required in this case, since the constant already contains the keymask value
Referring to the code (check full implementation):
https://github.com/SkyTemple/py-desmume/blob/1e347cbd0e4ea95257c430e1471982c437d16ead/desmume/controls.py#L46 https://github.com/SkyTemple/py-desmume/blob/1e347cbd0e4ea95257c430e1471982c437d16ead/desmume/controls.py#L106 https://github.com/SkyTemple/py-desmume/blob/1e347cbd0e4ea95257c430e1471982c437d16ead/desmume/emulator.py#L173
It isn't the case, the keymask
method is actually required, since the Keys
class acting as an enumeration doesn't hold the actual keypad mask value, but rather the index of the keypad variable bit to change counting from 1
This brings us to the actual problem: upon multiple testing and playing around keypad_update
I found out the odd behavior was because of the keymask
method giving an incorrect value because of a little mistake. The shifting was smart, but as you started your enumeration from 1 instead of 0 every keypad mask output got their value shifted, acting as the next key rather than the one intended. That's the reason why A wasn't working when I used it and worked without. Because coincidentally the A key value in your enum and the keypad mask are both 1.
Although I think the existence of keymask
should be reconsidered (hardcoding power of 2 in Keys
shouldn't hurt :p) I'll just commit a small fix on it so everything works again
Not all problems are fixed, though. For some reason I still need to call process_input()
(which basically effects in resetting the keypad) every iteration to avoid getting stuck. After some adaptations this is the only way I got everything working smoothly. An evil bringing some good, as that forces touchscreen support for me
When running the emulator in the window, I am not able to interact with it with the "keypad_add_key" and "keypad_rm_key", but the "touch_set_pos" seems to work as intended. When querying the keys (keypad_get()) it seems to be registering the "keypad_add_key" but the game does not seem to progress according to the keys I press. The script seems to work fine if it is headless (without the window it seems to register them) and it registers keys fine when pressing them on the keyboard during gameplay (in the window). Could you help?