Timecraft / retro-games

A to-be elementary OS app for running libretro cores
GNU General Public License v3.0
3 stars 1 forks source link

Get input working #1

Closed Timecraft closed 4 years ago

Timecraft commented 4 years ago

Currently input is not working. I have contacted someone working on retro-gtk to see if they can help me figure out my stupidity

Timecraft commented 4 years ago

According to the person who works on retro-gtk, these lines can be removed

Timecraft commented 4 years ago

They also suggested that we should try to move the core's boot function to AFTER we set up controls

Timecraft commented 4 years ago

The lines were removed and the core boot function was moved to after setting up the controls. No avail

alice-mkh commented 4 years ago
public class Timecraft.RetroGame.View : GLib.Object {

    public Retro.CoreView game_view;
    public Retro.MainLoop main_loop;

    public static View? instance;

    public View (Retro.Core core) {
        game_view = new Retro.CoreView ();

        game_view.set_core (core);

        MainWindow.instance.add (game_view);

        var key_joypad_mapping = new Retro.KeyJoypadMapping ();
        var key_map = new GLib.HashTable<Retro.JoypadId, uint16> (null, null);

        // Keycodes come from input-event-codes.h + 8 because that's what GDK does
        // Normally you allow user to remap keys, so you get this value from GDK, but not here
        // Agree it sucks and we should do something about it
        key_map.insert (Retro.JoypadId.A,       45 + 8);
        key_map.insert (Retro.JoypadId.B,       44 + 8);
        key_map.insert (Retro.JoypadId.Y,       30 + 8);
        key_map.insert (Retro.JoypadId.X,       31 + 8);
        key_map.insert (Retro.JoypadId.UP,      103 + 8);
        key_map.insert (Retro.JoypadId.DOWN,    108 + 8);
        key_map.insert (Retro.JoypadId.LEFT,    105 + 8);
        key_map.insert (Retro.JoypadId.RIGHT,   106 + 8);
        key_map.insert (Retro.JoypadId.START,   28 + 8);
        key_map.insert (Retro.JoypadId.SELECT,  54 + 8);

        key_map.foreach ( (joypad, keyboard) => {
            key_joypad_mapping.set_button_key (joypad, keyboard);
        });

        game_view.set_key_joypad_mapping (key_joypad_mapping);

        game_view.set_as_default_controller (core);

        // This keyboard input is different from Retro.ControllerType.KEYBOARD, you mostly
        // need it for home computer platforms. Yay Libretro having multiple APIs for things
        core.set_keyboard (game_view);

        // This is needed so that you only control the first player with joypad, and not all
        // at once. For other players assign the actual gamepads. In Games we use keyboard
        // for the last one (e.g. if you have 2 gamepads in a 4-player game, players 1 and 2
        // will use gamepads, player 3 will use keyboard, player 4 will just stand there)
        core.set_default_controller (Retro.ControllerType.JOYPAD, null);
        var core_view_joypad = game_view.as_controller (Retro.ControllerType.JOYPAD);
        core.set_controller (0, core_view_joypad);

        // You have to have save dir and system dir set to something.
        // Save directory is where the core saves (not all cores use saveram, a lot
        // just write a file into save directory), so you gotta have it
        core.save_directory = ".";

        // This is where firmware is. Once again, should be set to something meaningful,
        // e.g. it matters for Nestopia UE core.
        core.system_directory = ".";

        try {
            core.boot ();
        }
        catch (Error e) {
            error ("%s", e.message);
        }

        // This you of course do after you boot, can't start the game before it booted
        // Though tbh in 0.18 it might work, but that's still not something you should do
        main_loop = new Retro.MainLoop (core);
        main_loop.start ();

        Headerbar.instance.remove_back_button ();

        MainWindow.instance.show_all ();

        instance = this;
    }
}

Here's your view.vala, fixed and with some explanations. :)

Timecraft commented 4 years ago

Holy crap, thank you for taking your precious time to do this!

I believe I understand now, quite a bit of set up that I neglected to do, assuming it would be obvious to the core (hey core, just put the save files where the game is!) and not understanding that some cores have... quirks...

Didn’t realize you had to initialize the MainLoop after booting the core

Again, thank you so very much!

alice-mkh commented 4 years ago

You can maybe do it before, but e.g. in 1.0 you won't be able to do that (well, I removed RetroMainLoop completely, but you can imagine retro_core_run() won't be able to tell the remote runner process to start the core if the process does not exist yet :), and it's created in boot())

Cores have indeed a lot of quirks :( The most fun part will be when you add savestates. Some cores (MAME and ParaLLEl N64 in particular) fail to restore the state unless you run()/iteration() once before you load. 1.0 will do it implicitly, but 0.18 won't because stable API etc.

There's also content dir, DOSBox needs it, but that core sucks in general (incl. in RetroArch) and I've never been able to get it fully working.

Feel free to ask or use Games as a reference if you hit other problems :)

alice-mkh commented 4 years ago

Also feel free to open issues in https://gitlab.gnome.org/GNOME/retro-gtk/issues if you feel the docs are unclear. They might very well be.

Timecraft commented 4 years ago

The “not remaking keys” thing is kind of a temporary measure too, just so I have something working right now

alice-mkh commented 4 years ago

You could just not set anything, or do new Retro.KeyJoypadMapping.default () :) It also maps L, R (, 2, 3) that you forgot.

Timecraft commented 4 years ago

Also feel free to open issues in https://gitlab.gnome.org/GNOME/retro-gtk/issues if you feel the docs are unclear. They might very well be.

If retro-Gtk-1 is going to be an API break, perhaps it would be better to wait for the API to become more stable before publishing an issue on how the docs are

alice-mkh commented 4 years ago

Well, 0.18 might be unclear too. These kinds of things are hard to notice when you develop both a library and an app using it so there might very well be parts that are "obvious" to me and Adrien, but that really aren't.

Timecraft commented 4 years ago

You could just not set anything, or do new Retro.KeyJoypadMapping.default () :) It also maps L, R (, 2, 3) that you forgot.

What are the default controls, then? As for L/R 2 and L/R 3, again, temporary measure. The game I was testing with was a GameBoy Advance game, which doesn’t have to worry about that. I’ll have to get started immediately on remappable controls so that this issue can be more easily rectified (hopefully 😬)

alice-mkh commented 4 years ago

GBA has L/R ;)

Defaults: WASD for XYBA, Q/E for L/R, Z/C for L2/R2, 1/3 for L3/R3, arrows for dpad, Enter for Start, Backspace for Select.

Edit: and of course it's not documented. Bingo!

Screenshot from 2020-02-20 17-37-58

Timecraft commented 4 years ago

GBA has L/R ;)

L/R 1, unless I’m mistaken in what those are supposed to be. GBA doesn’t have L/R 2 (triggers) or L/R 3 (press down on the stick)

alice-mkh commented 4 years ago

Right. But your mapping doesn't have L/R 1 either.

Timecraft commented 4 years ago

A lot of this could also be my fault for not looking super closely at the docs. I was mostly trying to use the Vapi and assuming what was happening by the function names. Poor coding practice on my part!

Timecraft commented 4 years ago

Right. But your mapping doesn't have L/R 1 either.

Ah **** 😂

How did I not notice!

alice-mkh commented 4 years ago

I wouldn't say that's a poor coding practice really, ideally names are self-documenting. :)

(I would say making every object a singleton is a poor practice though ;)

Timecraft commented 4 years ago

Ideally, I shouldn’t need any of those objects more than once, hence singleton

Timecraft commented 4 years ago

And, unless i’m mistaken, if I want to access a specific instance of the object that has already been created, I need to have an instance of it. I am fairly new/naive when it comes to programming

alice-mkh commented 4 years ago

Ideally, I shouldn’t need any of those objects more than once, hence singleton

As soon as you want e.g. a second window, all that is thrown out the window. :)

You need an instance of course. You pass that instance via function arguments, properties etc. OOP is all about that :)

Timecraft commented 4 years ago

You pass that instance via function arguments, properties etc.

Fair. I’ll work on removing singletons from this app and my other app that is current

Timecraft commented 4 years ago

Can confirm that this issue is fixed. I can't stress enough how much I thank you!

alice-mkh commented 4 years ago

Eh, you've messed up indentation in that file :)

Timecraft commented 4 years ago

My “spam the down arrow and tab key” technique didn’t work D: Copy/Paste from GitHub is kinda weird. Doesn’t preserve indentation, so you have to add that in manually

alice-mkh commented 4 years ago

Can't you select everything and press tab once? IDK if that works in your editor, but it's a common thing.

Timecraft commented 4 years ago

I don’t believe so. I’m using elementary’s Code editor. I’ll have to try that and open an issue if that doesn’t work

Timecraft commented 4 years ago

Well, you learn something new every day (or in my case, about 20 thousand things in one day xD). elementary Code does in fact have the ability to do that

alice-mkh commented 4 years ago

I was pretty sure it does that, as gedit and GNOME Builder do it and they all use GtkSourceView. Though wasn't 100% you use Code, so asked. Similarly, shift+tab unindents for one level.

Timecraft commented 4 years ago

I did find something interesting in retro-gtk, and it's probably not supposed to be happening

Timecraft commented 4 years ago

Inputs are still a bit buggy for some reason. I can press enter/return (equivalent to start) on the main screen and get to the save file screen, but from there I can only press X (B) and go back to the title screen. Odd.

Timecraft commented 4 years ago

Ok, so the issues with the input seems to be directly related to this issue on GitLab. This is what I get for only testing with one core

Timecraft commented 4 years ago

This is still somewhat of an issue. #4 has some updates on this. In essence, controlling via the keyboard works great, but controlling via an actual controller is a question. If I pass it the Retro.Controller subclass RetroGamepad, it "works". It accepts the input, but the controls are not customized; on my controller, the right stick button (R3) ends up being START. This is not ideal nor expected. If I just try to make a Retro.KeyJoypadMapping, pass that back to the MainWindow and set the CoreView to use that as its mapping, it does not have any input.

alice-mkh commented 4 years ago

Retro.KeyJoypadMapping is for keyboard. For gamepads mappings are handled by libmanette.