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

Scaling lightgun coordinates to usable game area #655

Closed
StormedBubbles opened this issue May 19, 2022 · 16 comments
Closed

Scaling lightgun coordinates to usable game area #655

StormedBubbles opened this issue May 19, 2022 · 16 comments

Comments

@StormedBubbles
Copy link

Hello,

This is more of a question about a potential improvement because I'm not sure how to implement it. In pcsx_rearmed/frontend/libretro.c, these lines of code appear:

int gunx = input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X);
int guny = input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y);

If the whole screen is used for lightgun access, then this works perfectly (Time Crisis). Both the emulator and RetroArch treat (0,0) as the center of the screen and have the same coordinate ranges for lightgun usage. However, many other games do not use the entire viewable area for the lightgun coordinates. For example, Time Crisis: Project Titan does not allow the cursor to move all the way to the left or right and requires adjustments to the GunCon X ratio in order to get line-of-sight alignment with an absolute-mouse device such as a Sinden Lightgun.

I'm guessing the above issue is why the offset/ratio core options were added in the first place, but I am still curious: Is there an existing variable that fetches the width and height that the game is actually using for the lightgun? This would be different from the visible game area. If those were to exist and, say, be labeled as width and height, respectively, then the lightgun coordinates could probably be scaled as

gunx * width / 0xFFFE;
guny * height / 0xFFFE;

(where the Libretro lightgun coordinates range from -0x7FFF to 0x7FFF, so we'd want to divide by 2 * 0x7FFF = 0xFFFE to scale). Perhaps these variables exist somewhere and are related to overscan?

@StormedBubbles
Copy link
Author

As a quick follow-up, the same issue appears to have been solved in Beetle-psx using a similar scaling formula.

@negativeExponent
Copy link

negativeExponent commented Jun 13, 2022

what system are you using or better are you able to compile pcsx on the system you are using.

if your able to, try to change these lines from:

in_analog_left[port][0] = (gunx * GunconAdjustRatioX) + (GunconAdjustX * 655);
in_analog_left[port][1] = (guny * GunconAdjustRatioY) + (GunconAdjustY * 655);

to

in_analog_left[port][0] = (gunx * 0x7FFF) / (0x7FFF << 1);
      in_analog_left[port][1] = (guny * 0x7FFF) / (0x7FFF << 1);

and see how it behaves as i dont have an actual lightgun device

@StormedBubbles
Copy link
Author

Thank you!

I am using a Raspberry Pi. Sorry, I should have included that in the first place. Yes, I am able to make those code changes and compile to test. I will try that out shortly.

@StormedBubbles
Copy link
Author

StormedBubbles commented Jun 14, 2022

That code change reduces how far the in-game cursor can go. The cursor is aligned at screen center, but it loses alignment the further I point from center. If I'm reading this correctly, the formula is essentially dividing gunx and guny by 2. Is that correct? That seems to be what is happening. If I'm pointing the gun at the midpoint of the far-right edge of the screen, then the in-game cursor looks to be about halfway between where I'm pointing and the center of the screen.

@negativeExponent
Copy link

negativeExponent commented Jun 14, 2022

That code change reduces how far the in-game cursor can go. The cursor is aligned at screen center, but it loses alignment the further I point from center. If I'm reading this correctly, the formula is essentially dividing gunx and guny by 2. Is that correct? That seems to be what is happening. If I'm pointing the gun at the midpoint of the far-right edge of the screen, then the in-game cursor looks to be about halfway between where I'm pointing and the center of the screen.

Can you try out fceumm and some light gun games like duck hunt if it performs with sinden gun as expected?

BTW, in what gpu is running fceux in this platform? Peops unai or the other one? See in core options to know there should be options there for the specific gpu used

@StormedBubbles
Copy link
Author

FCEUMM, FBNeo, and various MAME cores are all good with the Sinden gun for me. I'm using RetroArch 1.10.0 and am accounting for the changes to how lightgun coordinates are handled by using a 16:9 border. I don't see info about the GPU for FCEUMM in the core options. The information section in the menu just lists FCEUMM as an SVN build. @Widge-5, do you happen to know that info?

The issue in my original post does happen for many games in this emulator, but some are fine and track perfectly as is (Time Crisis).

@negativeExponent
Copy link

i actually meant core option in pcsx. if your gpu is neon, try to disable that enhancemen t-related thing, its only neon-gpu i know of that has enhanced viewport, so the guncon coordinates probably need a multiplier of 2 or probably 4

@StormedBubbles
Copy link
Author

StormedBubbles commented Jun 14, 2022

Oh, I see that option. It is NEON. All of those options were off for me while testing. The behavior seems to be the same regardless of having the enhanced resolution on or off.

The issue doesn't seem to be related to integer scaling of the entire screen. Unless I'm forgetting something, the issue only occurs on the X axis. It's more like a 7-10% difference that can be accounted for with the core option for the GunCon ratio. The problem is that the cursor is trapped inside of a pillar-boxed area, but parts that are considered out of bounds still include game data. That's why I was curious if it had to do with overscan.

Apologies for the poor description. It would be easier to explain if the emulator had its own cursor representing the emulating computer's own mouse cursor. What you get with the original GunCon code here is very similar to what's shown in the linked images. The game's internal crosshair is the red one, while the + is the user's computer's mouse cursor. The offset is at its worst at the edge of the screen.

https://user-images.githubusercontent.com/5952315/50057642-4d8b6980-017e-11e9-98ac-6bfcfba14d9b.png
https://user-images.githubusercontent.com/5952315/50057643-4d8b6980-017e-11e9-9027-c9108c073eab.png

@StormedBubbles
Copy link
Author

I did some more research on this. I noticed that, in libpcsxcore/plugins.c, there is the following:

	case PSE_PAD_TYPE_GUNCON: // GUNCON - gun controller SLPH-00034 from Namco
			stdpar[0] = 0x63;
			stdpar[1] = 0x5a;
			stdpar[2] = pad->buttonStatus & 0xff;
			stdpar[3] = pad->buttonStatus >> 8;

			//This code assumes an X resolution of 256 and a Y resolution of 240
			int xres = 256;
			int yres = 240;

			//The code wants an input range for x and y of 0-1023 we passed in -32767 -> 32767
			int absX = (pad->absoluteX / 64) + 512;
			int absY = (pad->absoluteY / 64) + 512;

			//Keep within limits
			if (absX > 1023) absX = 1023;
			if (absX < 0) absX = 0;
			if (absY > 1023) absY = 1023;
			if (absY < 0) absY = 0;

			stdpar[4] = 0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * absX >> 10);
			stdpar[5] = (0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * absX >> 10)) >> 8;
			stdpar[6] = 0x20 + (yres * absY >> 10);
			stdpar[7] = (0x20 + (yres * absY >> 10)) >> 8;

			//Offscreen - Point at the side of the screen so PSX thinks you are pointing offscreen
			//Required as a mouse can't be offscreen
			//Coordinates X=0001h, Y=000Ah indicates "no light"
			//This will mean you cannot shoot the very each of the screen
			//ToDo read offscreen range from settings if useful to change
			int OffscreenRange = 2;
			if (absX < (OffscreenRange) || absX > (1023 - OffscreenRange) || absY < (OffscreenRange) || absY > (1023 - OffscreenRange)) {
				stdpar[4] = 0x01;
				stdpar[5] = 0x00;
				stdpar[6] = 0x0A;
				stdpar[7] = 0x00;
			}

			memcpy(buf, stdpar, 8);
			respSize = 8;
			break;

The code assumes a resolution of 256x240. I know that PlayStation games could have pretty wildly varying resolutions. The only list I could find including a lightgun game was this one, which states that Time Crisis has a resolution of 256x240. Time Crisis also happens to be possibly the only game that functions correctly out of the box with lightgun devices in this emulator. The rest have scaling issues on the X axis. Perhaps adjusting this so that the resolution is more generic would solve the issue. The example I gave above with Project Titan seems to indicate that it has an X resolution greater than 256, but the emulator is limiting the cursor movement to the portion 256 px wide centered at the calibration point the user triggers when firing at the target at the start of the game.

@Widge-5
Copy link

Widge-5 commented Jul 1, 2022

There are two Time Crisis games. One is simply called "Time Crisis" and the other is called "Time Crisis: Project Titan". They are two very different games.
In my experience using lightgun games with lr-pcsx-reamrmed, "Time Crisis" is the only game that requires no scaling correction. Here are the X-axis ratio corrections I must apply to each PSX game in order to have accuracy:

  • Crypt Killer : 1.08
  • Die Hard Trilogy 2 : 1.08
  • Gense Kyokou Seirei Kidoudan - Elemental Gearbolt : 1.08
  • Ghoul Panic : 1.07
  • Guntu - Western Front June, 1944 - Tetsu no Kioku : 1.10
  • Mighty Hits Special : 1.07
  • Point Blank : 1.05
  • Point Blank 2 : 1.05
  • Point Blank 3 : 1.05
  • Resident Evil Survivior : 1.04
  • Simple 1500 Series Vol. 24 - The Gun Shooting : 1.07
  • Simple 1500 Series Vol. 63 - The Gun Shooting 2 : 1.08
  • Time Crisis : 1.00
  • Time Crisis Project Titan : 1.07
  • Die Hard Trilogy : 1.03
  • Lethal Enforcers I & II : 1.07
  • Project Horned Owl : 1.05
  • Rescue Shot : 1.08

@StormedBubbles
Copy link
Author

@Widge-5 Thanks! Yes, I was referring to those two games separately. The original Time Crisis from 1997 is fine in this emulator. It's the console-exclusive sequel Time Crisis: Project Titan from 2001 that I was referring to with the problem. I can confirm Widge's numbers with those ratio adjustments (now called "response" in the core options). The ratio adjustment works to give nearly perfect accuracy, but the game gets artificially pillarboxed as a result. You still see the whole game, but parts of the left and right sides of the screen become inaccessible by the gun.

@Widge-5
Copy link

Widge-5 commented Jul 2, 2022

Thank you @negativeExponent .
Can you clarify that last edit to lines 660 & 661 of plugins.c?
I don't see a difference between the before and after.

@StormedBubbles
Copy link
Author

@negativeExponent Thanks for the suggestions! Making the changes you mentioned does appear to correct the scaling in Time Crisis: Project Titan while maintaining the tracking for the original Time Crisis (both NTSC USA versions). The patched version of the NTSC/USA Resident Evil: Survivor to add back in the removed GunCon support also appears to track correctly.

However, some other games I have tried are negatively affected. PAL games in particular seem to be hit the hardest. I can't seem to get any shots to hit the screen in Ghoul Panic (PAL) anymore, and Extreme Ghostbusters: The Ultimate Invasion (PAL) has the usable screen area reduced by a lot.

The formula right below the changed lines in plugins.c still seems to have dependence on the 256x240 resolution assumption:

stdpar[4] = 0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * absX >> 10);
stdpar[5] = (0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * absX >> 10)) >> 8;
stdpar[6] = 0x20 + (yres * absY >> 10);
stdpar[7] = (0x20 + (yres * absY >> 10)) >> 8;

@SindenLightgun (the one who added that code) Do you have insights on how to generalize the formula?

@negativeExponent
Copy link

Ok

@StormedBubbles
Copy link
Author

For what it's worth, with xres=256 and yres=240,

  • stpar[4] ranges from 90 to 446
  • stpar[5] just divides stpar[4] by 256, so it ranges from 0.351563 to 1.74219
  • stpar[6] ranges from 32 to 272
  • stpar[7] just divides stpar[6] by 256, so it ranges from 0.125 to 1.0625

The difference between the max and min for stpar[6] is 240, which at least makes sense at a glance. I don't understand why it's not 0 to 240, but it seems to work for most games. The 90 to 446 range of stpar[4] gives the difference 446-90=356. I'm not sure where those numbers are coming from.

@StormedBubbles
Copy link
Author

The above commit resolved the specific issue I was having with games losing screen real estate when using the core options to adjust the ratio and offset.

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

No branches or pull requests

3 participants