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


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! 😲