Thursday, 1 June 2023

Galaxian star field

I've been chipping away at Galaxian as updates come from jotd. It's all-but-finished now, with a few sounds to implement and/or debug on the Neo Geo, and the mystery of randomly disappearing bombs.

I've just finished implementing the starfield, although I realise now I made one mistake that I may or may not decide to go back and rectify. The end result would be practically indistinguishable though.

The starfield in Galaxian (and similar games) is generated in hardware with some rather simple circuitry. A maximal-length LFSR is used to generate - and scroll - the star positions, with some simple combinatorial logic to generate the colours and blinking.

The original (MAME's approximation anyway)

Of course there's no way to replicate that mechanism on the Neo Geo, so I had to come up with a way to implement something similar with sprites. I wanted to be as accurate as possible, and I think I've managed that (almost) except for the blinking pattern (which you couldn't possibly tell anyway).

The LFSR has a period of 131071 (2^17-1) but is effectively clocked twice per pixel which, given a 256x256 pixel virtual display, causes the starfield to scroll every frame. The combinatorial logic generates 252 stars each frame (which of course just repeats every frame). Star colours are derived from certain bits in the LFSR on that clock.

The Neo Geo requires just 16 sprites of 16 tiles each to cover a 256x256 pixel area - IOW 256 sprite tiles. The first step was to generate the stars using the same LFSR and render them in the respective Neo Geo tile, taking into account the relative rotations of both the Galaxian and Neo Geo displays. [I've since realised I made a wrong assumption about the orientation of the Galaxian display, which wouldn't be difficult to fix.]

Once I had the star positions, I had to think not only about the colours, but also the blinking. Fortunately the Neo Geo has an extensive palette which allows up to ~4096 colours on-screen at the one time. This allowed me to use a separate palette entry for each of the 252 individual stars. The only added complication was partitioning the palette entries across those 252 stars. I calculated that each 16-colour palette would be sufficient for one half (left/right) of each sprite. Not 100% efficient use of the palette, but easier to calculate and also code up.

Now to blinking. No prizes for guessing I used colour-cycling. With a unique palette entry for each star, I can blink any/all stars independently. But what algorithm should I use?

Although there are only 252 stars, each of the 16 sprites requires 2 palettes (with 16 colours/palette) for a total of 512 palette entries. So I came up with a 9-bit (Galois) LFSR that effectively selects a random palette entry (star) each clock - though not all entries correspond to stars of course. To blink the stars, I needed two (identical) LFSRs, each clocked at the same frequency, but out of phase. The leading LFSR would blank out palette entries, and the following LFSR would restore them. How long the stars are blanked out depends on the phase difference between the two LFSRs.

I played with them only briefly before coming up with an acceptable solution; the LFSRs are 1/4 of a cycle out of phase, and they're each clocked 4 times per VBLANK. This seems to give a fairly decent emualtion of the starfield in terms of blinking.

Not that anyone will ever notice any of this!

Starfield on the Neo Geo. Can you still tell it's Galaxian?

If I do go back and change the starfield layout (as mentioned above) I'll update with results. In theory it should generate the exact pattern of the original. Blinking will never be the same though.

UPDATE: It took just 2 simple changes to reverse the rotation of the Galaxian screen and re-generate the starfield. However I still can't visually confirm it's the same as the original. But it'll probably stay this way now regardless, as I need to manually render an opaque tile for the display masking sprites. Oh well, I tried...

Saturday, 20 May 2023

Galaxian getting close.

More Galaxian (though not a lot) progress and none on Xevious (again).

I've optimised the OSD layer somewhat and it should be adequate for real hardware (not that I've actually tried it yet). It's doing nothing anywhere near as demanding as Xevious, although I'm yet to implement the scrolling starfield. Having said that, the starfield should be a lot simpler than Xevious, in that I can utilise non-zoomed sprites and use wrap which means a single sprite update each scroll. I'll use colour cycling via palette update to blink the stars so again, not a lot more demanding than what is happening now.

The game is playable except for the few bugs that remain in the transcode. jotd is getting very close though, so it isn't too far off being finished. The big challenge for both the Amiga and the Neo Geo is the background 'swarm' sound effect, which changes frequency as you reduce the size of the swarm. I think jotd is going to take the same approach as will be necessary on the Neo Geo (at least without writing a custom sound driver), namely take a number of samples at different frequencies and play them back at the appropriate time.

No eye candy because it doesn't really look any different, just plays better.

Otherwise, no excuse not to get back to Xevious really...

UPDATE: another drop from jotd and it's looking very close now!

Monday, 15 May 2023

Galaxian looking good now!

More incremental progress on Galaxian when I should be doing Xevious. But time has been short and I'm trying to support jotd as far as possible as he did me during Xevious. He is slowly finding and fixing bugs in the transcode and so it's getting that little bit closer to being finished every day.

One thing I forgot to mention is that I've implemented all the sounds that jotd has ripped and added to the core. Almost trivial thus far on the Neo Geo, though I suspect the "swarm sound" may cause some difficulties on the Neo Geo...

I've implemented the bullets. With plenty of tiles to spare I rendered the bullets in every possible position within the 16x16 grid of the Neo Geo tile. That gives me options if I need to tweak pixel offsets for the nuances of Galaxian hardware.

Looking pretty accurate now,
although the OSD is still a quick hack atm.

Having just said that, jotd has made the decision to eliminate the above-mentioned hardware nuances (pixel offsets for different sprites) together with the corresponding core code that caters for them. Not much point adjusting sprite coordinates in the core 68K code, only to subsequently reverse them in the OSD layer.

It's time for me to implement my hacked OSD layer "properly". I'll have to implement dirty tiles and defer the background tile update to the VBLANK ISR as well us tidy up the sprite code.

Wednesday, 10 May 2023

Galaxian sprites working

Got the sprites working during lunchtime today. Positioning is only a rough approximation atm. When I re-write the OSD layer "properly" I'll make sure it's all pixel-perfect.

Tiles and sprites all done!

They work on the attract screen, but not in-game. It's a transcode issue, not an OSD issue.

Next is to implement the bullets. I'll have to manually render the tile(s). I've already added palette entries for them.

Tuesday, 9 May 2023

Galaxian on the Neo Geo

Galaxian is coming along nicely! I've only implemented a few very quick hacks to the Xevious OSD layer on the Neo Geo and I can already start and play a game. The tilemap layer is implemented, CLUTs correct, and scrolling working except the offset for the visible display needs tweaking.

Can start and play a game (on FREEPLAY)

Not implemented are the sprites; dive-bombing aliens and bullets & shots. And sound, though it appears jotd has already ripped the sounds and added a few to the Amiga port. Using NGFX SoundBuilder it wouldn't take a lot of work to add them to the Neo Geo as well.

An interesting issue with the Neo Geo implementation. On the MVS the BIOS handles coins and you can only query the BIOS as to whether or not there are sufficient coins inserted to start a game. Galaxian, OTOH, reads a raw input port and debounces it over 4 samples. Thus I will need to use the BIOS routines and effectively "pulse-extend" the coin input to allow Galaxian to detect it.

I'm also considering the possibility of supporting a horizontal monitor for Galaxian... I think it can be done - that'll be interesting!!!

UPDATE: Have implemented 'pulse-extend' for the coin input, and can now coin up.

Have implemented all dipswitch settings except SERVICE MODE and my custom cabinet mode.

Have implemented Galaxian sprites, but so far I can't get them to appear on the screen!?!

Wednesday, 3 May 2023

Xevious, Donkey Kong and now Galaxian on the boil...

Still yet to work on Xevious as there is another distraction now - Galaxian!

jotd is working on a largely programmatically-transcoded version of Scott Tunstell's very comprehensive RE of the arcade Galaxian. He has the game running on the Amiga, sans sprites, already!

I have updated my tools to rip the graphics and palette, and rendered the Neo Geo tiles. I've created a skeleton project for the Neo Geo, added some stub functions for the OSD functions implemented by jotd, and it builds. The splash screen displays (using the Galaxian font) but the game resets the Neo Geo as soon as it runs.

Splash screen with arbitrary colours

I won't be doing a huge amount of work on this in the short term; just enough to get the game running and displaying to give jotd an idea of how the OSD he has defined is working. Then I'll let him finish off the transcode before I polish it off on the Neo Geo.

Xevious is still beckoning of course...

UPDATE: Galaxian may be put on hold. jotd is using a lot of PC-relative addressing which breaks when I specify .text and .bss sections for the code and data respectively... so it may depend on whether or not he's interested in supporting the Neo Geo...

Friday, 28 April 2023

Even less Xevious happening...

Scool holidays means even less time to work on my projects. Not that I've been particularly motivated lately. Xevious has been a no-go for a few weeks now... it's getting ridiculous now - I need to release a new Beta with better sound before everyone forgets all about it.

I have done some more work on Donkey Kong though. I think I've finished converting all the tilemap accesses to osd_w_vram calls. I should now be able to fill out the routine to actually update the Neo Geo sprites, and then remove the call that renders the entire tilemap every VBLANK.

I'm not too keen on how I did the transcode all those years ago. I was more concerned with mirroring the Z80 register usage than optimising for the 68K registers. Even then I don't think I was entirely consistent. As a result, it's a bit of a dog's breakfast. I've already re-allocated some registers in the routines that I've been updating for vram access.

When I finish Xevious and start on the transcode in earnest, I'm going to go back to the start and work through all the existing code. There's a few other areas where I diverted from the way the original code works when I really shouldn't have. I want to fix all that up - I'm much happier with the way Xevious turned out, and want to use that as the template for my transcodes going forward.

This week I'll make a concerted effort to finish off Xevious and release a new Beta, even if it is just the sound. There's really only one last bug that I need to find - spurious Toroids (flying objects?) destroyed when firing continuously.