Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AM64DS Mod #435

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

AM64DS Mod #435

wants to merge 4 commits into from

Conversation

LRFLEW
Copy link

@LRFLEW LRFLEW commented Mar 11, 2021

I'm not really expecting this to be merged here, but I wanted to make the PR so that it can at least be discussed. I'm sure some of this doesn't follow the style of the rest of the project, so any code style suggestions are appreciated.

I've been working on getting analog stick input into Super Mario 64 DS recently. To do this, I wrote a modification to DeSmuME that interacts with the mod I made for SM64DS to add analog stick support. This works in DeSmuME by inventing a new Slot 2 (GBA-slot) device that has an analog stick and provides the state in the way that SM64DS stores input information internally. The idea is that this works similarly to the guitar grip or piano accessories, except there is no real-world device this is emulating.

The simulated Slot 2 device is designed to work very specifically to how SM64DS processes input. This means that it is less applicable to other games that might benefit from analog stick input. Though, SM64DS is one of the few games that can be easily modified to support an analog stick due to it already having a virtual analog stick on the touch screen.

@zeromus
Copy link
Contributor

zeromus commented Mar 11, 2021

Wow, it even does bindings. Way more than minimum effort, good job.

Can YOU think of any reason this shouldn't be merged? It seems to not impose big junk burden on the core.

Only reason I can think of to improve it is.. I wonder... could you go ahead and add a drop-down list that lets you select the a "mode" which is "AM64DS" and "Generic" (for now) and then design a simpler method of communicating the analog state for Generic? This will enable someone else to expand it later in case they feel like undertaking a similar project.

@LRFLEW
Copy link
Author

LRFLEW commented Mar 13, 2021

Sorry it took me a while to respond.

Can YOU think of any reason this shouldn't be merged? It seems to not impose big junk burden on the core.

I wasn't sure how much much of a "junk burden" it would be seen as. I also wasn't sure how accepting the project would be of an "emulated" GBA-slot device without a real-world physical version. I don't have any particular reason why it shouldn't be merged, other than maybe it being too specific to AM64DS in this form.

could you go ahead and add a drop-down list that lets you select the a "mode" which is "AM64DS" and "Generic" ...?

I've been thinking about this. I don't like the idea of it being a drop-down menu. It could be confusing to end-users, and could lead to UI bloat if more game-specific versions are added. I think the better way of doing it is to have one "mode", but use the address range for game-specific interfaces. Currently it just uses 0x09000000 to 0x09000007, with 0x09000008 to 0x09FFFFFF completely unused (There's also 0x08000000 to 0x08FFFFFF, but since I did find code in SM64DS that seems to look for a GBA ROM header, I'd rather leave this range empty).

My proposal is to provide a "Generic" interface in the range 0x09000000 to 0x0900000F, and allow any game-specific hacks to be placed in higher ranges. For example, AM64DS could use 0x09000010 to 0x09000017 (This change would require changing the AM64DS codes, but it would be a simple change to make). More game specific interfaces can be added for more games and similar projects, as it's generally easier to update the emulator for the game than it is to update the game for the emulator (especially without symbol names). Plus some games might want more than just one stick (eg. Metroid Prime Hunters might be nice with dual-stick controls (if it's possible))

Do you have any ideas for how the "Generic" interface would work? I could go off of how I'd imagine an actual GBA-slot attachment might work (two unsigned 6-bit values in one 16-bit read), or go off of how DirectInput reports it (two signed 16-bit values), or some other option altogether.

@zeromus
Copy link
Contributor

zeromus commented Mar 13, 2021

Your idea is much better than mine.

Actually, with that idea, we can consider this done. Adding new protocols later is trivial. However I would suggest we go ahead and do the generic one, to set a precedent (on the memory map) and avoid future mistakes. the small address range makes sense to me. You can keep AM64DS in the address range that it's at. No need to change those; we don't need to privilege "generic".

I don't see why we should do it as 6 bit. Seems kind of arbitrary. Let's do it the way directinput does it: two signed 16-bit values. Let's put those at xx14 and xx16 and save xx10 and xx12 for future use... configuration and strobing. I don't feel strongly about this; it's just a proposal. If it doesn't make sense for some NDS programming reason, please do let me know.

The only further idea I have would be to transform this into a multifunction emulator enhancement interface. Added memory if someone needs it, etc. Really the only way that affects us today is with "branding".

@LRFLEW
Copy link
Author

LRFLEW commented Mar 15, 2021

However I would suggest we go ahead and do the generic one, to set a precedent (on the memory map) and avoid future mistakes.

I'm ok with waiting on the Generic interface before merging this. I'd rather get it right than have to deal with fixing things after the merge.

You can keep AM64DS in the address range that it's at. No need to change those; we don't need to privilege "generic".

I'd actually rather privilege Generic. Moving the AM64DS part up 0x10 would require adding a single instruction to my patch, which would take like 5 minutes to update everything (since all the different revisions only have different offsets in their patches). There are also some requests on my project that would involve making more game changes (eg LRFLEW#3), so I might make the changes together in one update.

I don't see why we should do it as 6 bit. Seems kind of arbitrary.

My thinking was about what chips would be available for making something. I figure the analog stick would work as two potentiometers to get two analog signals (from Gnd to Vcc voltages), which would go through a DAC. Looking at the list of 7400 chips, I saw the 74x500, which produces a 6-bit output, and I figured that would be the likely way it would work. However, doing more research, I found quite a few 8-bit DACs (eg) that would be more likely to be used. With this, I think a physical device would most likely use two 8-bit values, so that both axis can be sampled with a single read of the ROM address range.

Let's do it the way directinput does it: two signed 16-bit values.

Sounds reasonable to me.

and save xx10 and xx12 for future use... configuration and strobing.

What do you mean by this?

@zeromus
Copy link
Contributor

zeromus commented Mar 15, 2021

I meant to reserve two halfwords for future use, since one expects to see those in a memory map before the registers that contain the axis values.
struct generic_regs
{
u16 reserved;
u16 forlater;
u16 x;
u16 y;
};

If you want to privilege generic, that's fine.
But I would suggest you move yours to 0x09001000 or something to leave plenty of room for generic variations and stuff. I just hate having a disorderly memory map and figure its best to leave spaces where we can.

@LRFLEW
Copy link
Author

LRFLEW commented Mar 17, 2021

Ok, I'm going to update this PR very soon with the suggested updates. I have a few thoughts/questions to point out real quick before I start pushing changes.

I understand pushing my range up to make more room, but I wonder if 0x1000 isn't a bit much. I feel like whatever we reserve for Generic will be the standard for how much gets reserved for each variant. With the range you gave, this would be a mask of 0x00FFF000 for the protocol and 0x00000FFF for the value. I was thinking moving my interface to 0x09000100 might make a bit more sense, giving a mask of 0x00FFFF00 for the protocol and 0x000000FF for the value. Either works; it's just a matter of if we want to section it into 256-byte chunks or 4096-byte chunks.

I want to reserve the first two bytes of the range (0x09000000 and 0x09000001) specifically for any physical device that might be made. I'm not really expecting such a device to be made (though I'm tempted to try to do it myself), but if someone does, it would be nice to have the address range reserved so that we can properly emulate it. If you have plans for the two values you want reserved (which it sounds like you might), then we should move the x and y values up by 4 (so 0x09000008 and 0x0900000A) (4 to keep them 32-bit aligned so they can be read by a single ldr instruction).

I think I'm going to rework the deadzone code I wrote. Working with the Wii U and reading DirectInput documentation, I realized the deadzone-applied values should be continuous, which my implementation isn't. I'll fix this, but might remove one of the check boxes in the UI, since it probably won't make sense anymore.

Also looking at the DirectInput documentation, I realized that saying the Generic interface works based on "how DirectInput reports it" is a little non-specific. DirectInput has the range of output values runtime-specified using DIPROPRANGE, with the program expected to either query or set the range. It looks like DeSmuME sets the range of all joystick axis to -10000 to 10000 here. Should we stick with this range for the Generic interface? Should we use the more standard -32768 to 32767? Or perhaps we should use the standard that SM64DS sets up, which is -4096 to 4096 (-0x1000 to 0x1000) (which would probably be easiest to use on the DS due to its lack of an FPU). EDIT: Or another power-of-two bounds, such as -0x4000 to 0x4000 (which is the largest that will fit in a signed short without overflow).

Lastly, it seems like some of the other GBA-slot devices use a custom "open bus" value to (I assume) indicate that it's connected. The Guitar Grip uses 0xF9FF, the Piano uses 0xE7FF, the Paddle uses 0xEFFF, and the RumblePak uses 0xFFFD. Should we create one for the Analog "accessory" as well? Maybe something like 0xAFFF (if it's not already in use).

@zeromus
Copy link
Contributor

zeromus commented Mar 17, 2021

At this point you've put enough thought into it to get whatever memory map you want. There's no decision there that's irrevocable; more stuff can always be kludged in somewhere else. As long as we put some some thought into it now, that's good enough.

The open bus value is a good idea. Im not sure why games do it that exact way, but maybe there's some reason that future hardware-makers will appreciate us copying. Nocash has more peripherals documented so you can check there for a few more values.

Your point about 4096 is a good one. That's the fixed point precision many NDS games are using. Let's stick with that.

@LRFLEW
Copy link
Author

LRFLEW commented Mar 21, 2021

I've updated the PR with the new memory map. I put the AM64DS interface at 0x09000100 and the X and Y values of the Generic interface starting at 0x09000008. I also left comments about the currently-reserved values.

I added the Open-Bus value, but I'm not sure how applicable it would be for the device. It seems that these sorts of open-bus values are done by connecting certain pins to ground (through a resistor likely), forcing the value to always be zero. Devices that don't make use of all the bits, such as the Guitar Grip with 5/8 lines used and Piano with 13/16 lines used, will tie unused lines to ground. But devices that use all the data lines, such as the RAM Expansion, don't use this method at all. This means that an actual Open-Bus value would depend on a physical device's specification. For now I added a basic open-bus value, but we can say it might change in the future. We could also make a more explicit detection value in the Generic interface or indicate the custom open-bus value is only well-defined in the 0x08XXXXXX range (which should be doable in hardware with transistors). (Plus, DeSmuME doesn't appear to emulate Open-Bus 100% correctly, as the value should depend on the EXMEMCNT/EXMEMSTAT value according to the GBATEK info)

@zeromus
Copy link
Contributor

zeromus commented Mar 21, 2021

sounds good to me. let me know when youre done and ill merge it

@DragonautMk
Copy link

Is this pr dead?

@getItemFromBlock
Copy link

Hello, I have made a fork of this in order to have the latest changes in the repo with this PR. I don't want to take credits here, all I did was resolve the merges. So far the fork is up to date with the latest commits in this repo, so if people want to play with this while waiting for updates you can check my fork. https://github.com/getItemFromBlock/AM64DS_DeSmuME

@rofl0r
Copy link
Collaborator

rofl0r commented Feb 28, 2024

@getItemFromBlock : it would be more helpfull if you could make a recursive diff of your repo vs master and have the changes in a single patch/commit, rather than what you currently have (years old branch with master merged into it, and the actual commits on page 123) - since it makes it much more visual what the actual changes are.

@getItemFromBlock
Copy link

I see, but I am lacking the git knowledge here. Do you have any source or indication on how I could accomplish that ?

@rofl0r
Copy link
Collaborator

rofl0r commented Feb 29, 2024

clone official git master to dir1 , copy your fork's directory to dir2, remove .git directory in dir2, then cp -r dir2/* dir1/, then go to dir1 git add '*' , git commit -m changes git format-patch -1 HEAD~1 and then you have a patch called something like 0000-changes.diff. go to your original fork dir (not the copied one) and git checkout master, git checkout -b am64ds, git am /path/to/dir1/0000-changes.diff and finally git commit --amend --author "LRFLEW <LRFLEW@aol.com>" to fix the author name. in the editor window that pops up fix the title of the commit to "Add Analog "GBA" Support"
and add
"This allows hacked/homebrew DS games to read analog stick values from the emulator." a line further down to fix the commit message, then save and exit the editor and push your new branch. now you can delete dir1 and dir2.

@zeromus
Copy link
Contributor

zeromus commented Feb 29, 2024

Allow me to put it a little more succinctly. Clone official repo. Paste your version on top. Check it closely for mistakes accumulated through merges. Fix them. Commit it. Done. This loses the history of the development of the feature, but it's not likely to be hugely important in this case.

@getItemFromBlock
Copy link

Alright, I managed to make the new branch with the patch solution, but it took way longer than expected. I don't know why but git refused to apply the patch.
Anyway here is the new branch: https://github.com/getItemFromBlock/AM64DS_DeSmuME/tree/am64ds

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants