Main > Main Forum
720 Real/Joystick/Spinner Test
Xiaou2:
marcusP
Tested new upload.
While this seems to work with a mouse well...
It will not work with a real 720 controller.
A real 720 controller has 2 optical reader discs.
Dial a (72 spokes) = read rotation of the player
Dial b (2 spokes ONLY ) = calibrate player to face north if reading is true/on
Dial b will only be read Once in a full rotation. When it is read, it will immediately snap the player to face North. With your code, it is not snapping north immediately... its incrementing gradually over time. There was also a decrease option... which should not exist.
The reason for the Instant snap to North, is because the if the player is facing the wrong direction when the stick is pointing North... the Dial B will let the game know that the stick is north, and to make the player face north right now... so that the stick direction matches the player direction.
Xiaou2:
Ok, heres a visual so its easy for anyone to understand how the real controller works:
Parts: (from top to bottom)
1) Controller Lever
2) Encoder 1 ( 72 notches )
3) Encoder 2 ( 2 notches )
Color Key:
Light Blue Dots = Notches (holes where the sensor can read through )
Orange = Sensors (can tell if a notch has passed, and in which direction)
A) Game starts and the Skater is facing diagonally left... but the stick is pointing diagonally right. The game does not know this, because Encoder 1 isnt capable of telling the machine which way is Up. It can only track movement.
B) When the player spins the controller, the 2nd encoders 2 notches go past the sensor. The sensor tells the game that the stick is now in the NORTH position, so please reset the character on the screen to face NORTH.
C) Now the game is calibrated, and the Lever and Character both face the same direction. If any time in the game there is any de-calibraion... the game will recalibrate it when the 2nd encoder moves past the sensor.
Playing the game with a normal spinner is sort of possible... but to pull of tricks, you have to land the skateboard facing the right way or you will crash. That isnt easy when you can not feel which direction you are facing... which is why the game designers made a stick that points in the direction you are facing. This way you are well aware of how much you have to turn to land the trick without botching the landing and falling flat on your knees.
Derrick Renaud:
--- Quote from: marcusP/driverman/arabara on January 28, 2011, 11:01:01 pm ---
--- Quote from: Derrick Renaud ---For the 100th time. SUBMIT THE CODE!
The latest idea to use the -joy & -mouse options to select between options in the driver code would be refused.
--- End quote ---
Whom did you consult, or is that just YOUR own OPINION?
Submitting code just to be refused is waste of time, no?
--- End quote ---
Are you back to actually try to learn something or just rant more. Everything in your new rant shows that you refuse to read anything. You actually cut the answers given right out of the quotes you make.
I explained why these options are not to be used. Also the proof is in the fact the no drivers do this. It limits the users ability to map inputs the way they desire.
If you actually read anything I wrote, I stated that my own first code submissions would be changed to meet core standards. I did not rant on like a child about that. I used it to learn and become a team member.
I will ignore the rest of your trolling and move on to your code. I will discuss it for the forum members that actually do want to learn from technical discussions. Feel free to actually learn from the discussion of it.
--- Quote from: marcusP/driverma/arabara on January 28, 2011, 11:01:01 pm ---
--- Code: ---static READ8_HANDLER( leta_r )
{
static int last_in, input, rotations, last_angle, angle;
int aX= input_port_read(space->machine, "LETA0") - 127;
int aY= - (input_port_read(space->machine,"LETA1") - 127);
int relative_in = input_port_read(space->machine, "LETA2");
if(aX!=0 || aY!=0){
if((angle= atan2(aX, aY) *22.9183)< 0) angle+= 144;
if(last_angle > 120 && angle < 24) rotations+= 144;
if(last_angle < 24 && angle > 120) rotations-= 144;
input = (last_angle = angle) + rotations;
}else if(last_in!=relative_in)last_in=input=relative_in;
return((offset&3)<1)?
input_port_read(space->machine,"LETA3") : input;
}
--- End code ---
--- End quote ---
First off, you removed the whole checking if the hander is only running from the 720 game. This will break all other games that use the LETA ports. Do not remove the "state->pedal_count != 0" check and handling that is in the original code. You can not overlook the fact that other games use these ports.
--- Code: ---int aX= input_port_read(space->machine, "LETA0") - 127;
int aY= - (input_port_read(space->machine,"LETA1") - 127);
--- End code ---
Interesting changing the -128 to -127. Unforunately 8-bit integers go from -128 to + 127. So this would be wrong.
We are tring to change an UINT8 (0-255) to a INT8 (-128 to +127). So if the UINT8 value is 0 it should move to -128.
0 - 127 = -127 (wrong)
0 - 128 = -128 (correct, at min)
255 - 127 = 128 (wrong, overflows to -1)
255 - 128 = 127 (correct, at max)
128 - 127 = 1 (wrong, not center 0)
128 - 128 = 0 (correct, at center)
I imagine your code only seems to work because you must have changed the port default from 0x80 to 0x7f.
FWIW you do not need to do (offset & 3) like the previous code did. That is done automatically by the core memory call. I only mention this to explain how it works. Leaving the code as (offset & 3) would not reflect poorly on the submission.
--- Code: ---AM_RANGE(0x1810, 0x1813) AM_MIRROR(0x278c) AM_READ(leta_r)
--- End code ---
Memory range 0x1810 to 0x1813 can only have an offset value in the 0-3 range.
I won't even bother to check if your changes to the joystick code is correct. But it does not seem so. This seems strange but it does not matter to the discussion:
--- Code: ---if((angle = atan2(aX, aY) *22.9183)< 0)
angle += 144;
--- End code ---
I also will ignore that you asign values in the if statement. I do not beleive Aaron would let that pass. It should be like this:
--- Code: ---angle = atan2(aX, aY) *22.9183);
if (angle < 0)
angle += 144;
--- End code ---
You really need to change the names of the ports. LETA0 is the centering, LETA1 is the rotate. And name the fake ports as such. That would have been the cleanup part of my original walkthrough, that you just ranted about instead.
MAME concerns itself with actually hooking up ports that the original hardware had hooked up. In my original walk-through I suggested just using the LETA ports to make things easy for the discussion. The unused LETA ports really should not be used this way. I would have discussed this after step 1/2 had been completed and we moved on to the cleanup. I would have explained why the fake joystick port tag should be renamed as such. And the original unused LETA ports be passed through unchanged.
So your code at this point should be:
--- Code: ---static READ8_HANDLER( leta_r )
{
static const char *const letanames[] = { "LETA0", "LETA1", "LETA2", "LETA3" };
atarisy2_state *state = space->machine->driver_data<atarisy2_state>();
if (offset <= 1 && state->pedal_count == -1) /* 720 */
{
static int last_in, input, rotations, last_angle, angle;
int aX= input_port_read(space->machine, "FAKE_X") - 128;
int aY= - (input_port_read(space->machine,"FAKE_Y") - 128);
int relative_in = input_port_read(space->machine, "LETA1");
if(aX!=0 || aY!=0)
{
if((angle = atan2(aX, aY) *22.9183)< 0)
angle += 144;
if(last_angle > 120 && angle < 24)
rotations += 144;
if(last_angle < 24 && angle > 120)
rotations -= 144;
input = (last_angle = angle) + rotations;
}
else if (last_in! = relative_in)
last_in = input = relative_in;
return (offset != 1) ? input_port_read(space->machine, letanames[offset]) : input;
}
return input_port_read(space->machine, letanames[offset]);
}
--- End code ---
The rest of the code, unfortunately is a complete hack. Unfortunately you refused to understand my code which shows how the game truly behaves. Your only concern in your code seems to be to make the game behave in the way you want it to. No concern for how it really behaves is shown.
I know you want to completely ignore the center disc and only concern yourself with game play, but that is not what MAME wants. You modified the joystick code to not return any centering data because "you" do not care about it. You are free to not care in your own build.
I have told you my spinner code lets you test the game code with simulated centering data that matches the real thing. You want to ignore that and are free to do so in your own build. As far as MAME goes, the game constantly polls this data. A way for us to test this is preferred. The service mode control test will only constantly pass this test with a real control or my spinner code. It will go out of sync otherwise. Again you are free to ignore this in your build. MAME does not.
So now, congrats you made it to step 2 of my original coding walk-through. Well even though you did not post the PORT code (step 1,) I can infer what it must be. You made both the real input and the fake joystick exist at the same time. Adding the spinner code like I did was not part of the original challenge. Though I would have moved on to explain it if we ever sanely got past the cleanup part after step 1/2 were done.
That leads us to the final thing I would have got to. The problem with making the fake/real controls exist at the same time. It would be nice to see your PORT code to see how you handled this. I would have suggested at this point an easy to use menu selection so the user does not have to see/understand why there are multiple inputs in the player control menu. A lot of users already have a hard time with the fact that inc/dec buttons exist at the same time as the analog axis. Adding more ports mapped together would only add to their confusion. So IMHO a user selection process if preferred to limit the player controls and analog settings to just the control the player wants to use.
One final thing is that the final submission should follow MAME coding standards. So each { } in if statements should be on their own line. I do not say this to be picky. It is a code policy that you need to be aware of. See:
http://mamedev.org/devwiki/index.php/MAME_Coding_Conventions
You may feel that having standards is being too picky when your only concern is making one game behave the way you want. MAME has to concern itself with marinating maintaining thousands of games. Standards need to be followed. MAME is an ongoing project. I'm sure you will find old drivers not up to current standards. These should not be used as an argument to justify old standards. MAME's policy when working on old drivers is to try to update them to new standards whenever work is done to them.
First submissions will not be refused for not following standards. If the code serves a valid need, it will be cleaned up and added. For future submissions to be continued to be looked at as good quality, the person will be explained the standards. If they learn from it they will continued to be guided when needed. Refusing to learn from the process, will reflect negatively.
--- Quote from: marcusP/driverman/arabara on January 28, 2011, 11:01:01 pm ---1.) Do you want to know how to fix flickering animation?
2.) Do you want to know how to solve jittery analog motion?
--- End quote ---
Submit the code once you are sure it is correct. Not if it is anything like the code you submitted in your post. If it is it will be rejected. No one will bother giving you the in-depth explanation that I have here. MAME does not have a paid response team to to handle all messages. If a submission shows promise, someone usually tries to guide the person who submitted the code. If it is totally wrong like above, it most likely will not be responded to.
(edit) stupid spell checker - marinating?
Derrick Renaud:
Some minor changes to the code I posted:
These are optimizations. "angle" does not need to be defined as static. Doing so forces it to be in memory when it only needs to be temporary. Changing it to just an int allows the compiler to be free to use a register instead.
Also no need to get the "relative_in" value from the input_port_read() at the start if it is not needed. Doing so is slower then the strcmp() that caused you so much grief in my previous code. A better placement is after it is found that the fake joystick has not moved.
--- Code: ---static READ8_HANDLER( leta_r )
{
static const char *const letanames[] = { "LETA0", "LETA1", "LETA2", "LETA3" };
atarisy2_state *state = space->machine->driver_data<atarisy2_state>();
if (offset <= 1 && state->pedal_count == -1) /* 720 */
{
static int last_in, input, rotations, last_angle;
int angle;
int aX= input_port_read(space->machine, "FAKE_X") - 128;
int aY= - (input_port_read(space->machine,"FAKE_Y") - 128);
if(aX!=0 || aY!=0)
{
angle = atan2(aX, aY) *22.9183;
if(angle < 0)
angle += 144;
if(last_angle > 120 && angle < 24)
rotations += 144;
if(last_angle < 24 && angle > 120)
rotations -= 144;
input = (last_angle = angle) + rotations;
}
else
{
int relative_in = input_port_read(space->machine, "LETA1");
if (last_in! = relative_in)
last_in = input = relative_in;
}
return (offset != 1) ? input_port_read(space->machine, letanames[offset]) : input;
}
return input_port_read(space->machine, letanames[offset]);
}
--- End code ---
Or better yet, my original coding walk-through suggested to check the relative port for change. This way the relative port only has to be read. If it changes then you do not have to read the 2 fake ports, do some fast math on them and check for 2 changed items. 1 port read versus your current 3. Which brings us to araraba's answer to his ultimate question. What variable are you talking about in step 2. That would be the "last_in" that he created to compare against.
--- Code: ---static READ8_HANDLER( leta_r )
{
static const char *const letanames[] = { "LETA0", "LETA1", "LETA2", "LETA3" };
atarisy2_state *state = space->machine->driver_data<atarisy2_state>();
if (offset <= 1 && state->pedal_count == -1) /* 720 */
{
static int last_in, input, rotations, last_angle;
int relative_in = input_port_read(space->machine, "LETA1");
if (last_in != relative_in)
last_in = input = relative_in;
else
{
int aX= input_port_read(space->machine, "FAKE_X") - 128;
int aY= - (input_port_read(space->machine,"FAKE_Y") - 128);
if(aX!=0 || aY!=0)
{
int angle = atan2(aX, aY) *22.9183;
if(angle < 0)
angle += 144;
if(last_angle > 120 && angle < 24)
rotations += 144;
if(last_angle < 24 && angle > 120)
rotations -= 144;
input = (last_angle = angle) + rotations;
}
}
return (offset != 1) ? input_port_read(space->machine, letanames[offset]) : input;
}
return input_port_read(space->machine, letanames[offset]);
}
--- End code ---
marcusP:
Do you know about Xiao-Xiao fighting figures, master Xiaou? You see, they were even accusing me of doing nothing else but re-using that old code from Analog+ days, and we all know authentic controller did work there. I uploaded binary TWO WEEKS ago specifically to test this functionality first, please everyone:
TEST - OBSERVE - COMPARE - DESCRIBE - ASSUME NOT
Anyway, it does work with authentic controller, it works perfectly with everything. Calibration snaps to north only 1st time when the game is started, after that re-calibration is GRADUAL, of course! My code does nothing to authentic input, it simply just forwards it to virtual input pins, as it was discussed already, and even Derrick confirmed that works with authentic controller.
To calibrate analog stick or arcade spinner with a handle (absolute spinner), move AD_ANALOG stick, or "DEC" (HACK_UP) key, or spinner handle towards north and then press digital UP or DOWN, or move Mouse_Y, mapped to DIAL_V until the character sprite faces north too. After that this input is unnecessary/irrelevant, just like with authentic controller where this second encoder stops working and the game would stay calibrated during the whole day of gameplay, need only be calibrated at the start up, by moving the handle to the east before powering the cabinet on.
--- Quote ---Playing the game with a normal spinner is sort of possible... but to pull of tricks, you have to land the skateboard facing the right way or you will crash. That isnt easy when you can not feel which direction you are facing... which is why the game designers made a stick that points in the direction you are facing. This way you are well aware of how much you have to turn to land the trick without botching the landing and falling flat on your knees.
--- End quote ---
This is irrelevant, we all know about your "Robotron argument" and how authentic controllers are very important aspect of the gameplay, and I of course agree, but anyone can now play _720 Degrees_ whit whatever controller they want/have. So, the point now is to discuss the two implementation, compare differences, establish cons and pros, test for the bugs, test if there is any impact of these changes to other Atari games, and such... By the way, as explained several times by both me and Derrick, you can always try to stick some handle on top of arcade spinner and thus make it "absolute" just like 720 spinner is, you know what I'm talking about?
Derrick, I am purposely giving you obfuscated code, you would not want me to do everything for you now, right? This is not place to discuss source code, let's please stick to what code actually does and how it works. Then, I can help you write it down properly. Bring some of MAME developers here if you want to discuss the code itself, I dare you bring anyone, just ONE person from the team to support what you are saying, I don't think even haze will support you.
Anyway, I already addressed and explained all your objections on MAMEworld, most specifically here in this post:
http://www.mameworld.info/ubbthreads/showthreaded.php?Cat=&Number=244562&page=0&view=expanded&sb=5&o=&fpart=1&vc=1
*** I suggest non-programmer should do not pay attention to Derrick's confusion as to how sentences in C, just as in English, can be re-written in many different ways, and some of those ways is plain blabbering and gibberish, while the other are pure application of mathematics. In any case it is the MEANING or "what code actually does", that is important, where simpler and smaller is ALWAYS better, that's Occam's razor in general, while in mathematics the same thing is really just a plain "sanity".