Code Monkey home page Code Monkey logo

Comments (3)

Kenix3 avatar Kenix3 commented on July 24, 2024

I'm not fundamentally against the idea of an action oriented system instead of mapping to N64 buttons. I have some issues with it that would need to be worked out to make a change like this.

The first is that I'm not totally sure I see the conceptual value for the kinds of projects LUS is meant to support, outside of one. What I mean by that is everyone knows these are N64 games and are used to an emulator-like approach to bind controls. In other words, people are already used to mapping physical to virtual N64 buttons. There is one project which this assumption is a lot weaker on. Plus we are not an emulator. Really looking to discuss this point more than anything.

The actual problem is that an action system is a fundamental change to how the game interacts with LUS. It no longer calls a libultra function and gets back libultra data. You now need to query the state of an action instead of a ContPad. I think this needs more baking time before it's ready. If you're not suggesting to remove the old system, but instead treat an action as a bit flag for which virtual buttons are pressed, we are getting closer, but it still needs thought on how it would interact where the buttons are the bits. I'm other words, how would a port out of the box that doesn't want to deal with this complexity query data? The systems need to support both. How does that new port transition?

This would also mean we no longer need to change the controller headers, which would be a good thing. I don't think there's very many other places, maybe 2 or 3, where we modify headers. I'd be nice to take a look and see if we could theoretically reset them and allow games to provide their own headers.

from libultraship.

briaguya-ai avatar briaguya-ai commented on July 24, 2024

everyone knows these are N64 games and are used to an emulator-like approach to bind controls.

however, we already rely heavily on workarounds in SoH to provide context specific control customization. a specific example from SoH is playing the ocarina.

from a player perspective: a player must map their physical controller in one menu, then edit settings in another menu to add custom ocarina playback controls (which, due to the nature of n64 controller based mapping, is based on n64 buttons)

from an implementation perspective: 10 cvars are needed to provide dpad, right stick, and custom ocarina controls
in func_800ED458 we have this:

bool customControls = CVarGetInteger("gCustomOcarinaControls", 0);
bool dpad = CVarGetInteger("gDpadOcarina", 0);
bool rStick = CVarGetInteger("gRStickOcarina", 0);

and then this:

Audio_OcaUpdateBtnMap(customControls, dpad, rStick);

which calls into this:

// Function originally not called, so repurposing for control mapping
void Audio_OcaUpdateBtnMap(bool customControls, bool dpad, bool rStick) {
    if (customControls) {
        sOcarinaD5BtnMap = CVarGetInteger("gOcarinaD5BtnMap", BTN_CUP);
        sOcarinaB4BtnMap = CVarGetInteger("gOcarinaB4BtnMap", BTN_CLEFT);
        sOcarinaA4BtnMap = CVarGetInteger("gOcarinaA4BtnMap", BTN_CRIGHT);
        sOcarinaF4BtnMap = CVarGetInteger("gOcarinaF4BtnMap", BTN_CDOWN);
        sOcarinaD4BtnMap = CVarGetInteger("gOcarinaD4BtnMap", BTN_A);
    } else {
        sOcarinaD5BtnMap = BTN_CUP;
        sOcarinaB4BtnMap = BTN_CLEFT;
        sOcarinaA4BtnMap = BTN_CRIGHT;
        sOcarinaF4BtnMap = BTN_CDOWN;
        sOcarinaD4BtnMap = BTN_A;
    }

    if (dpad) {
        sOcarinaD5BtnMap |= BTN_DUP;
        sOcarinaB4BtnMap |= BTN_DLEFT;
        sOcarinaA4BtnMap |= BTN_DRIGHT;
        sOcarinaF4BtnMap |= BTN_DDOWN;
    }

    if (rStick) {
        sOcarinaD5BtnMap |= RSTICK_UP;
        sOcarinaB4BtnMap |= RSTICK_LEFT;
        sOcarinaA4BtnMap |= RSTICK_RIGHT;
        sOcarinaF4BtnMap |= RSTICK_DOWN;
    }

    sOcarinaAllowedBtnMask = (
        sOcarinaD5BtnMap |
        sOcarinaB4BtnMap |
        sOcarinaA4BtnMap |
        sOcarinaF4BtnMap |
        sOcarinaD4BtnMap
    );
}

as well as extra logic to handle the right stick here:

s8 rstick_x = input->cur.right_stick_x;
s8 rstick_y = input->cur.right_stick_y;
const s8 sensitivity = 64;
if (rstick_x > sensitivity) {
    sCurOcarinaBtnPress |= RSTICK_RIGHT;
}
if (rstick_x < -sensitivity) {
    sCurOcarinaBtnPress |= RSTICK_LEFT;
}
if (rstick_y > sensitivity) {
    sCurOcarinaBtnPress |= RSTICK_UP;
}
if (rstick_y < -sensitivity) {
    sCurOcarinaBtnPress |= RSTICK_DOWN;
}

and then more modification is done here:

u32 noteSharpBtnMap;
if (customControls) {
    noteSharpBtnMap = CVarGetInteger("gOcarinaSharpBtnMap", BTN_R);
} else {
    noteSharpBtnMap = BTN_R;
}

and here:

u32 noteFlatBtnMap;
if (customControls) {
    noteFlatBtnMap = CVarGetInteger("gOcarinaFlatBtnMap", BTN_Z);
} else {
    noteFlatBtnMap = BTN_Z;
}

with an action-based system this could be simplified immensely and done with 0 cvars. Audio_OcaUpdateBtnMap would no longer need to be called. instead, all we would need to do is set the static map vars here:

s32 sOcarinaD5BtnMap = BTN_CUP;
s32 sOcarinaB4BtnMap = BTN_CLEFT;
s32 sOcarinaA4BtnMap = BTN_CRIGHT;
s32 sOcarinaF4BtnMap = BTN_CDOWN;
s32 sOcarinaD4BtnMap = BTN_A;

to be the actions instead, for example

s32 sOcarinaD5BtnMap = ACTION_OCARINA_D5;
s32 sOcarinaB4BtnMap = ACTION_OCARINA_B4;
s32 sOcarinaA4BtnMap = ACTION_OCARINA_A4;
s32 sOcarinaF4BtnMap = ACTION_OCARINA_F4;
s32 sOcarinaD4BtnMap = ACTION_OCARINA_D4;

It no longer calls a libultra function and gets back libultra data.

i'd argue it already doesn't (we get back extended libultra data), but i understand your point. if we want to continue to support

As a developer of a port using LUS, I should be able to get up and running without building my own controller mapping/configuration menu.

then providing the default OSContPad and/or the proposed OSContPadExtended would very much still be required

If you're not suggesting to remove the old system, but instead treat an action as a bit flag for which virtual buttons are pressed, we are getting closer, but it still needs thought on how it would interact where the buttons are the bits.

This is where a port would need to do some heavy reworking. I wouldn't expect young ports to go this direction as it requires finding all the places where the authentic bit structure of button in OSContPad is expected, and replacing it with a heavily modified version (not sure about name, but let's use OSActionPad as an example)

the Input struct in the port would be modified to use the action pad

typedef struct {
    /* 0x00 */ OSActionPad cur;
    /* 0x?? */ OSActionPad prev;
    /* 0x?? */ OSActionPad press; // X/Y store delta from last frame
    /* 0x?? */ OSActionPad rel; // X/Y store adjusted
} Input; // size = 0x??

and the port-specific OSActionPad could be built however makes the most sense for the port. it could be as simple changing button to be a uint64_t instead of a uint16_t and having 64 actions live within button, or it could be more complex - for example grouping related actions into their own variables (think menuButton and gameplayButton, where the menu would compare bits against menuButton and in game stuff could compare bits against gameplayButton)

I think this needs more baking time before it's ready.

I agree, and I think it probably makes sense to build as much of this as possible out within a port instead of LUS to start, and then see what can be done to move away from an implementation that I assume will basically be "we aren't using LUS for control stuff right now"

tentative plan would be to:

  • create a new SoH branch to do discovery/proof of concept work for this
  • copy the libultraship/src/controller directory into soh/Enhancements/controller.
  • Utilize the work from #340 to initialize an LUS context without the LUS control deck.
  • Get SoH working with with the code from soh/Enhancements/controller instead of the LUS control deck stuff
  • check in to see what needed to happen for that to work (did LUS need changes? if so why/are they reasonable? i figure this would be a good point to step back and think/talk a little.
  • hack away at the code in soh/Enhancements/controller, try to get some basic action based stuff working
  • start to settle in to patterns that feel like they make sense
  • use discovered sensible patterns to fully implement action-based mapping in SoH
  • see what needed to change in LUS (ideally nothing)
  • create a new branch of LUS, copy over the soh/Enhancements/controller directory, make a draft PR (with no intention of it getting merged)
  • discuss the changes, see if there are things that LUS could do that would make it so this would be possible without a port just straight up copying a directory from LUS
  • PR any changes that make sense (think adding functionality to LUS that can be utilized by a port implementing their own control stuff)
  • rework the SoH branch to utilize the new upstream LUS functionality
  • PR a pretty good v1 for action based mapping to SoH

from libultraship.

Kenix3 avatar Kenix3 commented on July 24, 2024

The initial suggestion will no longer be an issue once libultra headers are gone. #406

from libultraship.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.