|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Author | Message |
---|---|
|
Light phaser code/algorithm
Posted: Fri Feb 15, 2019 8:45 pm
|
I've been looking at some games' light phaser code and the official Sega docs, and I'm finding it quite confusing.
The docs say that the TH signal is pulsed for 20-30us when the gun sees light. This seems not to be a feature of the gun, so presumably it's the VDP (or IO chip?) analysing the gun signal and denoising/edge detecting/pulse generating - but if so, why only 20us? That's only ~70 CPU cycles. Why not set a per-line flag? The docs also say that the H position is latched when the edge is seen. Therefore the code must poll TH, grab the H and V positions, and the values returned will trace the left edge of a circle "seen" by the light sensor. The game must then calculate where it thinks the gun is pointing (the middle of the circle) based on this. So I disassembled Missile Defense 3D. It does a few interesting (and possibly unexplained) things: 1. It polls TH much faster than the docs say is needed. Every 25 cycles (7us), in fact. This doesn't leave time for it to ever exit the polling loop, so it does some funky call stack rewriting in the frame interrupt to terminate the loop. 2. It has what look like delay opcodes between each time it gets triggered, so it won't see points on the same line - but then it also uses the V count to discard points seen on the same line 3. It discards the first two lines it sees 4. It seems to compute the X position as the mean of the points it sees, which ought to mean it mis-tracks to the left of the cursor 5. It scales and offsets the values it gets from the H counter, suggesting the values don't map to the pixel count It's possible this is just horrible code that happens to come out with a reasonable result because one part (the skew to the left) cancels the other (the scaling/offsetting) in normal use cases. Certainly when I played it a few years ago on a small CRT it seemed OK. Averaging might be reasonable if the TH signal was a raw "do I see light" signal, and you polled really fast, because then you'd aim to sample points all over the circle and averaging them will be sensible. But the code is careful to ignore multiple points on the same scanline. I also had a look at Porkopolis. This seems to act entirely differently (if my understanding is correct): 1. It only checks TH in the HBlank interrupt 2. If low, it grabs the H and V counts 3. It then doubles the H count and subtracts 32 to map it to pixel space If the TH signal is only held low for 30us, then I don't see how this can work on a real system (where each line is ~63us) - but forum posts suggest it does. Can someone confirm that? Does anyone have any other insight? I thought maybe I should have a look at another game, maybe Missile Defense 3D is not "normal". I am thinking of making a test ROM, but I don't actually have any hardware to test it with. |
|
|
Posted: Sat Feb 16, 2019 9:57 am |
I can't speak for the MS version, but I've been doing some C64 light gun coding. There is a delay in the signal, once you press the trigger and/or it sees the light beam, the signal takes time to travel down the cable. While on say the pad, this amount of time in tiny and trivial, when you are measuring the pixel clock, its a significant delay. And such you will get a H reading that is further to the right than where the user is aiming. Also hands are shaky and need to be factored in. | |
|
Posted: Sat Feb 16, 2019 10:37 am |
That's certainly true, and I expect the alignment of sensor is going to be fairly dodgy, but I guess I still need to make a test ROM to collect the raw data from a real system to see what the gun really "sees". | |
|
Posted: Wed Feb 20, 2019 2:29 pm |
Every filter in between the SMS and light gun input adds delay too. It's not a direct connection from light sensor to an input as shown by the schematic that someone drew in a previous post : http://www.smspower.org/forums/files/lightphaser3050_145.png
It's interesting to see how different games use the light gun. |
|
|
Posted: Wed Feb 20, 2019 9:21 pm |
I'm hoping to find a standard function in several games... but it's clearly not a simple copy paste job. | |
|
Posted: Tue Feb 26, 2019 10:02 am Last edited by Maxim on Wed Feb 27, 2019 10:22 am; edited 2 times in total |
Here's a commented/reformatted/refactored version of the sample code in the Sega docs for reading the light phaser...
It: 1. Waits for the trigger to be pressed 2. Blanks the screen to white 3. Polls TH, waiting for it to be 0 4. Captures the H and V counts to a buffer (unless the buffer is full) 5. Polls TH, waiting for it to be 1, before going back to 3 6. When the frame is up, it tries to rewrite the stack (but I think it's buggy...) 7. It then looks through the data it captured and segments it into runs of H, V pairs where the V counts are <3 lines apart 8. It selects the longest run and then the H, V in the middle of that run 9. If H >= $a0, the gun is not pointing at the screen 10. Else X = (H - 22) * 33/16 and Y = V - 1 The code seems untested and the algorithm seems oddly tolerant of missing lines or triggers on the same line, tries quite hard to deal with "seeing" multiple things (which I don't see how it is possible to do), and then totally fails to try to compute a valid X coordinate anyway. |
|
|
Posted: Tue Feb 26, 2019 9:51 pm |
I disassembled Marksman Shooting / Trap Shooting / Safari Hunt and it actually uses almost exactly the same code as the official docs sample above. The byte sequence for the part where it scales the H-counter to an X coordinate is found in these games:
* Hang On & Safari Hunt * Hang On & Safari Hunt [BIOS] * Marksman Shooting & Trap Shooting & Safari Hunt * Marksman Shooting & Trap Shooting.sms ...suggesting they all use the same code as their source. |
|
|
Posted: Wed Feb 27, 2019 9:38 am Last edited by Maxim on Wed Feb 27, 2019 12:23 pm; edited 2 times in total |
Gangster Town is almost identical, except it subtracts 24 from the H count before scaling it up and it rounds the result to a multiple of 8 pixels. | |
|
Posted: Wed Feb 27, 2019 9:55 am |
Similar code (subtracting 22 from the H counter) with a single opcode optimisation (sla a -> add a, a) is in:
Assault City [Light Phaser] Rambo III Rescue Mission Wanted |
|
|
Posted: Wed Feb 27, 2019 10:15 am |
Laser Ghost is similar again, but with some changes to the code:
* It does not rewrite the stack to break the polling loop, instead it uses the V count to decide to stop polling the gun * It reads the H and V counts after seeing a 1 -> 0 -> 1 transition on TH, the earlier code captures them on the 1 -> 0 transition - but as I understand it this ought to work much the same. * It subtracts 27 from the H count instead of 22 * Then it clamps the result to the range 0..112 * It applies the same scaling, then subtracts another 16 at the end * It takes Y = V + 4 So still no intelligent way to compute X, just (different) fudge factors which result in an X offset of about 5.7 pixels. |
|
|
Posted: Wed Mar 15, 2023 3:07 am Last edited by Rene Dare on Wed Mar 15, 2023 8:22 pm; edited 1 time in total |
I've recently got a Canadian/US Master System in pristine condition (lucky me). Since I want to play light phaser games, I've also had to purchase a CRT TV and ended up getting a 32" Sony Wega (not the hi-scan version) which I expected to behave just like any other CRT TV. However, on the first try of Safari Hunt, I've noticed the hits were slightly off to the right, indicating some level of input delay introduced by these newer CRTs that borderline makes the game unplayable. Then yesterday I had some time to spare and ended up quickly disassembling Gangster Town and manually adjusting the HCounter readings (by subtracting a fixed amount) to offset the delay introduced by the TV and it did work surprisingly well. Gangster Town shows on the screen where the gun was pointing, making it easier for me to find the appropriate offset value (in my case, $0c). That being said, I believe the 20-30 usec is the average time the gun will "see light" on each line. The connection from the light sensor to the TH pin goes through several amp steps and TTL level converter, which probably introduces an extra delay. @Maxim, now that I have a proper system (I've been wanting to grab a full system with console and CRT for years) I will be more than happy to run homebrew test programs if you need. |
|
|
Posted: Wed Mar 15, 2023 8:48 am |
I remember I had some similar problem with a CRT that had a DNR (Digital Noise Reduction) system. I turned that off and it disappeared. |
|
|
Posted: Wed Mar 15, 2023 8:26 pm |
I've tried playing around with the TV service menu (there are hundreds of parameters you can change) but so far I couldn't find anything other than geometry settings. The code change to adjust the HCounter reading is working really really well, so I'm quite happy with this. |
|
|
Posted: Thu Mar 16, 2023 1:59 pm |
I didn't have to use any service menu, it was a key on the remote to switch that off IIRC... | |