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...