Monday 6 November 2023

And that's probably it for Vulgus!

I've decided to put Vulgus to bed.

After a fruitless session, I've exhausted my interest in finishing the RE. Given that I don't have plans to transcode it at all, the ROI for the remining sections is miniscule.

The few remaining 'free-standing' variables are flags and timers for spawning various alien types. I could probably stare at it long enough to come up with some sort of meaningful name for them, but I'm not going to.

The various alien object tables have indeterminate member variables that are almost certainly related to movement, whether they be timers, velocities and/or accelerations, or movement table pointers. I've spent some time trying to nail them down, but the different object table structures for different aliens makes it a nightmare.

Finally, the data structure used to generate and keep track of the background map is missing a whole heap of values, including pointers and offsets into various tables of meta-data, tile codes and colour palettes. I've tried a few times now to decypher it all, but it just leaves me with a headache.

I've thought of simple patching/lifting the source for the purpose of generating the full map, but even that seems overwhelming atm. I think I've simply burnt out on Vulgus.

That's it for Vulgus... for now at least.

I will continue to play it and hopefully (finally) see the titular Vulgus for myself. Part of the quandary I have is that I have no idea how the elements of the final boss look or behave, which makes it difficult to RE the code related to it, and I don't want to spoil the game for myself by cheating or watching a YouTube video.

Let's see what takes my fancy next...

You'll want to collect 'E' as well!

Another session, another few variables decoded (RE'd). Most of the 'free standing' variables have either been decoded, or I have at least some idea of what they do - just not the specifics. A surprising number of seemingly unused variables in the code; initialised but no cross-references to code that reads them. Setting watchpoints in MAME tends to confirm too.

There is a timer for spawning the non-firing or 'kamikaze' aliens in the game (spinning star-discs, black blocks etc) which is initialised after every spawning. However the value from which it is initialised is itself never initialised, other than being zeroed at program initialisation time. As a result, the non-firing aliens tend to come thick and fast in the game!

Related to this; formations (worth big points) consist of either 5 or 6 aliens as specified in a table entry. However the game will 'give up' waiting for 5/6 free slots in the object table after while and just spawn as many aliens as it can given the free slots - which means you may have to kill less aliens to get the bonus formation points! After all these years playing it, I never noticed this!!! 😶

I've finally detailed the result of missing the letter 'E'. Again, the manual suggests an immediate effect when it appears, however it is when you fail to collect it that something happens. In the case of the letter 'E', without going into excruciating detail because it is a little complicated, missing it increases the frequency for spawning of firing aliens (only). Not that it would be possible to increase the frequency of the non-firing aliens because of the abovementioned feature/bug. And like the letter 'D', at some later stage it becomes a moot point because the area will start with maximum frequency anyway. It has no effect on the big/mega aliens either.

Nothing to do with 'E', just eye candy for attention

Aside from the handful of 'free standing' variables mentioned above, it's mostly variables in the map and object tables that haven't yet been fully RE'd. And these of course relate to the two outstanding areas I mentioned in the last post, namely map generation and alien movement.

TBH I'm at the stage now where I just want to be finished - I'm thinking too much about the next project. However I think if I tackle the alien movement next it'll unlock a lot of the outstanding object variables, if not all. That'll leave just mostly map generation. And it would be nice to write something to display the entire map...

Thursday 2 November 2023

Parallax Scrolling!?!

Another quickie; cracked a few more variables in the last session which revealed an interesting if subtle detail to the game.

I had previously deduced the meaning of one variable to be the amount by which the background had scrolled left/right (dy), so it could be used to update, for example, the map and objects superimposed on it. Turns out that whilst I was close, I wasn't quite right.

There are actually two (2) variables updated when the ship is moved left/right; the abovementioned and another variable, updated by a slightly different amount. The other variable is actually dy for the background and ground-based objects and the first variable is dy for airborne objects, such as bullets and aliens.

What this means is there is a subtle parallax scrolling effect when moving the ship left/right! It is hard to notice when playing, but the effect is that your bullets (and certain aliens) will move left/right slightly less than the background moves.

[I should note that I use dy for left/right movement rather than dx because the screen is rotated, and the offset is made to the sprite register that is documented as the 'Y' register. Ultimately it's less confusing to reference the hardware than the physical orientation of the monitor, especially if the hardware is used for multiple games, some horizontal!]

It is getting harder and harder to progress, but I'm yet to finish a session without making at least some progress. A few variables seem to be initialised but never used (like the letter 'S'), but it's not straightforward to prove they're never used. In some cases the best you can do is set a watchpoint in MAME and play the game...

Here are the areas I have visited but have yet to complete:

  • Background map generation/rendering; the data appears to be packed into blocks of meta-data
  • Alien movement; alien movement is all table-driven
  • Planet/Area data that affect difficulty; some of them are simple spawn timers or alien types but I haven't decoded every single parameter as of yet
I think that's about it.

Monday 30 October 2023

'S' is for... nothing!

Just a quick one... still progressing on Vulgus, chipping away at the unknown variables.

Indications are that the letter 'S' does... ABSOLUTELY NOTHING! I can't find any cross-references to it in the code, other than initialisation and updating a counter (max=4) when one disappears off-screen. A watchpoint in the MAME debugger doesn't reveal any accesses to the variable either.

Somewhat puzzling given that the other two letters do affect game play.

Random Vulgus picture for attention

I've been working on ROMSET #2 in MAME, so I decided to load up ROMSET #1 and see if that had any references to the variable. Took quite some time (two sessions) to get to the point where I could analyse the code in some detail - because of all the jump tables used in the game - but couldn't find any other references. Similarly playing the game didn't trigger the watchpoint.

I did however notice one difference in game play logic, and there are more. Interestingly ROMSET #1 allows 10-character names in the high score list, whilst #2 is only 3 characters. When I've finished the RE I will go back and analyse the differences in detail.

Monday 23 October 2023

It's official, collecting the letter 'D' is good!

I haven't posted in a while but I have been making quite a lot of progress on the RE.

I would say 90-95% of the code has been commented now. Most of the unknowns have to do with the gameplay 'AI' - variables that affect the difficulty of the game, and also a few areas of functionality that I know the exact purpose of, just not the specific mechanics. Those include unpacking background map data, and handling the movement patterns for the aliens.

The RE is somewhat complicated by the fact that there are multiple object tables; one for enemies that fire, one for enemies that don't fire, and one for the 'large' enemies - and these tables don't have the same structure! 😣 So when commenting the code, I need to remind myself which type of alien the routine is operating on. Quite annoying because they are relatively small, and it would have been perfectly acceptable to use the same structure even if some members were unused.

But I still seem to be able to make some progress each session; I think I've hit a wall but then make a breakthrough with a few variables. It's just a matter of continuing to chip away here.

On the subject of collecting 'D' from an earlier post, I can say with absolute authority that it is beneficial to the player. Here's what the Vulgus manual on Capcom Arcade Stadium on the Nintendo Switch has to say about it:

"Increases enemy firepower when it appears. Collect it to stop the effect."

Technically though, it's not about collecting them, but rather not failing to collect them. Each map area starts with a variable denoting the maximum number of enemy bullets allowable on the screen at any one time, with an absolute maximum of 6. Nothing changes when 'D' appears, but failing to collect a 'D' will increase that count by 1. Of course at some point in the game, it becomes a moot point because you'll eventually start the area with the maximum (6).

Not a 'D', but here's an 'E' just for attention

'E' & 'S' are related to other variables which I haven't examined in detail just yet.

There's also a bonus that appears at 150,000 pts and then again at every 100,000 until the last one at 550,000 pts. After that it doesn't appear again. I need to understand more about the actual bonus at this point - I've never seen it myself and was completely unaware of its existence.

I've also learned about the titular 'Vulgus' boss enemy which, again, I am yet to encounter in my own gameplay. I'll need to practice a bit more  - I'd like to get there without cheating - but I need to get my MiSTer repaired first. That's on the to-do list for the very near future. Or maybe I should install my Vulgus PCB in the lowboy and fire it up!?!

Sunday 8 October 2023

Slowly taking shape

I've reached the point in the RE where the rate of progress is beginning to slow. On the bright side, I've probably commented about 75% of the code thus far, so I have a good idea of how it's all working, if not some of the finer details. What's remaining is mostly entwined with what I call the 'AI', or gameplay logic.

Last session I was getting a little frustrated with the lack of progress, but a few small gains and then actually taking a step back to look again at the bigger picture improved my perspective somewhat and, as a result, some of the higher level unanswered questions suddenly seemed to click into place.

I didn't get a chance to work on it again today, but after working out all the hardware sprite allocations I now know what I need to do next; identify how the various aliens are allocated to the different object tables. That should in turn assist in RE'ing some of the remaining variables, and the mystery of the letters!

More to come on that subject...

UPDATE: I'll just tack onto the previous post...

Really getting into the nitty-gritty now. I have a much clearer idea of object table and sprite allocation after tonight's session. One structure I thought was an object table actually isn't, though I don't really have any idea what it is at this point.

There's quite a bit of table lookup happening. I'm working on the data structures and routines for the (up to 9) objects stored at $E200, which include the 'normal' smaller aliens buzzing around. I've identified the STATE, TYPE, X,Y and DX,DY structure members, plus what I believe are the TIMER and COUNTER members. Other members I'm still not sure of. I've identified types/routines for two (2) specific aliens now, the others should be relatively straightforward to identify one I work through the code.

There's quite a bit of table lookup in the logic for handling aliens. This is for both movement and other gameplay-related logic. It's going to take quite a while to work it all out, and perhaps there are sections I never will.

I can say that collecting 'D' is at least beneficial to the player in one aspect... more I can't say yet.

Thursday 5 October 2023

Answers and Questions

More progress tonight and more questions than answers.

I started looking at the 'object' data structure used in so much of the code. Byte $00 appears to be the state, and $01-$04 appears to be the (16-bit) object X and Y coordinates. The MSB of the coordinates are copied to the sprite registers. Or so I thought...

Turns out that is true only for the player bullets, thus far at least. The player bombs have different coordinate data AFAICT. This doesn't bode well for the other objects, and it may well be that each object type has its own data structure. Sigh.

One interesting discovery... player bullets are rendered as foreground tiles - not sprites! Each bullet can potentially span 6 tiles, so there is a lengthy process of calculating the foreground video RAM address, and a lookup of tile codes just to render a bullet. The bullet object structure stores the address each time it is rendered, so it can be used to wipe the bullet when it is moved/destroyed. Phew!

And it gets even stranger - it doesn't seem to call these routines in attract mode!?!

More to come...

UPDATE: I was curious about the bullet sprite vs tile issue, so I looked a little further into it...

During attract mode, the bullets are rendered as sprites, using hardware sprites 4-7.

During gameplay, the bullets are rendered as foreground layer tiles.

Here's the kicker though, and this threw me for a bit... when you coin up and start a game, and 'READY' is displayed on the screen - all handled by the 'gameplay' state machine, as opposed to the 'attract mode' state machine - the bullets are also rendered as sprites! As soon as 'READY' disappears, it starts using tiles!

What's more, you can fire (white) bullets when 'READY' is displayed, but as soon as it disappears, so do all the on-screen bullets! And any subsequent bullets fired are pink!!!

Why?

I haven't looked further into it, but I have my theory.

Firstly, during attract mode and when 'READY' appears, there are foreground tiles in the gameplay area (VULGUS title and READY text), so any bullets rendered as tiles would obliterate those graphics. In attract mode, the (sprite) bullets run behind the title and text, and even behind the score at the top of the screen. In gameplay mode, (fg tile) bullets disappear before reaching the score.

Secondly, with (only) 24 hardware sprites, I suspect the game designers wanted to make more use of the sprites for enemies and their bullets? Otherwise - why would you do it??? Presumably (I'll deduce this later) the attract mode gameplay screens are explicitly designed to use less sprites than the game uses at its most difficult!?!

I've never seen anything like this before! 😲

Tuesday 3 October 2023

Vulgus RE progressing a little better than I initially expected!

Back from holidays (boo!) and although I haven't posted again, I've made quite a lot of progress over the last couple of weeks.

First I'll admit I haven't gone back to look at the map decoding - there was plenty to do in the rest of the disassembly that kept me occupied. Some of the aforementioned numerous variables have been identified, though there's quite a lot that I still haven't deduced, as many of them are only used in one or two places, and likely for enemy AI - they're always the most difficult!!!

Having said that, a huge portion of the code has at least been commented to a degree, if still missing some key elements of data. Aside from the map data, there appears to be a homogenous 16-byte 'object' data structure for every, well, object in the game, from the player ship, to bullets & bombs, and aliens. I've figured a few of those bytes out, and hoping I can focus on the rest now that I'm at home and have access to larger & multiple screens, notepads etc.

There's a not-insignificant amount of code for a few unobtainable self-test screens, which I've been able to see run via patching a few bytes. They threw me for a bit as I couldn't reconcile what the code was doing with what I've experienced in the game. TBH they're nothing more than a curiosity and not worth in-depth RE.

Speaking of non-insignificant amounts of code; the 'instructional' sequences showing the point scoring system is quite a chunk in its own right. I've identified the state machine responsible for the attract mode sequences and have documented parts of it, but not all of it.

Part of the instructional sequence - quite a lot of code required

My overall impression is that the code isn't exactly the best I've come across; Xevious was far neater and more efficient. There seems to be quite a bit of duplicated code, and routines called from multiple places when you wouldn't expect they would need to be. I think some of the logic is a little hap-hazard in the way it was put together. And the game actually looks a little un-finished, though those more familiar with the game probably won't be surprised to hear that. Aside from evidence in the gameplay, things like branches between different routines that are identical tend to support this theory.

And finally for this post; there's the debate over whether collection of the letters 'E', 'S' & 'D' actually help or hinder the player. I've found the code that handles this, though I haven't completed the RE so I won't say anything more just yet other than to note that initially, I thought them completely benign! That was because the code that 'collects' them doesn't actually do anything (as opposed to the code that collects the 'POW' pickups). However further analysis revealed that the code actually tallies how many you've MISSED, rather than how many you've collected!!!

My immediate focus will probably be on deducing all the elements of the 16-byte 'object' data structure - that should help identify some of the outstanding data variables. As I said, I have a few worked out thus far, and have guessed a few others, now it's time to nail them all down!

Saturday 23 September 2023

Holiday project - Vulgus RE

Long time no post!

Truth is I haven't had the time or the motivation to work on any Retroports projects for the last few months as work and Real Life have both ramped up significantly. The good news is that although work has been a lot busier, I have been working on FPGA design and that has me thinking more about potential projects for MiSTer. But I digress...

For now, I've brought my laptop away on holidays and needed a non-development project to fill in my down time - usually later in the evening - and have decided to RE Vulgus. Vulgus is perhaps a little lesser known title, Capcom's first arcade game in fact, and although it didn't set the world on fire, it is a sentimental favourite of mine as I played it quite a bit back in the day.

MAME screenshot

The game is a vertical shoot-em-up and (the game) runs on a single Z80; fixed foreground (character) 2bpp layer, 4-way scrolling background 3bpp layer, and 4bpp sprites. There's a 2nd Z80 for sound, and a pair of AY-3-8910 sound chips. Nothing exotic about that configuration.

I've spent about 5 nights thus far doing RE and have made reasonable but not spectacular progress. There do seem to be quite a lot of variables and I must admit I've hit the hard stuff a bit earlier than I generally do in these exercises. I've deduced the program architecture, which is remarkably similar to Galaxian and Scramble - almost to the extent that it suggest some sort of prior/shared knowledge. I haven't read the history of Capcom in any detail, but it is interesting how alike they are.

In a nutshell, the game runs from the VBLANK interrupt, queuing low-priority commands for the background to process - mostly tasks like foreground-layer output and score calculation. The background simply runs in a tight loop waiting to process commands, while the interrupt runs a hierarchy of routines called in sequence via jump tables, with variables keeping track of which routines are to execute next interrupt. Scott (Galaxin/Scramble RE) referred to them as 'scripts', they can also be thought of as 'state machines'.

After hitting routines in every state that manipulate varying amounts of yet-to-be-deciphered data variables, I decided to turn my attention to the game map. Even that appears to be more complicated than I'd hoped; possibly stored as meta-tiles and decoded on the fly one row at a time. I think I know where the data is stored, I just need to do more work to confirm it.

In order to assist with the RE of the map, I went back and created the graphics conversion tool that I do for every project, that allows me to render palettes, CLUTs, tiles and video memory. It's not 100% accurate, but close enough; in fact the one layer that is 100% is the background layer! My tool has been hacked from project to project over the years, and was becoming quite unweildy, so I also took the opportunity to tidy it all up and simplify the process a little. The next RE project will be a bit easier again now.

Next task is to return to the code and work out a way to render the entire map, as I did for Xevious (although I was far from the first to do that). I'm pretty sure I'll be the first to do it for Vulgus though.

Whether this effort ultimately results in a transcode is not clear atm. It does have the 16x16 background layer tiles though, which make it a lot easier to port to the Neo Geo, especially with the scrolling.

UPDATE: some progress with the map decoding/rendering. I think I've identified the tables and live pointers for the map meta-tile data, map tile data and map palette data. There is a distinction between 'planet' and 'area', and I think you can travserse the entire map 3 times before it resets?!?

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.

Sunday 16 April 2023

Not much Xevious happening...

Currently finding it difficult to work on Xevious due to other commitments, but I should have some free time in the coming week and hoping to be able to release a Beta by the end of it.

In the mean time I've been doing bits and pieces on Donkey Kong, updating all the tilemap accesses so they are done via the OSD layer. Not quite as efficient as simply writing to video ram, but a lot more flexible and allows the choice of either on-the-fly updates or, for example, dirty tile updates during VBLANK. It also makes it much easier to rotate the screen, which I am planning to support on the Neo Geo. I don't think the Neo Geo or Amiga will have anywhere near the performance concerns of Xevious for this transcode.

Not being "in the zone" for Donkey Kong does makes things a little more difficult. There are things I've done in the code that I am now questioning; things that will take more time to analyse. It has been around 10 years since I touched it last... but I can't afford investing that time until Xevious is done and dusted.

Regardless of the countless changes, it is still mostly working. I've broken the intro animation where Kong has kidnapped Pauline and climbs the ladder before stomping on the girders - it loops endlessly. But the attract mode demo runs - for a while before rebooting. It's annoying that I can't simply coin up and start a game to test my OSD changes, but it's nothing to be overly concerned about atm.

Hopefully my next post will be announcing the next beta release of Xevious!?!

UPDATE: I fixed the broken intro sequence; I had recently 'optimised' one of the RST routines, not realising that some callers relied on a side-effect (setting the HL register pair). I can coin up and start a game, but there are multiple gameplay issues now.


Wednesday 12 April 2023

NGFX SoundBuilder

More RE - this time Blastar's NGFX SoundBuilder Z80 ROM.

I wanted to learn more about how the Neo Geo sound works in general, and how the SoundBuilder Z80 ROM works in particular. Together with the Neo Geo Development Wiki, the YM2610 (incomplete) datasheet and some sample driver code, I was able to decypher most of it today.

Pretty neat how Blastar has designed his driver to cater for most situations. It provides 5 channels of ADPCM allocated in a round-robin fashion for short samples, a 6th channel that can play background sounds (optionally looped) for longer samples or voice/music, and a 7th independent channel (again, optionally looped) that can also play background sounds. On the NGCD, the 7th channel is replaced - seemlessly - with CDDA tracks.

The way it works is that the driver code itself doesn't need to change, just the data table(s) at the end of the ROM. One for the (optional) eye-catcher, and one for the game sounds. After you insert the samples into the GUI and allocate channels, it produces a Z80 ROM image and accompanying PCM data ROM ready to go for either cart or CD systems.

Now that I understand how it all works internally, hopefully I can get the sound working in Xevious without any glitches sooner rather than later.

Monday 10 April 2023

Sound complications holding up Beta 2 release

Been quite a while since my last post. There are a combination of reasons, but primarily it's that work has gone from 1 to 100 and kids' soccer season is in full swing. And I also have to admit that I'm just a little bit over Xevious now.

However, I have still been working on the next Beta release when I can. The particular issues that remain include sound, and artifacts that only appear on real hardware; so working on either isn't possible during lunchtime at my desk. That hasn't helped matters either.

I had a theory on the artifacts (aka "sparklies") but that hasn't panned out. I've decided - for now at least - that I can live with them. Nothing that a crappy composite picture won't mask anyway! Maybe sometime down the track when working on other projects I may get another insight?

The sound isn't proving to be going well either. I re-allocated some of the sounds to make use of ADPCM-B on the cartridge-based systems, and CDDA on the NGCD. This allows me to mix the Solvalou background 'tune' and the Andor Genesis sound. It was also supposed to simplify some of the logic that calculates when to stop certain sounds.

However it seems to run amok fairly frequently now, sometimes playing sounds when they shouldn't and sometimes muting sound altogether. I'm yet to actually confirm, but I'm fairly certain it's to do with the 68K writing sound commands faster than the Z80 can process them. Of course the arcade code just writes sound commands whenever it needs to, and I have no control over that. It won't be trivial to solve...

These issues aside, the Beta is all-but-ready for release. A few minor enhancements/fixes that jotd has discovered during the Amiga port, and I'm well and truly ready to wrap it all up.

NaggyNaggerson created this awesome 'flyer'
for the Neo Geo version of Xevious

On other news, I've been working a little on Donkey Kong, mainly during lunchtimes at work when I can't work on Xevious for reasons outlined above. I've eliminated all the old macros that didn't really work the way I want them to now, and it's only a little broken! In the process I replaced all the branch and jump opcodes with the gnu pseudo opcodes that automatically calculate the optimum instruction. Next step is to replace all the video/sprite calls with osd_XXXX functions.

Finally, I've been tweaking the Xevious makefile and project directory structure to accommodate the new sound and ultimately produce a .CHD rather than a .ISO to accommodate the audio tracks. That was a learning exercise in itself. Of course that will need to be carried over to DK as well.

Saturday 25 March 2023

Scoring differences in Super Xevious, and a 'cheat'?

Quite fortuitously I decided to watch a YouTube video of someone playing Super Xevious to see the new objects in action as they were intended - ie. on a non-patched ROM. The video features the score reaching 9,999,990 which is when the game starts to crash...

Halfway through the player was seemingly stuck on the screen where a series of Garu Zakato (large bombs) explode on the screen, releasing 4 Brag Spario. These Brag Spario circle the Solvalou in a display of celestial mechanics (quite impressive), and the player was trying (fruitlessly) to destroy them whilst trying to evade them. My tactic since 1984 has been to sit near the bottom of the screen, where you have more time to react, and they also promptly disappear before they can circle back (in fact, I didn't even know they circled back until I was testing the transcode in 'invincible' mode, and ventured up the screen!)

Brag Spario circling the Solvalou can't be destroyed...

I was wondering why the player hadn't worked this out, and then I noticed they had racked up a massive score! Watching closely, I realised that the score was incrementing quite rapidly each time a Brag Spario was shot; they can't be destroyed, but as they circle they can be shot multiple times.

Checking the code, I noticed each shot was scoring 2,000 points! Wondering why I'd never seen this tactic in Xevious before, I checked the original code - only 500 pts! On EASY setting (as this video seemed to be), on Super Xevious you could earn an extra Solvalou by hitting a Brag Spario just 20 times - easy to do when 4 of them are circling!

Of course this meant I now had to go through all the scoring in Xevious and compare it with Super Xevious... and found just one other case; Sol Towers have been reduced from 2,000 pts to 1,000 pts.

I hope I haven't missed any other subtle changes in Super Xevious...

Today I (also) added support for separate high score load/save for Xevious and Super Xevious on the Neo Geo. It's painful to test on both BRAM and memory card, but all done now.

Now... sound or sparklies???

Thursday 23 March 2023

Super Xevious post mortem.

I've finished testing the Super Xevious transcode additions.

I can only say that Super Xevious was a half-arsed, almost apathetic exercise that couldn't have taken more than a week. The main enhancement is the increased difficulty (table entries), and the new objects don't really add much to the gameplay experience at all. In fact, you should actually ignore all of them except the Galaxian.

*** WARNING: some spoilers here, though they're really not that exciting...

  • Galaxian; technically worth 150 pts but you can't actually hit it. Always spawns away from the Solvalou, and will turn away before you can get under it. Shoots at you though.
  • Jet Taking Off; appears once (area 10). Unique in that it is a flying enemy, but shooting it results in a crater on the ground. You can't get close enough for it to hit the Solvalou before it leaves the screen, Don't shoot it - you have been warned!
  • Jet; the most pointless addition. Appears once (area 15). Flies down the screen at a random (relatively shallow) angle but is completely and utterly benign. It can't hurt you, and you can't destroy it. What was the point?
  • Helicopter; appears once (area 14). Don't bomb it - you have been warned!
  • Tank; appears once (area 8). Don't bomb it - you have been warned!
  • Bridge; appears once (area 15) and is purely cosmetic (completely benign). 'Allows' the Domograms to cross the river. 
And that's it really. To be fair, there was very little free ROM space available (they had to remove some copy protection routines) but I feel they could have done more than that. There are existing object handlers that aren't used - they could have (re)used them too?!?

As I mentioned, the code base now builds both variants.

Wednesday 22 March 2023

Super Xevious transcode complete! Now to squeeze both into the same binary...

 I've finished the Super Xevious transcode, though I'm yet to test the new objects.

To give you an idea of how little code has changed, MAIN has 10 uses of an assembler directive to differentiate code, whilst SUB has only 2. These are mainly for title screen and high score table differences in MAIN, and the data structures in SUB that drive gameplay.

The code for the additional object handlers are included in build options for both, as they simply won't be called when playing Xevious. It's neater than adding more assembler directives, which only makes the code harder to read. And one of the tables in SUB has an extra 6 bytes on the end; one for each new object type. The negligible 'wasted' resources are hardly an issue on a typical 68K system.

My next challenge is to get both variants building in a single binary. The difficulty arises because Xevious is split into MAIN & SUB src (object) files, with a whole bunch of locations (labels) shared between them (so global). I don't really like the idea of reorganising into a single source file (using .include, for example).

What I think I need to do is separate the shared locations (RAM, more-or-less) into their own object file that need only be linked once, and then go from there. Both MAIN and SUB only have 2 entry points, so it's not difficult to duplicate for each variant. And hopefully that's about it.

I'll post my success, or lack there-of, here of course!

UPDATE: SUCCESS!!!

I pulled all the RAM variables out into a separate source file to be assembled once (shared by the two variants). MAIN & SUB are assembled twice within the target, using --defsym OPT_SUPER=0/1 to differentiate the build. Now there are two (s)xevious_reset and two (s)xevious_im1_irq entry points exported. As it turns out, there's no difference between the two irq handlers, so it's possible to just call the original from either variant. As a result, the variant chosen is wholly dependent on which reset function is called!

It wasn't quite that easy; some duplicate routines that I was exporting from MAIN rather than re-implementing in SUB had to subsequently be copied into SUB. And there were a couple of data structures shared between MAIN & SUB that had to be either duplicated, or constructed in RAM.

The binary is larger now, so I had to arrange the objects to preserve my 16-bit branches.

The Neo Geo target now prompts to select the variant from the splash screen.

Selection of Xevious or Super Xevious on the Neo Geo

All that remains now is to support separate high score load/save for each variant.

Then test the new objects in Super Xevious, fix the sound, and the sparklies. And investigate some weird graphics 'sparklies' when shooting toroids... will it ever be finished?

Tuesday 21 March 2023

Amiga performance, Super Xevious ready for transcode, and Donkey Kong updates.

I've been playing around with the (transcoded) Xevious source in order to facilitate better performance on the Amiga. I think I was somewhat successful.

On the original machine, the MAIN CPU gets a VBLANK interrupt and updates the lower 32 (ground-based object) sprites. It then sets a pair of memory variables (aka semaphores) to signal to both MAIN and SUB ROMs to stop spinning and calculate the next frame. The MAIN doesn't touch any hardware, but the first thing SUB does is update the upper 32 (air-based object) sprites and then hits the h/w scroll register. This is why the ground-based objects "shake" a little even on real hardware!

In order to handle this on one processor, the transcode updates the lower 32 sprites and sets the memory variables in the VBLANK ISR as per the original. When MAIN is signalled, it first calls the SUB ROM routine, which updates its hardware (as described above), runs the rest of its code to completion, and then MAIN can complete the frame processing, before spinning again waiting for the next VBLANK.

So SUB ROM gets to update its hardware immediately after MAIN finishes its VBLANK ISR - just like on the original - which comprise the most time-critical tasks. But on the original, it wasn't clear which CPU was finishing its processing first. This could be important, since the last thing SUB does is update the sprite shadow registers with data from the current frame - including data updated by MAIN. HOWEVER, the transcode is calling MAIN *AFTER* SUB has run to completion. And this is still the case atm. It's something that requires more investigation on my part.

One thing the code couldn't handle though, is 'frame-skipping' which is especially important to get the game running at 60Hz on a PAL (50Hz) machine. So I added an 'ISR' for SUB, comprising the two h/w-related routines, and removed them from the SUB main loop. This 'ISR' gets called directly from the MAIN VBLANK ISR.

I then modified the code to treat the 'semaphore' variable (I removed the superfluous SUB semaphore) more like a real semaphore - a count instead of a flag. The result being, if you set the semaphore to 2 instead of 1, it'll call the main and sub routines twice, whilst updating the screen just once. Perfect for adding an extra frame every 5.

jotd has reported better performance on the Amiga, though I can't immediately eplain why, unless excessive lag was causing the two semaphores to get out of sync and delay an extra frame? Regardless, it's getting a lot closer to a release and is certainly very playable on suitable Amiga harwdare now!

The other thing I've done is completed the RE for the new objects in Super Xevious. They aren't particularly exciting, or very complex at all, though to be fair there wasn't much spare memory to play with as the Xevious ROMs were pretty full; they even removed some of the copy protection to fit them in.

At the risk of spoilers, I will say that of the six new objects, 3 are better left alone and one is completely benign! I was wondering why they went to the trouble of adding an object that effectively does nothing, and only appears in one place - until I saw it in action; it's a bridge to allow Domograms to cross a river. Purely cosmetic of course, as there was nothing stopping them from crossing before, but a clever addition.

The bridge 'allowing' Domograms to cross the river.

The rest I'll let you discover yourselves.

It won't take me long now to add Super Xevious to the transcode, at least as a build option. I'll probably add it before the next beta release on the Neo Geo.

Oh and when I haven't had the opportunity to work on Xevious, I've been working on Donkey Kong. I've updated the makefile to bring it in line with the Xevious makefile, including eliminating any need for masquerading. I've also moved the Neo Geo-specific code from MAIN into the now-familiar OSD routines, and also removed some macros that I'm not sure why I implemented.

I still need to fix the mess I made of the graphics routines, where I attempted to support rotation by changing tile/sprite coordinates on-the-fly in the code, rather than writing the original values to shadow memory and converting then or during VBLANK rendering. Once that's done the MAIN code will be 'clean' and even suitable for jotd to work with on the Amiga.

Friday 17 March 2023

Super Xevious coming soon!

I've fixed one bug in the Amiga port (it was copied from my code) but I haven't been working on the next beta or the Amiga version as I should be... instead I've been distracted by the possibilty of adding Super Xevious to the transcode.

To this end, I've been going through the MAIN CPU and naming all the labels; IOW a complete RE except for the comments. And I finished this morning.

In a nutshell, the Super Xevious MAIN CPU code is a super-set of the Xevious code. The only real differences are the addition of six (6) object handlers at the end of the object handler table and the table of flying enemy types. And of course slight changes to the title screen and copyright messages. Some of the copy protection code has been sacrificed for the new object handlers.

Adding the additional object handlers wouldn't affect the Xevious gameplay in any way, so there wouldn't be any need to #define those out for a Xevious build. That just leaves the title, copyright and flying enemy table, which would be trivial.

And as mentioned previously, the SUB CPU code would just require those three (3) different lookup-tables to be selected for each respective build.

Almost too easy!

UPDATE: I've updated my map parsing tool (it's more accurate now and handles the new objects) and have confirmed that none of the previously unused add-object functions in the SUB CPU, and none of the previously unused object handlers in the MAIN CPU are being used by Super Xevious. Thus additions are purely the six new objects. In fact, much of the map, and object counts throughout the map, are very similar to Xevious - it really doesn't play that differently, except perhaps the difficulty level in the new flying enemy table.

I also looked at the execution flow of the original vs the transcode (the context of the VBLANK interrupt and graphics hardware accesses) in light of the 'shaking ground objects' in the Amiga port. TBH I can't really explain it atm, without suggesting that the Amiga is eg. simply updating the scrolling outside the blanking period?!? I need to discuss further with jotd...

Wednesday 15 March 2023

When is Super Xevious not Super?

Today I managed to find a bug that I had inadvertantly caused in the Amiga port of Xevious. So I think jotd will be happy about that!

I also found myself stuck en-route to dinner tonight with about an hour to kill, so I pulled out the laptop and worked through more of the RE of Super Xevious. I started with the SUB CPU and whilst I'm labelling all the routines and variables, I'm not adding any comments, unless the code differs from Xevious.

That's finished now and it turns out that there's only three (3) differences (of any significance) to the two SUB CPU ROMs, and they're all data structures:

  1. The object data (where objects appear in aeach area)
  2. The handler function lookup for various objects (to cater for new objects)
  3. The flying enemy offset table (which determines which flying enemies and how many appear)
The only other differences are a re-organisation of some of the routines (it goes about half-way towards implementing all the handler routines in the same order as they appear in the tables), and inversion of the FREEZE dipswitch setting (and a few extra instructions to handle it).

Since there are no additional handler functions (these functions are only responsible for adding new objects to the object table) - as several object types share the same handler here - my theory is that replacing the SUB CPU ROM in Super Xevious with the ROM from Xevious, will result in Super Xevious playing exactly like Xevious, but with a different title.

I'll try to put that to the test shortly...

UPDATE: after patching 2 bytes in the Xevious SUB CPU ROM to ignore the FREEZE setting and replacing the Super Xevious SUB CPU ROM, Super Xevious does indeed run as Xevious. I only played through Area 1, but it shows that it is at least highly compatible.

What's most important here is the possibility of using a single source base for the SUB CPU ROM for both Xevious and Super Xevious, with assembler directives around the three data structures. Since the transcode doesn't implement the FREEZE dipswitch, that's not an issue either.

Sunday 12 March 2023

A short break, and thinking (too far) ahead.

Just having a few days break fom Xevious before I get back to it in ernest this week.

Over 100 downloads of Beta 1 which I'm a bit surprised about, although I've never had any statistics on any of my projects in the past.

A bit of feedback; some issues with FREEPLAY (which I've already fixed) but no other reports of glaring bugs other than those related to sound. I will be re-arranging my sound channel allocation for the next Beta. I've also done away with masquerading in MAME thanks to Blastar who handed me a better solution on a platter!

Next task though is to take a step back and look at the code from a higher level again, to address the issue of both 'sparklies' on Neo Geo real hardware, and 'shaking ground objects' in the Amiga port. I'm not entirely sure they're related issues, but I have a few things to confirm and try out.

I should also dig into the Amiga code and try to understand more about how it works.

I've started migrated my hosted files to github, starting with my RE listings. I just need to update some of the links on my 'Projects & Downloads' page. Then I'll look at re-homing my transcodes... somewhere...

And of course looking (way too far) forward, I've started to think about what my next transcode will be after Donkey Kong. I think I'm still going to target the Neo Geo as it's one of my favourite systems and so capable. Of course an Amiga port is always on the cards, and possibly a few others, especially as I'm looking to (finally) do a horizontal title. Contenders at this stage are Ghosts 'n' Goblins and Bubble Bobble.

The possibility of doing Super Xevious also occurred to me; identical hardware, identical graphical assets - even though several new enemies appear in the game! It wouldn't require any changes to the OSD layer, only parts of the ROMs transcoded. All 6 devices appear to have different code, though I suspect 90% of the code is unchanged. So probably relatively easy to do, but I'm a bit over Xevious atm...

Screenshot for attention

UPDATE: had a VERY quick look at the Super Xevious disassembly; no doubt it's little more than an enhanced version of the original code, reassembled.

UPDATE: Curiosity got the better of me. I've taken a closer look at the disassembly...

The SUB ROM is not a lot different, but they have re-ordered some of the code and data. All the object data is still at the same location at the end of the ROM though.

I've only taken a preliminary look at the MAIN ROM, but so far it's not a lot different either. I have identified the object hander table; they've added six (6) new objects to the end of the table (rather than utilising unused slots in the table for some reason). The flying enemy table is different too.

It uses the same background map ROMs, so there's no difference in the landscape. What is different is the object data, so things appear in (potentially) different locations. There are (again) 46 Sol Towers (I wonder if they're all accessible this time?) and 4 Bonus Flags in the same areas. I have generated the maps for each area, detailing the locations of Sol Towers and Bonus Flags... I've only looked at the first few... no spoilers!!!

I was wondering whether it would be possible to simply add to the original transcode and produce source that you could build for both variants of the game. The re-arrangement of some routines and data is a little inconvenient, but it may still be possible. It would probably take a few weeks to at least add labels to all the routines and data areas, then check that nothing has changed in the existing code. It does run a bit faster though, so there would have to be some differences...

Now back to the Amiga and also getting Beta 2 out there!

Tuesday 7 March 2023

Bacura; the bane of my existance!

I've tweaked the sound to use APCM-A only and it's all there and working. The only downside is that the rumbling sound of the Andor Genesis neccessitates muting the Solvalou tune since there is only one background channel. Good enough for a beta release...

However jotd gave me a good idea - use CDDA tracks for some of the sounds. Makes perfect sense since the NGCD removed the single-channel ADPCM-B and added CDDA playback - doh! So I should be able to move the background tunes back to ADPCM-B on the cart and CDDA on the NGCD. The nice thing is that NGFX SoundBuilder will make a lot of it transparent - from memory I'll just need to handle mute/unmute and stop loop differently between the two systems. But that's for a later date.

Right now I'm looking for the gameplay bug involving those !@#$% Bacura - bloody trouble-makers! I do know the Solvalou is destroyed (erroneously) by a Bacura, but at this stage I don't know why, or even if the offending Bacura was supposed to be active. Early days yet...

And jotd has reported another possible gameplay bug involving the Zakato. I have had my suspicions that they weren't 100% correct, but they appear so briefly and there's so much happening on the screen it's difficult to tell. But this is the sort of bug I'm happy to leave for the beta testers to discover!

jotd is reporting some good progress with the Amiga port! He has identified and eliminated a major source of flicker in his sprites which should also boost performance a little, so I'm looking forward to seeing that version in action!

UPDATE: Some progress on the bug; in the routine that checks whether the Solvalou has been hit by a Bacura, the value of the Solvalou shadow sprite X register - used only in hit-box calculations - is wrong at the time the bug manifests itself, but seemingly not at other times!

UPDATE: FOUND IT!!! Turns out it had nothing to do with the Bacura, and in fact could have happened with any flying enemy at any time! And the bug wasn't in the core, but in the Neo Geo OSD layer where it was updating the shadow sprite registers (used only for hit-box calculations). Yet another byte/word issue; the shadow X register calculation involves adding #8 to the object X coordinate, and I was doing addq.b instead of addq.w....

Beta1 release imminent!!!! 😮

Monday 6 March 2023

I've heard a beta release (on the Neo Geo is imminent!?!)

Some significant, albeit unexpected progress since last post!

As I mentioned, I've been looking at sound support on the Neo Geo. I'd searched for demo code and downloaded a few, before deciding on one such example. However it had a complicated build process involving lua (whatever the hell that is) and it was broken.

Then I stumbled upon Blastar's NGFX SoundBuilder. It's been a while since I was properly impressed by a piece of software, but this is downright awesome! It has a GUI that allows you to add samples to your project, assign channels and specify looping, and then click on a button and it will generate not only the sound sample ROM, but also the driver ROM in its entirety!

Writing Z80 sound drivers for the Neo Geo has never been easier!

Playing sounds using the driver is trivial; write a single byte (ordinal) to the sound register and it starts to play. A few extra commands to mute and stop looping etc, but that's really all there is to it as long as you have assigned samples to the right channels!

As a result, given that jotd has sampled most of the sounds already, all I needed to do was convert them to 18.5kHz, run NGFX SoundBuilder, add a handful of 68K instructions, and most of the sound is playing on the Neo Geo! I'm still shaking my head at how easy it was. What it all means is that the beta release will probably have full sound (just one sound missing, and a few to test in-game)!

[An aside, I had to produce one of the samples myself - the ground-based object explosion. The complication with ripping it from MAME was the fact that it was mixed with the background tune of the Solvalou. Having RE'd the game - including a lot of the sound ROM - I was able to patch the ROM to remove the tune and, while I was at it, the sound of the bomb that would immediately precede the explosion. Booting up Xevious with the option to record sound to WAV, I waited for the first ground object to bomb, bombed it, and immediately quit MAME.

Loading the WAV into Audacity, it was easy to spot the explosion near the end of the file. I clipped it, saved the clip, and converted it using sox to 18.5kHz mono for the Neo Geo. Trivial!]

Currently I'm just missing the start-up tune -which jotd has sampled and included in his Amiga port - so I'm just waiting for him to push it to his repository. Incidentally, he has just released a preview version of the Amiga port on the EAB site!

Whilst I've been adding sound however, I haven't even looked for the last (known) gameplay bug. I knew it wasn't related to the Neo Geo code, but it was nice to get confirmation from jotd when he saw the same issue on the Amiga port!

So right now, I think I'm just one .WAV file and one bugfix away from a full beta release with sound!

UPDATE: I've added the main theme, so I think all the sounds are there! I did discover that one of the channels isn't available on the NGCD, so I will have to tweak the channel assignment. But at the end of the day, I don't think it'll make any functional difference.

The main theme was a bit of a kludge in the end. The problem is that the original code calls 'play main theme' continually for about 3 seconds (somewhat bizarrely, that's only about halfway through the theme playing)?!? At the same time, it's continually calling 'play solvalou sound'. While the theme is playing, that takes precedence, but as soon as the sample is finished the solvalou sound kicks in. All that is done in the sound driver... with no control or visibility in the main program.

That presents a problem for the transcode, and doubly so on the Neo Geo using the NGFX SoundBuilder, as there is no way of knowing when the main theme has finished. jotd has the same issue on the Amiga port.

The solution - first suggested by jotd - is to start a counter when the main theme is playing, and essentially time it. It's possible because the 'play solvalou sound' call runs all the way through the theme at a nicely predictable 60Hz. It seems to work well!

The only other 'kludge' I needed for sound was to add osd_sound_mute and osd_sound_unmute calls to the main code around the attract mode. This is because the arcade sound ROM actually checks the attract_mode_stage variable itself and handles muting there.

Only one known gameplay bug to go... although jotd did question something he saw in the Amiga port today...

Tuesday 28 February 2023

The sound of silence

Quick update; added sound hooks and osd stub functions for them - but nothing else!

Have been doing a little more RE of the SOUND CPU and it has helped a little, although I won't be needing (or wanting) to complete it. It's a bit more complicated than I first imagined, with lookup tables for which sounds to silence when certain other sounds are playing, for example. I don't think we'll go that far into replicating the behaviour - it has probably more to do with hardware limitations than anything else anyway.

Still yet to look for that last gameplay bug...

...but I was playing it tonight and when the Bacura appeared I was waiting for the bug to manifest itself. It wasn't happening when it should have... and then I realised I had actually fired up the arcade original to check out some of the sounds! I guess it's a good thing when you can't tell the difference between your port and the arcade game (ignoring the obvious aural hints!)

Monday 27 February 2023

Another gameplay bug squashed - potentially only one to go!

Getting really close now - fixed another game play bug! Only one confirmed, and one unconfirmed to go now... (that I know of!)

I fixed the bug where you would suddenly start to earn an extra Solvalou for every hit. I had suspected it was something to do with the dipswitch settings and bonus life calculation; what I didn't suspect was that it actually comprised about 4 different bugs! 😮

The dipswitches on the Neo Geo were a bit of a mess TBH. And for some reason, I was negating the bits when reading them which only confused matters - including debugging - further. The trick to avoiding CPU-consuming bit operations is to order the Neo Geo settings to match the bit patterns of the arcade dips, rather than preserving a nice 'natural order' for each option. It's better that the options listed for lives is "5, 2, 1, 3" (you'll likely only ever look at them once) than requiring an extra 12 instructions every VBLANK just to read the dipswitches - or a few lookup tables!

Suffice it to say, as well as incongruencies in the Neo Geo dipswitch settings, there were a few bugs in the bonus calculation routine as well (comprising 16-bit BCD addition), which meant around 64,000 you started getting Solvalou every hit. And because it worked fine at 20K and 60K, it went unnoticed for a long time, until I started patching the starting score to test the high score table and load/save.

So now I'm left the randomly exploding Solvalou, seemingly (only) when Bacura are present. At least I believe I can reliably recreate the issue every time, so I'm hoping that won't be too difficult to fix either. I'm a bit surprised that it might be related to the olde Bacura hit-box issue again (which was a bit of a bugger to find), but no solid theories just yet.

The only other issue I'm aware of is something I noticed early on when working on the scrolling - when ignoring attribute settings for tiles (can't remember fg or bg) there was a curious black square scrolling down the left-hand side of the screen. It could have been related to the Xevious sprites - which have since undergone a complete overhaul - so I'm half-expecting the issue to longer exist. But I will see if I can recreate that one as well, just for good measure.

That should cover everything, except for the purely cosmetic issue of 'sparklies' on the screen, mosty down the left-hand side. Absolute worst case, they don't affect the game at all and are easily ignored, but again it wold be nice to know what it is, and whether it can be eliminated.

I suspect it is Neo Geo sprite code running outside the context of VBLANK. It may even be the foreground layer tiles being updated - they are always outside VBLANK. If that's the case, I can look at using dirty squares and deferring update until VBLANK, or just leave them as-is. Not a show-stopper by any means, and akin to 'sprite flicker' you see on a lot of platforms being pushed to their limit.

Now, those pesky Bacura...

Saturday 25 February 2023

Running on real NGCD hardware!

One step forward, two steps backwards perhaps?

Firstly, I burned a CDR and tested Xevious on my NGCD. Works as expected! I can also confirm that high score load/save (to/from virtual memory card) works fine on the NGCD hardware as well - yay!

Xevious running on real NGCD hardware!

During play testing however, I noticed another bug today. I also confirmed one of the two existing gameplay bugs - extra Solvalou suddenly starting to appear every hit - is definitely still an issue.

The new bug, which I haven't really noticed before, is the Solvalou suddenly exploding for no reason! In hindsight I may have seen a hint only a few days ago, after fixing the "hanging bullets" issue, but at the time I thought it was due to a teleporting Zakato. Not so it seems...

So I have 3 outstanding issues, one yet to be re-confirmed.

Another observation; I do get "sparklies" on the screen. I noticed this on my AES, but couldn't discount the fact that it was crappy output/cabling. Now that I get the same issue on the NGCD, I'm forced to concede that it may well be my programming (although I'm using the same cables). Not a show-stopper by any means, but would be nice to find the cause and eliminate it...

And as a reminder to myself; I also need to generate the proper FIX layer for the NGCD.

UPDATE: Fix layer for NGCD done (just needed to copy the cart FIX ROM and rename).

A bit more play testing. High score load/save working on NGCD. The random explosion of the Solvalou seems to be related to the Bacura; at the very least it happens more often with Bacura on the screen. Hopefully a good clue. Sparklies my issue; my splash screen is rock-solid.

Friday 24 February 2023

Xevious for the NGCD

No progress on the corrupt title screen after high score entry. I suspected it was related to the scrolling routines, as there are 3 distinct cases handled differently; in this case it would be an arbitrary scroll value which requires the entire background layer to be re-constructed. I did find what I think was a bug in that routine, but I also believe the case affected never actually happens!

However I've gone cold on that theory now; it only happens after high score entry, and there's no difference to the sequence of scroll register values written. I'm at a loss TBH...

Onto some good news. My inbox has been flooded with emails begging me to include a CD build of Xevious when I release the beta (by 'flooded' I mean I got one message and by 'begging' I mean asking me if Xevious could possibly be made to run on the NGCD).

And so I attempted to build - for the first time - the CD version of Xevious. Not having built a CD in probably 10 years, the build failed miserably. But after some refreshing of memory and re-visiting my old Donkey Kong project I updated the Xevious build tools to produce the .SPR file and managed to create a bootable CD.

Easy enough to run in NeoCD/SDL; running it in MAME is another story altogether. That was a learning curve but I finally worked it out, and added the necessary ISO to CHD conversion to my makefile.

The game loaded and ran fine. The graphics, however, weren't. It looked like the palette wasn't initialised. I could see the Xevious sprites, but just about everything else was invisible and/or black. I could see the forground tiles for example, as the Xevious sprites flew under them.

It's running in sttract mode!

So I went back and checked all the locations in the code that differed for a CD build - only one (OK). I checked the header file for the CD (OK), I checked the Donkey Kong code for differences in a CD build (none), I checked that I wasn't running out of RAM (OK). I perused the NeoGeoDevWiki for any clues... but I was starting to run out of ideas...

In fact I was typing up a post for one of the dev boards when I thought to re-check the format of the sprite data in the .SPR file. Referencing the NeoGeoDevWiki again, I noticed that the bitplane ordering was reversed wrt what I had just copied from the old Donkey Kong project...

A quick code hack and re-build and it confirmed the issue; Xevious looks just great on the NGCD!

I will burn a CD and try it on real hardware this weekend though.

That begs the question about how Donkey Kong was working. One possibility is that DK is using less bitplanes. Another is that I hacked the palette becase I couldn't work out what was wrong? It was 10 years ago... In any case, it's all fixed now and I even went back and fixed the original DK tool in the process.

Now back to that corruption bug...

UPDATE: A good day - not only did I get the NGCD build going, but I also fixed the title screen corruption bug!

Single-stepping through the code that updates the background layer after the high sore entry screen, it got interrupted by code that jumped into the BIOS. It then hit me that the hardware scroll update code wasn't actually being called within the VBLANK interrupt context - and thus potentially having the VRAM address register being changed mid-stream.

Right now I can't explain why the routine is being interrupted - it should be executing well before the next VBLANK interrupt - but that's for another day. What matters is that disabling interrupts around the scroll routine fixes the problem!

That now leaves just two (2) "bugs"; both of which I need to confirm are actual bugs. Just recreating them may be a challenge in itself. If I'm not successful in doing so within a couple of sessions, I might just release a beta and see if anyone else encounters them. Getting close now...

Wednesday 22 February 2023

Transcode audit finished & bullet bug fixed!

Significant day today - finished the audit of the SUB ROM, and also fixed a long-standing bug!

I'm reasonably happy with the state of the transcode, though I may still need to tweak some of the execution flow to better accomodate the single-CPU architecture with respect to the VBLANK. I don't think it's an issue on the Neo Geo, but the graphics-intensive Amiga port may be another matter.

I've fixed the bug where some bullets just "hang" in the air. As happens way too often, you "fix" it and it still doesn't work - because it actually turns out to be a combination of multiple (in this case 2) bugs. In both cases, it was about register usage; one case of a register not being preserved around a subroutine, the other a case of a subroutine called from two places but parameters in different registers.

And only now that the bug is fixed, have I noticed that the Brag Zakato firing patterns look right!

Brag Zakato spraying 5 bullets

I also confirmed that one 'bug' was an artifact of skipping areas when debugging - it happens on the original version as well. In fact I don't really understand why it's happening, and suspect it's a bug. Regardless, it doesn't happen during normal gameplay.

That leaves me with three (3) outstanding bugs now; corrupt title screen after high score entry, extra Solvalou every hit, and a glitch that I noticed when debugging the graphics routine. The first is almost certainly a bug in the Neo Geo (OSD) layer, the 2nd may be related to dipswitch settings, and the 3rd I'm not even sure is a bug!

There is also the question of transparency in the Xevious sprites; jotd has pointed out that a whole bunch of sprite CLUTs have multiple transparent colour entries. I do know the crosshairs use such CLUTs, but was not aware of the others. I certainly haven't noticed anything "wrong" whilst testing... but I haven't been looking either. To be investigated...

Hopefully I can knock these off in the next few days and I can move onto sound!

I may also release a beta before adding sound for people to test the gameplay...