Sharing my ps4 ds4 controller hack and asm debug
IncVoid
Posts: 40
Long Story short, make sure your pasm variables are initialized to some value, or else the PC compile time assembly pointer doesn't get incremented, respect the special register's S-field behavior versus D-field behavior, update your constants when you feature creap.
Bought a "remap ffc" from amazon, and had a prop mini and 4 way. So my wires popping off the pcb pads wasnt' an issue anymore. Made this abomination.
In hindsite I should of did ffc to ffc soldering and it would of been a lot thinner, and not as wide due to half the IDE cable not being used. and mounting the 4way stick on top made it hard to solder neighboring pins, should of did a rotary encoder or two, the stick's axis is mapped to adding or subtracting to values that get added to phsa based on the high bit, kinda jumping time, probably should of just compared versus cnt but ohwell.
I did similar with a 4d microsystems uoled with a prop in it for my 360 years ago. Don't know if that forum made the migration but its around somewhere.
I was brainstorming the code and staring at it for days before the 8th, when Tom Clancy's The Division launched. Googled Phil's tricks and traps to double check my assembly. I had a couple hardware/software issues, such as I soldered to the same legs of a switch so that one switch was always locked on, label'ing, uninitialized data and using registers in D-field when they should of been in the S-field, as well as a bad array length in my constants.
I pass parameters to a function that are to be moved into the S and D field of a rdlong instruction.
I figure why move them into a register only to move them into the S and D field, so I opted out of using inline parameters to pasm funtions to make it easier to read for me, I kept getting confused, so instead of pass parameters via the "trick and traps" way:
I tried this, dref just takes a register label/address and puts the contents of that register back into D
Later I made an easier to read and less generalized function checking buttons using an array masks and whether the button is active low or high,because I knew I'd be using the same arrays #masks #action
everytime so I embedded the parameters inside the function. and let the movd and movs instructions do it for me. I used TD and TS, because earlier version of the function were using another array and instructions. So I was using the same values many times and it was easier to reuse, plus I'd have to shift the index over to add to the D field instead of s-field if I did't use temporary holders.
Pretty sure my problem was where I defined ts and td:
so td and ts were both #action+index, luckily I never used d1, I only used d1s4 above. Easily fixed by giving it a 0 value.
So I wasn't testing INA with the proper mask, instead its active low/high signal. I know my buttons are active low, so the c_pin test would be testing against an all zero value, which would always set the 0 flag,
again test for an all zero value in the c_sig op, no carry. So I ALWAYS got zero set, carry cleared.
and of course since the flags aren't equal the following code would always call #pb, which is why my buttons were locked on (disregarding the one button that was physically soldered the wrong way)
the #pb function was written higher level like, which kinda saved me because at least it was working
How I found my errors were a lil brute forcy
since my jmps were fine and it wasn't executing data or being super random, I was able to insert wrlong instructions to copy the registers out to a literal address in hub ram. the end of the array that I originally passed it. In fact this is where I found my array length was wrong, cause I had it write the array it stored, back to hub ram, and I serial'd that out and hand checked it in the Parallax Serial Terminal and saw it wasn't what I expected, off by one, I had added another remapped button and added one more element to the arrays mask/action/pin number. The middle array was all wrong (where the ts td yielded its head), which lead me to my array garr function (get array) and I checked the registers. line by line by adding "mov d,(register to check)" around to check my operations then discovered hmm. if I check td up here its one thing, but down here after ts was manipulated, I get something else.
after all that only one button was locked on so I went to the multi-meter and checked the switch legs fixed that and the might prop is providing me accessibility functions, albeit trivial ones that could of been handled normally with just wiring but still, fun exercise.
Bought a "remap ffc" from amazon, and had a prop mini and 4 way. So my wires popping off the pcb pads wasnt' an issue anymore. Made this abomination.
In hindsite I should of did ffc to ffc soldering and it would of been a lot thinner, and not as wide due to half the IDE cable not being used. and mounting the 4way stick on top made it hard to solder neighboring pins, should of did a rotary encoder or two, the stick's axis is mapped to adding or subtracting to values that get added to phsa based on the high bit, kinda jumping time, probably should of just compared versus cnt but ohwell.
I did similar with a 4d microsystems uoled with a prop in it for my 360 years ago. Don't know if that forum made the migration but its around somewhere.
I was brainstorming the code and staring at it for days before the 8th, when Tom Clancy's The Division launched. Googled Phil's tricks and traps to double check my assembly. I had a couple hardware/software issues, such as I soldered to the same legs of a switch so that one switch was always locked on, label'ing, uninitialized data and using registers in D-field when they should of been in the S-field, as well as a bad array length in my constants.
I pass parameters to a function that are to be moved into the S and D field of a rdlong instruction.
I figure why move them into a register only to move them into the S and D field, so I opted out of using inline parameters to pasm funtions to make it easier to read for me, I kept getting confused, so instead of pass parameters via the "trick and traps" way:
CALL #Subroutine LONG Arg1 LONG Arg2 .. Subroutine MOVS :GetArg1,Subroutine_ret ADD Subroutine_ret,#1 :GetArg1 MOV :Arg1,0-0 MOVS )GetArg2,Subroutine_ret ADD Subroutine_ret,#1 :GetArg2 MOV :Arg2,0-0 .. JMP Subroutine_ret :Arg1 LONG 0-0 :Arg2 LONG 0-0 Subroutine_ret RET
I tried this, dref just takes a register label/address and puts the contents of that register back into D
garr 'd_register,pointer to hub memory,count mov d,garr_ret add garr_ret,#1 'inc addr call #dref 'd contains inline[0]=#masks movd :loop,d ':loop d = inline[0] mov d,garr_ret add garr_ret,#1 call #dref 'd contains inline[1]=#bufp call #dref 'd contains the address inside bufp movs :loop,d mov d,garr_ret 'address of inline 2 add garr_ret,#1 call #dref mov :loopc,d 'loop count :loop rdlong 0-0, #0-0 'literal hard address add :loop,d1s4 djnz :loopc, #:loop '+4 jmp garr_ret :loopc long 0-0 garr_ret ret 'we got all parameters
Later I made an easier to read and less generalized function checking buttons using an array masks and whether the button is active low or high,because I knew I'd be using the same arrays #masks #action
everytime so I embedded the parameters inside the function. and let the movd and movs instructions do it for me. I used TD and TS, because earlier version of the function were using another array and instructions. So I was using the same values many times and it was easier to reuse, plus I'd have to shift the index over to add to the D field instead of s-field if I did't use temporary holders.
cb mov td,#masks add td,index mov ts,#action add ts,index movd :c_pin,td 'modify all the next instructions movd :c_sig,td movs :c_sig,ts :c_pin test 0-0,ina wz 'is one of A-D pressed :c_sig test 0-0,0-0 wc 'is it the correct signal cb_ret ret
Pretty sure my problem was where I defined ts and td:
ts long td long d1 long $200 'one to the d-field d1s4 long $204ts,td,d1 all pointed to the same register, if my knowledge of the data section is correct. I'm still not sure if this is what was happening. But maybe that is why the res instruction is required to increment the PC compile time assembly pointer because empty labels do not?
so td and ts were both #action+index, luckily I never used d1, I only used d1s4 above. Easily fixed by giving it a 0 value.
So I wasn't testing INA with the proper mask, instead its active low/high signal. I know my buttons are active low, so the c_pin test would be testing against an all zero value, which would always set the 0 flag,
again test for an all zero value in the c_sig op, no carry. So I ALWAYS got zero set, carry cleared.
and of course since the flags aren't equal the following code would always call #pb, which is why my buttons were locked on (disregarding the one button that was physically soldered the wrong way)
mov f_c,#3 'buttons 3,2,1. 0 is handled separately :f mov index,f_c call #cb [b]if_z_ne_c[/b] call #pb 'press remapped 'if the pin matches required signal if_z_eq_c call #rb 'release remapped 'make sure released djnz f_c,#:f 'next button
the #pb function was written higher level like, which kinda saved me because at least it was working
pb mov d,#map 'D for data :) add d,index call #dref mov mindex,d 'mindex=map[index] mov d,#masks add d,mindex call #dref mov m,d 'm=masks[mindex] or dira,m 'set the output of pin pb_ret ret
How I found my errors were a lil brute forcy
since my jmps were fine and it wasn't executing data or being super random, I was able to insert wrlong instructions to copy the registers out to a literal address in hub ram. the end of the array that I originally passed it. In fact this is where I found my array length was wrong, cause I had it write the array it stored, back to hub ram, and I serial'd that out and hand checked it in the Parallax Serial Terminal and saw it wasn't what I expected, off by one, I had added another remapped button and added one more element to the arrays mask/action/pin number. The middle array was all wrong (where the ts td yielded its head), which lead me to my array garr function (get array) and I checked the registers. line by line by adding "mov d,(register to check)" around to check my operations then discovered hmm. if I check td up here its one thing, but down here after ts was manipulated, I get something else.
wb movs :loop,bufp add :loop,#(eof) nop :loop wrlong d,#0-0 wb_ret ret
after all that only one button was locked on so I went to the multi-meter and checked the switch legs fixed that and the might prop is providing me accessibility functions, albeit trivial ones that could of been handled normally with just wiring but still, fun exercise.