Kodewerx

Our culture has advanced beyond all that you could possibly comprehend with one hundred percent of your brain.
It is currently Mon Apr 15, 2024 9:22 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 17 posts ] 
Author Message
PostPosted: Tue Nov 27, 2007 11:12 am 
Offline
Kommunist
Kommunist

Joined: Mon Nov 26, 2007 7:21 am
Posts: 8
Hello - I'm KeithE, the creator of the DS Motion Pak.

Recently it occured to me that Nitro Hax could be used in conjunction with the DS Motion Pak to add motion/tilt sensing to existing nds games. The idea would be to create custom codes that read the Motion Pak and activate button presess when the DS is moved or tilted in a certain way. For example, tilting could be used to control Super Monkey Ball, Mario Kart, and plenty of other games.

The standard DS Motion Pak functions run on the arm9, but I have rewritten and simplified C code that runs on the arm7. Is there anyone who would be interested in collaborating with me to convert my C code into Action Replay or Nitro Hax code? I don't have any experience with that, but I'd be willing to donate a DS Motion Pak or two to people who will help.

Thanks.

[edit - changed subject from Nitro Hax to Nitro Hax/Action Replay]


Last edited by KeithE on Thu Nov 29, 2007 2:35 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 27, 2007 1:26 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 10, 2006 9:32 am
Posts: 445
I'm not sure to understand correctly, but if you have compiled the sources for the ARM7, it doesn't need to be converted, it can be executed right away by the AR/Nitrohax (well... what size is it actually ?). (edit : you just need to use a small code that hacks the AR and makes it executes the code you provide).

Then either your proggy must include some way to patch the pad reading routine, or they write to a fixed address that other AR codes can use to patch the game's pad reading routine accordingly to the movment.


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 27, 2007 2:15 pm 
Offline
Kommunist
Kommunist

Joined: Mon Nov 26, 2007 7:21 am
Posts: 8
Attached is a zip file with a simple demo I wrote (based on the combined template example from devkitpro) that reads the X acceleration on the arm7, then passes it to the arm9 via IPC to be displayed on the screen. It does not use NH/AR. My goal is to put the code listed below (from the attached arm7 source) into a NH/AR code that gets run every vblank.

Code:
// DS Motion Code
   // Need to do the read in two parts
   // First part sends the command to load acceleration value onto bus
   // Second part reads the acceleration from the bus
   static unsigned char read_state = 0;
   if(read_state == 0) // first part of read - send command to read X
   {
      read_state = ((volatile unsigned char*)0x0A000000)[2]; // send the command to read X
      read_state = 1; // update read state to the next step
   }
   else // second part of read - get X acceleration
   {
      IPC->aux = ((volatile unsigned char*)0x0A000000)[0]; // read acceleration and send it to arm9
      /*
      Instead of loading X acceleration into IPC-> aux, it could be used to activate
      Left and Right buttons like this:
      if(Xaccel < (128-tilt_thresh) ) "Activate Right button"
      if(Xaccel > (128+tilt_thresh) ) "Activate Left button"
      
      tilt_thresh is a threshold that defines the "dead zone" where neither Left or Right
      are pressed.  Xaccel is equal or close to 128 when device is flat.  It increases
      when tilted left, and decreases when tilted right
      */
      read_state = 0; // reset the read state
   }


I've never done any AR code writing, so I'm not sure how to get it to execute this code.


Attachments:
File comment: DS Motion arm7 demo
arm7_DSMotion.zip [6.29 KiB]
Downloaded 222 times
Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 27, 2007 10:58 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 10, 2006 9:32 am
Posts: 445
I looked a bit the sources. So, if I got it correctly, you write 1 to 0x0A000000 on one VBlank, and the next Vblank 0x0A000000 holds the X acceleration. What I didn't get is what kind of values are they. I mean, 8 bits ? 16 bits ? 32 bits ? Also, what should be the value of tilt_thresh ? (32 ? 64 ?...). And do you have to poll the hardware only on each VBlank ? Or can it be done faster ? Also what about the Y values ? (send 2 to 0x0A000000) ?

The AR hooks the game at some place that gets executed like 300+ (up to 900?) times per seconds. At 60FPS, that means the hardware will be polled like 5~15 times per seconds. So the AR (or a small ASM routine inside the AR) could read the value of the X/Y acceleration (at it will poll at least 5 times per seconds, it should have the time to get both X/Y between each VBLank), write it at some place, and then a small asm routine hooked at the pad reading routine would read the value gotten by the AR, and change the UP/DOWN/LEFT/RIGHT bits accordingly.

Just to give you an idea, here it what the reading of the X(/Y) values would be when done by AR codes only :
// Runs a counter at 02000000
DB000000 02000000
D4000000 00000001
D8000000 02000000
D2000000 00000000
// If first bit of counter = 1 ask for X values by writing 1 to 0A000000
923FCFFC FFFE0001
0A000000 00000001
D2000000 00000000
// If first bit of counter = 0 copies value from 0A000000 to 02000004
923FCFFC FFFE000
D9000000 0A000000
D6000000 02000004
D2000000 00000000

(or it could be replaced with a small asm routine that will do the same job).

And then, on the ARM9 side, the asm routine hooked to the pad reading routine would just read from 0x02000004 and update the value the game has gotten at 04000130 accordingly...


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 28, 2007 1:22 pm 
Offline
Kommunist
Kommunist

Joined: Mon Nov 26, 2007 7:21 am
Posts: 8
Thank you very much - that is very helpful to get me started.

To read acceleration, first read from address 0x0A000002, which tells the motion pak to put the X acceleration on the bus. Then read from address 0x0A000000 to get the 8 bit acceleration value. There needs to be a short time delay between the reads to give the motion pak enough time to load the 8 bit value onto the bus. Reading at 5-15 times per frame is fine, or even once per frame is fine. Y values are read by using address 0x0A000004 instead of 0x0A000002.

Tilt threshold is around 15-30, depending on how you want it to feel. Smaller means it reacts quicker, larger means you have to tilt more to activate it.

I have a question about this:

Quote:
// Runs a counter at 02000000
DB000000 02000000
D4000000 00000001
D8000000 02000000
D2000000 00000000
// If first bit of counter = 1 ask for X values by writing 1 to 0A000000
923FCFFC FFFE0001
0A000000 00000001
D2000000 00000000


Why are you looking at first bit of 023FCFFC when the counter is at 02000000?

I modified it slightly, as follows, and I can see on my oscilloscope that the motion pak is being read properly. But I'm unsure of how to activate the Left and Right button presses. Could you provide some guidance on how to do that?

Code:
DB000000 02000000 // counter at 02000000
D4000000 00000001
D8000000 02000000
D2000000 00000000
            
92000000 FFFE0001 // if LSB of counter == 1
DB000000 0A000002 // read from here to tell motion pak to put X accel on bus
D2000000 00000000
            
92000000 FFFE0000 // if LSB of counter == 0
DB000000 0A000000 // read from here to get X accel
D6000000 02000004 // store X accel
D2000000 00000000
            
72000004 0000008F // if X accel less than (128-15)
// ACTIVATE RIGHT BUTTON
D2000000 00000000
            
82000004 00000071 // if X accel greater than (128-15)
// ACTIVATE LEFT BUTTON
D2000000 00000000


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 28, 2007 1:48 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 10, 2006 9:32 am
Posts: 445
Erm I first made a post will the counter at 0x023FCFFC, then I though it was stupid and changed it to 0x02000000 before going to work. And it seems I forgot to update the value in the conditionnal code...

Also I just remembered the DB code type should be used, as it's buggy.
I hope everything goes fine if we do a 16-bits read/write instead of a 8bits one ?


So, to read X and Y, the AR code should look like that (I changed the counter to 32-bits, and the other memory access to 16-bits. Might not be good?) :
Code:
D9000000 02000000 // counter at 02000000
D4000000 00000001
D6000000 02000000
D2000000 00000000
           
92000000 FFFC0000 // if LSBs of counter == 0
DA000000 0A000002 // read from here to tell motion pak to put X accel on bus
D2000000 00000000
           
92000000 FFFC0001 // if LSBs of counter == 1
DA000000 0A000000 // read from here to get X accel
D7000000 02000004 // store X accel
D2000000 00000000

92000000 FFFC0002 // if LSBs of counter == 2
DA000000 0A000004 // read from here to tell motion pak to put Y accel on bus
D2000000 00000000
           
92000000 FFFC0003 // if LSBs of counter == 3
DA000000 0A000000 // read from here to get Y accel
D7000000 02000006 // store Y accel
D2000000 00000000


A shortened version could be :
Code:
D9000000 02000000 // counter at 02000000
D4000000 00000001
D6000000 02000000
D2000000 00000000

DA000000 0A000000 // 16-bits reads the accelerator value from 0x0A000000
92000000 FFFD0002 // if Y is concerned
D3000000 00000002 // add 2 to the offset
D0000000 00000000
92000000 FFFE0000 // if we are 'asking' for the acceleration
DA000000 0A000002 // read from 0x0A000002 (or 0x0A000002+2)
D0000000 00000000
92000000 FFFE0001 // else if we 'have' the acceleration
D7000000 02000004 // write it 0x02000004 (or 0x02000004+2)
D2000000 00000000


Then you need to hook the pad read routine.
The easiest way, once you find it (using no$gba debugger is an easy way of doing it), is to change the 04000130 with the address of the place you wanna jump to, and then change the ldrh r3,[r0] (that's for mario kard) with a bx r0.

Then, at 0x02000010, you just have to load [04000130] into r3, and then apply the changes depending of the values of [02000004] and [02000006]. However, then one should decide if the pad is totally disabled, or if it's still enabled (the difference being that if the pad is enabled, a key combinaison like UP+DOWN or LEFT+RIGHT would become possible).

Edit :

For MKDS, the hook should look like that :
Code:
52043A90 04000130
02043A90 02000010
02043A60 E12FFF10
D2000000 00000000


The asm source would look like that :
Code:
ldr r3,data
ldrh r3,[r3]
mov r0,#0x02000000
ldrh r12,[r0,#4]
cmp r12,#0x71
biclt r3,#0x010
cmp r12,#0x8f
bicgt r3,#0x020
ldrh r12,[r0,#6]
cmp r12,#0x71
biclt r3,#0x040
cmp r12,#0x8f
bicgt r3,#0x080
ldr r12,data+4
bx r12
data:
.word 0x04000130
.word 0x02043A64

I'm assuming that if y<0x71 it means up, and if y>0x8f it means down. Might be the opposite...
Also, if you want to ignore the pad movments, make a orr r3,#0xF0 after the second line.
Also, I don't push/pop anything, as r0/r12 will be destroyed.
That compiles to this AR codes :
Code:
62000010 E59F3034
E2000010 00000044
E59F3034 E1D330B0
E3A00402 E1D0C0B4
E35C0071 B3C33010
E35C008F C3C33020
E1D0C0B6 E35C0071
B3C33040 E35C008F
C3C33080 E59FC004
E12FFF1C 04000130
02043A64 00000000


Edit : changed the 0203A964 to 02043A64. Also added a check on the asm AR code to make it be writen only once (no need for further writes).


Last edited by kenobi on Wed Nov 28, 2007 11:46 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 28, 2007 6:18 pm 
Offline
Kommunist
Kommunist

Joined: Mon Nov 26, 2007 7:21 am
Posts: 8
Wow, that's great. It all makes sense to me. When I tried it with Nitro Hax, I just got a white screen though. I may have to go buy an ARDS tomorrow.

Instead of hooking the custom asm routine at 0x02000010, could we do this:

Write 0x02000010 at 0x02043A90 (to indicate the address that stores the pad states), then execute (instead of hooking) an asm routine to read pad states from 0x04000130, apply the changes from tilt, and write to 0x02000010?

This might make it easier to adapt to other games, since it does not rely on the ldrh r3,[r0] and the address that you branched to at the end of the asm routine. Can you see an advantage in doing one method over the other?

A couple more questions:

How did you determine the address to branch to at the end of the hooked asm routine - 0x0203A964?

How do you know that there is free (unused) memory available from 0x02000000 to 0x02000054?


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 28, 2007 7:05 pm 
Offline
Komrade
Komrade
User avatar

Joined: Mon Oct 02, 2006 5:56 pm
Posts: 1978
Title: Mr. Bitches
It depends on the game whether or not that area in memory is free. You'll probably want to look at the memory with an emulator to see whether or not the area is free, that is if you feel comfortable with dumping your game cartridges. Alternatively you could see if you couldn't find an Action Replay Trainer Toolkit (Needs an AR to work) and use that to check the memory.

I remember Parasyte found an area in memory that was reserved for an official debugger. (and thus is never used in retail games) Let me see if I can't find it in his Kwurdi thread...

*minutes later*
Nah, I can't find it, but it shouldn't be too hard to locate 0x54 free bytes of memory. Or you could just ask Parasyte about the location of this free RAM.

_________________
Image
Image
<EggWerx> MetalOverlord: Dsman and lemmayoshi will be used for taco meat, ask mo he knows me.
jleemero wrote:
Being required to learn Java for a Comp Sci MAJOR is like being required to shit on a lawnmower to be an astronaut.


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 28, 2007 10:43 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 10, 2006 9:32 am
Posts: 445
Hm. Holy cow. I know have issues with copy/pasting codes and I usually end up writing bogus code in my posts... But this just look stupid. I know it's not 0x0203A964, but 0x02043A64. I saw that "problem" just before going to bed, and I thought I edited it (but the site was terribly slow, so I guess I gave up on verifying my post a last time...) :/
So the AR code shoud end with "02043A64 00000000". I"m terribly sorry about that mistake :/

I case that still doesn't work I'll make some tests on the hardware this evening...(only tried on the emu for now, by writing my codes manually in ram, that's why I didn't detect by bogus code at first...).

As far as I understood, usually games load their ARM9 at 0x02000000. So at this area you have the encrypted area of the game, which usualy starts with junks (ie. not asm code), which means that's free space to use.
You could also use the area just below 0x023FE000. I'm not 100% sure why, but I guess that if the programmers (of the games) obey to the devkit by the rules, they end up not using that area (actually, 0x023FE000 is the address at which the AR code handler sits, so it's free for 99.99% of the games. There are exceptions, like animal crossing, that use this area ("HighArena"?)).

And course your idea is also good. One could just make a bigger ASM routine that gets executed inside the AR (so no need to worry about finding free space), and that will run the counter, read the accelerator and the pad values, and write the result at 02000000 (and then one would make code(s) to change (all) the 0x04000130 to 0x02000000). Would be faster (if speed is an issue), and better (in term of compatibility - as we don't need to worry for free space for our asm code, and the very start of the encrypted area of the ARM9 (here 02000000) should always be "free" as it holds the destroyed game ID, ie. E7FFDEFF) I guess. However, even if executing code "inside'" the AR works for all the AR versions (and NitroHax), just be aware it might become an issue with future AR versions (ie. might need another AR hack), and can be an issue for R4/M3/whatever users. Also, it'll make the code not directly portable to things like CBDS.

And as you asked about (the bogus) 0x0203A964, I believe changing it to 0x02043A64 makes more sense to you now.


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 29, 2007 12:02 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 10, 2006 9:32 am
Posts: 445
FYI :
Here is an AR code that will autopatch the game when pressing Start+Select once (it'll replace all 0x04000130 with 0x02000000). Takes like 3~4 seconds to patch all the ram (0x02000000-0x02400000, by scanning 0x40 blocks of 0x00010000), and it lags the game a bit during that time :
source :
Code:
push {r0-r7}
ldr r0,values
ldrh r1,data
ldr r2,values+4
ldrh r3,data+2
cmp r1,#0
ldreqh r4,[r0]
tsteq r4,#4
tsteq r4,#8
cmpeq r1,#0
moveq r1,#1
streq r1,data
cmp r1,#1
bne end
mov r4,#0x02000000
add r5,r4,r3,lsl #0x10
add r3,#0x1
strh r3,data+2
add r6,r4,r3,lsl #0x10
loop:
ldr r7,[r5],#4
cmp r7,r0
streq r4,[r5,#-4]
cmp r5,r6
blt loop
cmp r3,#0x40
moveq r3,#0
streq r3,data
streq r3,data+2
end:
pop {r0-r7}
bx r14
values:
.word 0x04000130
.word 0x02400000
data:
.word 0x00000000

Compiled AR code :
Code:
023FE074 012FFF11
E0000000 00000084
E92D00FF E59F006C
E1DF17B0 E59F2068
E1DF36BA E3510000
01D040B0 03140004
03140008 03510000
03A01001 058F104C
E3510001 1A00000D
E3A04402 E0845803
E2833001 E1CF33B6
E0846803 E4957004
E1570000 05054004
E1550006 BAFFFFFA
E3530040 03A03000
058F3010 058F300E
E8BD00FF E12FFF1E
04000130 02400000
00000000 00000000
023FE074 E3520003

(tested on the hardware and working)


Then, this code should take care of reading the pad and the accelerator, and "join" them together :
source:
Code:
push {r0-r5}
mov r5,#0x04000000
ldr r5,[r5,#0x130]
ldrh r1,counter
add r1,r1,#1
strh r1,counter
mov r2,#0x0A000000
mov r3,#0x02000000
mov r4,#2
tst r1,#2
addne r4,#2
tst r1,#1
ldrneb r0,[r2]
ldreqb r1,[r2,r4]
beq end
tst r1,#2
bne Y
cmp r0,#0x71
biclt r5,#0x010
cmp r0,#0x8f
bicgt r5,#0x020
strh r5,counter+2
b end
Y:
ldrh r5,counter+2
cmp r0,#0x71
biclt r5,#0x040
cmp r0,#0x8f
bicgt r5,#0x080
strh r5,[r3]
end:
pop {r0-r5}
bx r14
counter:
.word 0x00000000

Compiled AR code :
Code:
023FE074 012FFF11
E0000000 00000080
E92D003F E3A05301
E5955130 E1DF16B8
E2811001 E1CF16B0
E3A0240A E3A03402
E3A04002 E3110002
12844002 E3110001
15D20000 07D21004
0A00000D E3110002
1A000005 E3500071
B3C55010 E350008F
C3C55020 E1CF52B2
EA000005 E1DF51BA
E3500071 B3C55040
E350008F C3C55080
E1C350B0 E8BD003F
E12FFF1E 00000000
023FE074 E3520003


(tested on the hardware and working).

(by hardware I mean DS+Trainer Toolkit).

The patcher should be a good think, because some games load some new routines in their memories, and that way the user should always be able to patch them if the accelerator suddently stops working (for exemple, when you enter a minigame, a special level, or things like that). Its danger is that some of the patched 0x04000130 could actually be some in-game values, or could used to access other registers...

Now as I don't have that accelerator thing, I can't test the Y axis (what value for UP, what value for DOWN). But I guess (hope) that for the rest it should work properly.

Also the code might look kinda poor (and maybe not optimized). But it works !

Edit : I've updated one or two things. If you've gotten the code before this message, get it again ;)

Edit2 : Actually a very small lag is created when the game is patched, I guess because the pad values are only updated when the AR code handler has been executed 4 times. I'll correct that in a couple of hours. (actually I'll look at it later...). Also, is there any sure way to detect if the accelerator is plugged ? I mean, if the user removes it, the asm routine could be able to detect that and then disable the accelerator support (until it has been plugged back).


Last edited by kenobi on Thu Nov 29, 2007 4:06 pm, edited 3 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 29, 2007 1:12 pm 
Offline
Kommunist
Kommunist

Joined: Mon Nov 26, 2007 7:21 am
Posts: 8
IT WORKS!! Awesome! I was struggling for a while to get the previous method to work, but it wasn't working. This is great. I bought an Action Replay this morning, and I'm using it now. I tried to modify this code to get it to work on Nitro Hax (replaced the AR hacks with NH specific commands), but I was unsuccessful.

Kenobi - please PM me your address and I'll put a DS Motion Pak in the mail to you as a token of my appreciation.

There is a way to check for the DS Motion Pak - if the X and Y acceleration are both 0xFF then it there is no DS Motion Pak. The 0xFF comes from the pullup resistors on the GBA cartridge bus pulling all 8 data lines to Vdd.

Is there a certain specific value before/near/after all the 0x04000130 that could be scanned for in order to avoid overwriting in-game values?

Currently it is all or nothing with the steering - either straight, right, or left. We could improve the "feel" by using a technique called Pulse Width Modulation (PWM). If you tip left a little, it would hold the left button for some frames, and not hold it for some frames. The percentage of frames that the pad is held would increase as you tip more, until it is held 100% of the time. This could be accomplished by having a counter that gets decremented by the magnitude of the acceleration. When the counter reaches 0, activate the button press. As you tip more, the counter would decrement faster so the button would be pressed more often.

Another thing that could be added - check if Z acceleration is greater than a certain threshold and activate R to jump. So, to jump you would just lift the DS quickly.

This is really cool - thank you so much for your help.


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 29, 2007 3:36 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 10, 2006 9:32 am
Posts: 445
Glad to hear it worked. As I said, the accelerator detection code is "unoptimized", and actually could look really bad to some eyes (sorry). However it was just a shortly wrotten "test code", to verify that everything is working fine.

For the 0x04000130, I guess one could also search for 0x027FFFA8 (that holds a copy of the DS buttons - ie. X/Y/Debug/Fold) near the 0x04000130 (until now I've only seen +/- 8 bits near 0x04000130), but I'm not certain that it'll be compatible with everything (ie. I'm not certain that all "parts" (="minigames") of all have it)).
The other way would be to scan for an opcode that reads the address where the 0x04000130 is stored, but that would make the patcher much more complicated, much more slow, and also that would bring an ARM/THUMB problem.

For particular cases, I guess a "manual" patcher code would have to be made and used instead of the automated patcher...
(would look like that for MKDS :
Code:
52043A90 04000130
02043A90 02000010
D2000000 00000000
)

And about the "all or nothing" yep, I guess a lot of things can be done to improve that. The counter is a good idea. I'm thinking of something like (if value>0x7f) do ((0xFF-value)>>8) (>>8 so we have 8 steps of acceleration), increment that until the value is >=0x1F (or whatever value between 0xF and 0x1F), and update the movement at that time. This is just an exemple of course, some tests/tweakings must be made on the real hardware.

Small question : I guess the values range from 0x00 to 0xFF, right (in that case, someone directing the accelerator to a full top/right would reach the values 0xFF/0xFF for X/Y ?).
Also, what about that Z acceleration ? (read from 0x0A000006 to get it? Also setting it to a jump buton sounds nice, however that would mean the code would be different for each game).

Finaly, you said a short time is needed between reading the 2/4 registers, and actually getting the value from the 0 one. Like... 10 ticks ? 20 ticks ? I mean, I bet having both X and Y "at the same time" would improve the movement/reaction.


Edit :
For Nitrohax, you should follow this :
chishm wrote:
ASM codes are supported, but you need to use the correct code type. Use C2000000 0000xxxx (where xx is the length of the ASM code in bytes) instead of 023FE074 012FFF11 E0000000 0000xxxx and remove 023FE074 E3520003 from the end of the code.


ie (untested) :
Code:
C2000000 00000084
E92D00FF E59F006C
E1DF17B0 E59F2068
...
04000130 02400000
00000000 00000000[code]
and
[code]C2000000 00000080
E92D003F E3A05301
E5955130 E1DF16B8...
E1C350B0 E8BD003F
E12FFF1E 00000000


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 29, 2007 5:49 pm 
Offline
Kommunist
Kommunist

Joined: Mon Nov 26, 2007 7:21 am
Posts: 8
Don't worry about your code at all. I'm a complete asm beginner, so I have to study your code carefully to understand how it works.

When an accelerometer axis is held perpendicular to gravity (so it feels 0 acceleration), its output is 128 +/ some small tolerance (around 5-10). For every g (1g is 9.8 meters/s^2 : earth's gravitational acceleration), the output will change by about 51. So when it is sitting flat on the table, the outputs (X,Y,Z) are 128,128,179 +/- some tolerance. If you tip it all the way to the left, the outputs will be 179,128,128.

This means that in the range 00-FF, the sensor can sense about +/- 2.5g. So it is good for sensing motions as well as tilt.

Yes, you guessed correctly for the Z axis - read from 0x0A000006 to put it on the bus, then read from 0x0A000000 a short time later to get the acceleration.

The time delay between reads needs to be at least 185 swi delays. In the standard arm9 DS Motion Pak functions, I use the libnds command swiDelay(185). I don't know how many ticks that corresponds to.


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 29, 2007 10:58 pm 
Offline
Kommunist
Kommunist

Joined: Tue Oct 10, 2006 9:32 am
Posts: 445
Ok. Thanks for the infos. Any luck with NitroHax ? I'll try to make some tests on it if you can't get it working.

And about my asm code, I guess I'll have to give it a fresh view to "clean" it a bit (maybe this week end), as there must be some unnecessary things. For exemple, in the "patch" routine, the last streq r3,data+2 should be removed as it's useless (the streq r3,data seems to already already have tooken care of setting the whole data to 0 - I guess I wanted to make 2 streqh, but a single streq is good enought in that case).
I also read some posts about calibration over gbadev, but I'm not sure how it actually works (I guess when calibrating the program read the X/Y/Z position when the DS is on a table, and consider the returned value as the "neutral" position).


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 30, 2007 9:32 am 
Offline
Kommunist
Kommunist

Joined: Mon Nov 26, 2007 7:21 am
Posts: 8
Yes, I did get it to work with Nitro Hax. I had to put the code all on one line - it was giving a white screen when I put each code on a separate line.

Calibration would be a good idea. Probably best to do it when start+select are pressed. The user should set the DS flat on the table, then press start+select. The program would then read X, Y, and Z (if Z is used). Here is how the calibration would work:

Call the calibration values X0, Y0, and Z1 (for 0g on X and Y, 1g on Z). Then, the tilt thresholds for X and Y would be X0 +/ thresh and Y0 +/- thresh instead of 128 +/- thresh. For example, if our threshold is 15, and X0 is 125 and Y0 is 130, the tilt thresholds would be [110 140] for X, and [115 145] for Y.

If the user wants to calibrate in an orientation other than flat, that would work fine too. This would be useful if the user wants to hold the DS tilted slightly towards them while playing (for games that use the Y axis).


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 02, 2007 1:19 am 
Offline
Komrade
Komrade
User avatar

Joined: Tue Mar 27, 2007 6:23 pm
Posts: 1354
Location: Mario Raceway, 1509.831, 217.198, -564.429
Title: Mario Kart 64 Hacker
Hm, do DS games do a lot of card access in-game? I'm thinking if we patched them to not detect the card being removed, then as long as they weren't trying to read from it, they'd still run, and we could stick in a motion card and use it. Even better, if they use one standard routine to read the card, we could patch it to just hang the game until we put the card back in.

_________________
Image 143
HyperNova Software is now live (but may take a few tries to load) currently down; check out my PSP/DS/Game Boy/Windows/Linux homebrew, ROM hacks, and Gameshark codes!


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 04, 2007 12:30 pm 
Offline
Kommunist
Kommunist

Joined: Mon Nov 26, 2007 7:21 am
Posts: 8
Here are codes that do analog control - tilt a little to turn a little, tilt a lot to turn a lot.

It makes the menus VERY hard to control, so I added a feature that if you hold SELECT it turns off the tilt sensing. Hold SELECT when the game is in a menu, then you can use the D-pad to choose your option.it needs some improvement (maybe a key sequence to turn the tilt mode on and off)

Action Replay:023fe074 012fff11 e0000000 00000084 e92d00ff e59f006c e1df17b0 e59f2068 e1df36ba e3510000 01d040b0 03140004 03140008 03510000 03a01001 058f104c e3510001 1a00000d e3a04402 e0845803 e2833001 e1cf33b6 e0846803 e4957004 e1570000 05054004 e1550006 bafffffa e3530040 03a03000 058f3010 058f300e e8bd00ff e12fff1e 04000130 02400000 00000000 00000000 023fe074 e3520003 023fe074 012fff11 e0000000 000000e4 e92d00ff e3a05301 e5955130 e1df1cb8 e2811001 e1cf1cb0 e3a0240a e3a03402 e3a04002 e5df60b4 e5df70b2 e3110002 12844002 e3110001 15d20000 07d21004 0a000021 e3110002 1a00000f e350007f b2866080 b0466000 aa000002 e356000f c3c55010 c3a06000 e3500081 c0866000 c2466080 da000002 e356000f c3c55020 c3a06000 e1cf55b2 ea00000f e1df54ba e350007f b2877080 b0477000 aa000002 e357000f c3c55040 c3a07000 e3500081 c0877000 c2477080 da000002 e357000f c3c55080 c3a07000 e1c350b0 e1cf60bc e1cf70ba e8bd00ff e12fff1e 00000000 00000000 00000000 023fe074 e3520003 94000130 fffb0000 023fe074 012fff11 e0000000 0000001c e92d0003 e3a00301 e5900130 e3a01402 e1c100b0 e8bd0003 e12fff1e 00000000 023fe074 e3520003

Nitro Hax:
C2000000 00000084 e92d00ff e59f006c e1df17b0 e59f2068 e1df36ba e3510000 01d040b0 03140004 03140008 03510000 03a01001 058f104c e3510001 1a00000d e3a04402 e0845803 e2833001 e1cf33b6 e0846803 e4957004 e1570000 05054004 e1550006 bafffffa e3530040 03a03000 058f3010 058f300e e8bd00ff e12fff1e 04000130 02400000 00000000 00000000 C2000000 000000E4 E92D00FF E3A05301 E5955130 E1DF1CB8 E2811001 E1CF1CB0 E3A0240A E3A03402 E3A04002 E5DF60B4 E5DF70B2 E3110002 12844002 E3110001 15D20000 07D21004 0A000021 E3110002 1A00000F E350007F B2866080 B0466000 AA000002 E356000F C3C55010 C3A06000 E3500081 C0866000 C2466080 DA000002 E356000F C3C55020 C3A06000 E1CF55B2 EA00000F E1DF54BA E350007F B2877080 B0477000 AA000002 E357000F C3C55040 C3A07000 E3500081 C0877000 C2477080 DA000002 E357000F C3C55080 C3A07000 E1C350B0 E1CF60BC E1CF70BA E8BD00FF E12FFF1E 00000000 00000000 00000000 94000130 FFFB0000 C2000000 0000001C E92D0003 E3A00301 E5900130 E3a01402 E1C100b0 E8Bd0003 E12FFF1E 00000000


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 20 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group