Tags

Related Posts

Share This

Shooting Squares

When I was a kid, I didn’t get a lot in the way of overpriced add-ons for my Spectrum. A joystick was considered essential, so I got one of those (Not essential for me – I preferred the keyboard – but my mother wanted to play Gauntlet without having to sit on the floor) but I never did get a Multiface. One add-on that I did manage to whine annoyingly enough to get given as a Christmas present, though, was the Magnum Light Phaser.

It came with a half dozen games, all of which had something of interest. Operation Wolf being the daddy, of course – in spite of the slow-down every time you fired, it was still highly entertaining – but all of the games were fun for a while.

Of course, six games can only last so long. It was a shame, then, that just about bugger all was released for it after that, and that it didn’t come with any sort of clue as to how to write any software for it. I’m sure we’ve all had an idea for a cool game that could use a light gun, but had no way of doing anything with it.

Well, I’m going to change that for you right now. This here is a little demo program that lets you point and shoot all you like. It works just great on the real, live hardware, and the emulators I’ve tested it with are RealSpectrum, EmuZWin and Spin. Don’t bother using Spin if you want to score anything though, because it won’t work properly – none of the light gun games work properly with it. (Although Spin was absolutely vital for development, what with having a very nice built-in assembler and all.)


First thing’s first, I’m going to explain how the light gun works. It’s fairly straightforward – there’s a sensor in the gun that is geared to detect brightness. That’s why our screen is mostly black – the white square is the target, and when you point the gun at it it senses the brightness. That’s why it also counts as a hit when you shoot the border, so in your projects remember to set the border to black.

I’m afraid there’s a bit of assembly in here, so mind your fingers:

LABELONE:
	ld bc, 65533
	ld a, 14
	out (c), a
	ld bc, 49149
	ld a, 32
	out (c), a
	ld bc, 65533
	in a, (c)
	and 32
	cp 32
	jp z, labelone

	ld bc, 49149
	ld a, 16
	out (c), a
	ld bc, 65533
	in a, (c)
	and 16
	ld c, a
	ld b, 0
	ret

The first half of that checks if we’ve pulled the trigger. If we haven’t, it loops until we have. And when we have, it checks whether or not we’ve hit a target and returns the result to BASIC. So from BASIC, then, we can call this routine with a USR and we get a number back – if it’s 16, then the player’s shot the target. If it’s not, then they haven’t.

Now, what we might just need for more interesting projects is to split this into two routines, like these…

Check For Trigger Pull

	ld bc, 65533
	ld a, 14
	out (c), a
	ld bc, 49149
	ld a, 32
	out (c), a
	ld bc, 65533
	in a, (c)
	and 32
	ld b,0
	ld c, a
	ret

Check For Hit Target

	ld bc, 65533
	ld a, 14
	out (c), a
	ld bc, 49149
	ld a, 16
	out (c), a
	ld bc, 65533
	in a, (c)
	and 16
	ld b,0
	ld c, a
	ret

…and that way we can wait for the trigger to be pulled from BASIC, at which point we can do something else before checking if a target’s been hit.

PseudoBASIC

	LET A = USR (trigger pull address)
	IF A AND 32 THEN (trigger is pulled)
	LET A = USR (hit target address)
	IF A AND 16 THEN (target is hit)

Of course, you’ve probably realised that just shooting a white square is going to get kind of old kind of fast. But there’s things you can do to get around that – like combining the light gun with the old movie player routine and coming up with something like this: