+cubanismo Posted August 11, 2020 Share Posted August 11, 2020 Seeing JagZombies 2 coming inspired me to order a Sega Light Phaser and wire up a prototype-quality adapter using leftover parts from my VGA cable and BJL adapter projects: Using an XOR gate to invert the light pen signal before feeding it back to the Jaguar. Seems to work pretty well with @Matthias's balloons demo, but the gun has some trouble near the center of the screen (Seems to be impossible to target the middle ~10-20 pixels of the screen, it jumps back and forth between either side in those areas). Anyone done anything else on the SW side since this thread? Everyone seemed to be all excited, then it looks like nothing came of it. I love light gun games, so I was going to try to write up a little bit of code that handled things besides over-saturated screens (Yes, by adding back the cursed flashing). I've also been considering ideas for two-player (Two light guns plugged into one controller port, switch between them with a gate on the adapter when the trigger button is pressed, with the console ensuring the switch doesn't happen too fast for it to sample by using one of the joystick select lines as a semaphore of sorts). I think this is roughly how Lethal Enforcers worked on the SNES, which my brother and I loved. Player 2's gun was plugged into player 1's gun, which in turn plugged into the console. Poor player 2's gun would get starved IIRC if player 1 was shooting too fast. 1 Quote Link to comment Share on other sites More sharing options...
+cubanismo Posted August 17, 2020 Share Posted August 17, 2020 (edited) On 8/11/2020 at 9:05 AM, cubanismo said: Anyone done anything else on the SW side since this thread? Quote *crickets* Guess not ? I've written a little mini-library of code to handle lightgun input based on the description of how things work in this thread and my own analysis/testing. It doesn't have the issue I had with balloons where I can't target the middle of the screen (I suspect @Matthias used roughly the same algorithm I came up with, but likely hard-coded PAL values? I think in theory this would explain the problem). I've posted the code here: https://github.com/cubanismo/bullets So far, it's just a little demo that prints the lightgun coordinates on screen and draws a pixel where the gun is pointing, making it a very crappy, black-and-white version of Mario Paint for the Jaguar that uses a lightgun instead of a mouse. I'd like to extend it into a full demo that lets you shoot bullet holes into an arbitrary bitmap background image. I have some more coding to do there, but I wanted to share it here as-is for a few reasons: It'd be good if someone using a PAL CRT + lightgun could try this out, potentially tweaking the hard-coded calibration variable (See lightgun.s XXX comments) as needed. I was hoping someone could check my math: As noted, there's an arbitrary calibration value in the code right now that adjusts the theoretically-correct X coordinate of the lightgun to make it line up with the screen in practice. I don't know why this is needed. It doesn't fall out of the math I came up with based on my current understanding of the Jaguar's lightgun hardware from the comments in this thread and a revisionist interpretation of the Jaguar docs. I'm pasting a slightly modified version of the massive verbose commit message from the github repo below explaining the algorithm for analysis/feedback. However, if you prefer, just look at the heavily-commented 68k assembly code in lightgun.s for the more-optimized version. Quote Convert lightpen registers to framebuffer (x,y): The math used is as follows: LPH = latched HC value, NOT horizontal position in pixels, as the manual states. LPV = latched VC value, more or less matching the documentation. Given LPH is is defined as a sampled value from the HC register, we know it counts from zero to the value in HP, or the horizontal period register, which is the number of pixel/video clock cycles in HALF of a scanline. When it wraps for the second half of a scanline, the 11th bit is set, so the first task we have is to reconstruct the full-scanline pixel clock count from LPH: raw = LPH hpcc = raw & ((1 << 10) - 1) if (raw & (1 << 1)) hpcc += HP (hpcc: "Horizontal Pixel Clock Count") However, we can't read HP (It's write-only). Luckily, HP should be either NTSC_HMID or PAL_HMID, so we can deduce it by checking the NTSC/PAL config bit. Next we want to convert from video clock ticks to a pixel count, so we divide by the PWIDTH field of VMODE. The current code always assumes PWIDTH4. This should give us a scanline position in pixels. Now we need to map that pixel count onto the framebuffer used by the object processor. This requires a lot of input variables, so I've simplified as mentioned above by assuming a framebuffer centered on the scanline horizontally. The object processor's BITMAP object type contains the field XPOS, which is defined as an offset in pixels from the start of the line buffer. OK, but where is the line buffer positioned? At HDB1/2 of course! Another write-only register, so back to analyzing startup.s, we see it exports a_hdb, a variable containing the value programmed in HDB1 and HDB2. Of course, a_hdb is in raw video clocks, and XPOS is in pixels, so we need to take care when combining them (Again, assuming PWIDTH4 here): framebuffer X origin = a_hdb + (XPOS * 4) Where framebuffer X origin is in video clock units. How do we get XPOS? We could pull it out of the object list, pass it as a parameter, or just re-calculate it from the framebuffer width in pixels if we make the above assumptions about a centered framebuffer, which is what I've done here. I call this value "xoff4" since it is the value subtracted from the above hpcc value to obtain the video clock offset within the framebuffer. The result of that subtraction is then divided by 4 to obtain the x coordinate within the framebuffer image. fb_x = (hpcc - xoff4) / 4 Or that's how it *should* work in theory. In practice, I have to skew xoff4 a bit to the left: xoff4 -= 170 ... fb_x = (hpcc - xoff4) / 4 ... The vertical position is much easier. Just mask off the "field" bit of LPV, divide it by two to get the raw scanline count. vslc = (LPV & ((1 << 11) - 1)) / 2 (vslc: Vertical ScanLine Count) From there, recalculate the YPOS object processor value, which luckily is a raw offset from scanline zero (though in half-scanlines, because everything has to be hard on Jaguar) so the only inputs we need here are the framebuffer height and the video mode middle line, the latter of which is either PAL_VMID or NTSC_VMID, which are also in half- lines. framebuffer Y origin = (VMID - ((fb_height * 2) / 2)) / 2 or, framebuffer Y origin = (VMID - fb_height) / 2 We'll call this value yoff, similar to above for the horizontal offset value, giving us the following equation: fb_y = vslc - yoff And there we have it, (fb_x, fb_y) is where the light gun was pointed in the framebuffer! Simple, right? Yeah... right... Oh, and in case you just want to play with the little demo/test it on your CRT without needing to compile anything, I've attached it here as well: bullets.cof Edited August 17, 2020 by cubanismo Attached the bullets.cof file 2 Quote Link to comment Share on other sites More sharing options...
Stephen Moss Posted August 17, 2020 Share Posted August 17, 2020 On 8/11/2020 at 5:05 PM, cubanismo said: Anyone done anything else on the SW side since this thread? Everyone seemed to be all excited, then it looks like nothing came of it. I love light gun games, so I was going to try to write up a little bit of code that handled things besides over-saturated screens (Yes, by adding back the cursed flashing). I've also been considering ideas for two-player (Two light guns plugged into one controller port, switch between them with a gate on the adapter when the trigger button is pressed, with the console ensuring the switch doesn't happen too fast for it to sample by using one of the joystick select lines as a semaphore of sorts). I think this is roughly how Lethal Enforcers worked on the SNES, which my brother and I loved. Player 2's gun was plugged into player 1's gun, which in turn plugged into the console. Poor player 2's gun would get starved IIRC if player 1 was shooting too fast. Probably because CRTs were on their way out and those old light guns do not work well with LDC screens, plus having to modify them to be Jagaur compatible and lack of supporting game software probably meant people thought it was more trouble than it was worth to peruse it. If regard to getting two guns working if the LP signal is hard wired to latching the counter data that would be tricky, if it relies in the LP signal being read into the JoyButs register then perhaps you could simply read each controller on alternate frames and when controller 2 generates an LP input set the relevant bit of the Controller 2 Joybuts register to trigger the counter latching. Alternatively, if you can read the counter anytime then read it just before the controller read, then perform the controller read, it should take a fined amount of time to perform a controller read so you should not how much to add to the previously read counter value to generate a correct value when an LP input is detected. Again you would need to read the controllers on alternate frames. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.