Monday 31 October 2022

Do you want to play a game?

Not a lot of time spent on it today. Can now start a game after coining up. Scrolling is a bit screwed atm.

Gameplay mode!

Might be enough to fix the scrolling now before I attempt to bring (Xevious) sprites into the picture.

Coining up, but scrolling will need to be revisited.

Some good and some bad news.

First the good news; transcoding of the high level structure and attract mode screens has been fairly straightforward. It cycles through the 4 screens - sort of, no gameplay - and prints a handful of messages. I can also coin up for 1 or 2 players. They are by no means complete though.

Coined up on the Neo Geo

The bad news; I'm going to have to re-think the background scrolling. Not so much the mechanism on the Neo Geo, but rather how it keeps track of where it's reading the map and where in video RAM is currently visible.

Without checking properly, I assumed that the only place the background layer was being accessed (written) was the map. This (incorrect) assumption allowed me to all-but-ignore how Xevious was doing it and come up with something easier to code on the Neo Geo. Well, that all came crashing down when I (re)-discovered that portions of the Xevious logo are actually rendered on the background layer.

And in the process it needs to position the visible area at a fixed location, which is not a function that I currently support. But it's not a deal-breaker by any means; I just need to revisit it at some point and emulate the actual hardware more accurately. I will do so with a better understanding of the Neo Geo hardware in any case, after the recent experiments with scaled sprites.

For now I'll press on with the high level structure, and flesh it out so I can start a game. This will allow me to start adding (Xevious) sprite support, and then things will really get interesting!

Friday 28 October 2022

Foreground and background tile layers complete

Tidied up the display (fixed a few bugs) and finished off the foreground tile layer.

Foreground and background tile layers functional

With both tile layers done (in theory) that just leaves sprites, inputs and - at a much later date - sound for the OSD layer. Undecided whether I'll tackle sprites next, or hook up inputs. Probably the latter as the sprites require quite a bit of infrastructure to be transcoded before I'll see anything of them. With inputs I can code the high level function structure, advance through the attract screens, coin up and start a game.

I was having some technical issues with the Neo Geo implementation of the tile layers using shrinking sprites. Turns out there is a rather unexpected limitation with sprite shrinking which has been confirmed by others. If I had known it would have saved me some frustration. For now I'm working around it, but can come back to that later.

The good thing is that once the OSD layer is in place, it's simply a matter of transcoding the game logic; arguably the hard work will be done.

Thinking more about the Amiga port it occurred to me that there may be issues supporting the rich palette of Xevious. Bugger...

Core transcode begun and the foreground tile layer WIP

Big tidy-up of the codebase today, with a better delineation of the core/OSD (OS-dependent aka host platform) interface. All the Neo Geo specific code has been moved from the Xevious core to the OSD (Neo Geo in this case) files.

I've implemented the foreground tile layer on the Neo Geo, and updated the palette to support it.

I started on the transcode of the Xevious core; very early days with little more than the main loop and the function tables in RAM but it's working nicely thus far. The immediate focus is to port some code that writes to the foreground tilemap layer so I can test it, and iron out the interface.

A quick hack in the end, but managed to get this...

NAMCO copyright message on the foreground layer (wrong palette)

It's a bit messy and there's still work to do but encouraging.

As with the background layer, I'm not going to replicate the mapping from video RAM to on-screen tiles; there's really no point and most if not all of the foreground video accesses are done with hard-coded screen offsets. I may be able to write a macro that converts the original offsets to linear addresses.

Wednesday 26 October 2022

Cleaning up the display

Very quick update tonight.

Cleaned up the Eye Catcher screen (with my custom hack from earlier projects) and added masking sprites to the Xevious display. The screen width still isn't right... there's some behaviour I haven't quite understood with the Neo Geo sprites but hopefully I'll get that sorted soon.


As you can see, the scrolling looks a lot better without the jumping edges top and bottom. Any jerking you may see is an artifact of the MAME video recorder and/or Google playback. It's silky smooth on the emulator.

I also had a look at the VASM assembler which seems to be popular with some Neo Geo and Amiga developers. It all makes sense but none of the sample projects are set up to use a linker with multiple object files, and right now I don't want to look further into it, so it's gnu AS for now...

Tuesday 25 October 2022

Scrolling, scrolling, scrolling... (I think I've used this one before)

Good progress over the last few days and the first real milestone achieved. The first half of the video doesn't show anything of interest, and I don't have the tools or the time to crop it, so I'd suggest you skip the playback to half way.


On arcade hardware, this is trivial, but the Neo Geo doesn't have tilemaps, let alone scrolling tilemaps, so it was necessary to emulate a scrolling tilemap using the sprites. Fortunately the Neo Geo has bucketloads of sprites (448 in fact) and they're pretty powerful; each one up to 32 tiles high and can be chained together to produce sprites as large as the screen.

Difficult to explain in a quick blog post, but each row of tiles is a Neo Geo sprite and every 8 pixels of scrolling the sprite at the bottom of the screen is re-positioned at the top with the tile data from the row about to scroll onto the screen. The sprite chaining needs to be updated during the process, so that there are essentially two (compound) sprites covering the screen. In between generating the new rows, the sprites are moved down a single pixel.

It's all running in the VBLANK interrupt, and as per the arcade, scrolled every 2nd interrupt.

Note that the distracting bouncing of the top and bottom rows are actually outside the visible area of the arcade screen and will ultimately be masked by opaque black sprites. The screen will also be narrowed from 32 tiles to match the arcade visible area of 28 tiles.

Part of the exercise here was to delineate the boundary between the Xevious core and the host (Neo Geo) layer, as I intend to use the same core on other target platforms. The trick is to have an interface that doesn't affect the (transcoded) core code, but is efficient to implement on the host.

I had started with the idea of the interface simply being the (background) tilemap video RAM, and had actually coded the prototype rendering routine with that in mind. But I found I was jumping through too many algorithmic hoops to produce what was simply a single row of tiles every 16th VBLANK interrupt, and for no good reason, as the access to the video RAM was confined to s single routine in the SUB CPU.

Instead, the video RAM is now essentially a linear row buffer, and where the arcade core calculated and updated a hardware scroll register, the 68K core calls out to the osd_update_scroll_hw() function with just the value of the core's software scroll_cntr variable. The OSD function uses the variable to find the new row in the video RAM and scroll the screen. Clean and as minimal and as optimal as I can make it.

Next I'll tidy up and re-size the screen as detailed above, and re-visit my allocation of Neo Geo sprite resources to fix the Neo Geo Eye Catcher screen and cater for the foreground tiles and sprites.

I should probably also try running this code on real hardware using my NeoSD cartridge, just to make sure I'm not doing anything that upsets real hardware (like I was initially on Donkey Kong).

Sunday 23 October 2022

Emulating map circuitry!

Unexpectedly I got quite a bit of time to work on Xevious today and made the most of it.

Pretty good progress actually, as you can see from here...

Somewhere in Area 1

OK, maybe you can't see anything different, but there is some significant work behind it.

Yesterday's code rendered from a static dump of the background tile video RAM from MAME.

Today's code reads the map ROM data from an arbitrary point and copies it to video RAM. The interface to the MAP ROM data is (conceptually) the same as the arcade code - a pair of latches. The Neo Geo implementation emulates the glue logic between the 3 map ROMs on the PCB the same way MAME does.

I don't know if I'll keep it this way, but it reduces 64KB of map data down to 8KB.

Next step is to implement the scrolling, which won't be trivial with the Neo Geo sprites, but I've got a pretty good idea how to do it. I also vaguely recall reading an article on how to do it many years ago. Either way, I'm sure I'll work it out. But I wouldn't expect to have it finished for at least a few days.

Saturday 22 October 2022

A background coding 68K ASM on the Neo Geo certainly comes in handy...

I thought today I'd see if I could remember enough about Neo Geo programming to modify my old Donkey Kong source code and get something running with the Xevious tiles.

I learned a few things today; primarily that I don't comment my Neo Geo code anywhere near as comprehensively as I should. It's fine when you're in the thick of things developing, but having left it for 8 years I found myself scratching my head. Another thing is that my 68K is really rusty, but I think that'll return to me soon enough.

In the process of adapting the code for Xevious, I restructured the source tree to more closely resemble my multi-platform C transcodes. The approach I had taken with Donkey Kong was using macros to access hardware within the core code, rather than remove all host-dependent code from the core with a cleanly-architected host layer. So I fixed that.

I updated my tools to generate 68k ASM data statements for the Neo Geo palette. It occurred to me today that the rich palettes on the Neo Geo negate the need for any CLUTs (colour look-up tables); instead there is a 16-colour palette for each CLUT entry on the original hardware. I also realised that I could partition palettes between the background tiles and the sprites, but I won't get into the details now.

One thing is that each palette entry has a transparent colour (0), but the background tiles use all (4) colours and don't have transparency. The solution was to go back and modify my Neo Geo graphics tool to produce background tiles with bit 3 set, shifting them to use the top half of the palette exclusively.

I still need to organise the tiles and palettes optimally for the Neo Geo, but it's enough to get started.

With the project in place and assembling with the new source structure and a few extra files, and a few modifications to get it running again, I tried to get a single screen of background tiles to display. I dumped the memory contents from MAME and copied the background attribute and code areas into an ASM source file and set about modifying the routine that renders the Donkey Kong tilemap. In the end I scrapped it and wrote another for Xevious from scratch.

Give that I hadn't really tested the Neo Geo graphics conversion properly, or the palette/CLUT conversion at all, I was surprised when tonight I finally got to this point...

Xevious on the Neo Geo

The code is far from optimal, but not bad for one night's effort after an 8 year hiatus from Neo Geo programming (in ASM at least). It's also 4 tiles wider than what is visible on the arcade game, but I can fix that easily enough.

Next step will be to get it reading from the map ROM and then scrolling. Then add objects (sprites).

Then I really should go back and finish the RE... (but this is too much fun!)

Friday 21 October 2022

Graphics conversions and Neo Geo

A bit of a break from commenting the RE today.

When I did Scramble I wrote a utility that took all the graphics (palette, CLUT, tile and sprite) information and created a file with a series of C arrays with the simplest format (1 byte per pixel) and possible and a fixed orientation. The idea was that any further conversion (Neo Geo etc) would be much simpler (and easier to understand should I ever revisit it in future). Having a standard format also means my other tools, like Neo Geo converters, don't need to be re-written for future projects.

I hadn't done this for Xevious, so I rectified that today. I then updated my map tool to remove all the loading of data from intermediate formats and instead use the C arrays. Much cleaner now.

I then took the utility that I wrote for Scramble to convert the graphics to Neo Geo sprites, and modified it for Xevious, which has two tilemap sets, more tiles & sprites, and greater colour depth. As mentioned above, this tools should now work for future projects as well.

Here's a snippet from an online tool that displays Neo Geo sprites from the C ROM data...

Some of the freshly-converted Xevious sprites for the Neo Geo

I've been thinking a lot about the next step and I've decided to bite the bullet and attempt a platform-agnostic 68K ASM core. The intention is to get it running on the Neo Geo and Amiga simultaneously. If it works out like I'm planning, the OS-dependent (host) layer can be written fairly early on and allow much of the transcoding to actually run as it is being developed. I'm hoping to enlist some help with the Amiga side of things, so I thought I'd get some sort of framework up and running on the Neo Geo. Hence the graphics conversion today.

First order of business will be getting a scrolling map. Then I'll add some sprites, and some foreground tiles just to round out the interface, before starting on the transcode itself.

Of course there's the small matter of finishing the RE too...

Wednesday 19 October 2022

On the right path (Domograms)!

I've documented the Domogram code. I had to revisit the function in the SUB CPU that adds the Domogram object information as I hadn't fully RE'd that either.

Not surprisingly, Domograms follow a pre-canned path. The path information in the SUB CPU object data table comprises a variable number of (length, vector) pairs. The length is self explanatory. The vector byte is an index into another table in the MAIN CPU ROM, which specifies delta Y and delta X values.

There is a circular buffer in shared RAM for the path data of up to 12 active Domograms. When a Domogram is added to the object tables, the path data (up to 64 bytes, or 32 vectors) is copied into the tail buffer entry. The address of the data is copied into the Domogram's object (what I've called for now) 'extra' table, and the length of the data also initialised in one of the tables.

The Domogram object handler then processes all the path entries by updating the object dX & dY values and timing each vector length. If/when the Domogram path entries are exhausted, it is left to continue on that vector until it scrolls off-screen (or is destroyed).

One thing that had me stumped for a little while is the re-purposing of the object type table as a third timer! A reminder to me that the type table is essentially defunct as soon as the type-specific object handler has been hooked into the object table. FTR the Domogram requires timers for shot frequency, path vectors, and animating the launching of bullets. In hindsight I'm wondering why the latter wasn't incorporated into the shot frequency timer?

Now to bite the bullet and unwravel the directional calculations. I have a sneaking suspicion that some of them may also incorporate some AI parameters that effect the accuracy of the calculations. We'll see..

Most of the handle-cranking is done. And considering where to take this project.

I've spent the last week or so commenting code at a furious rate as the object table structures were fleshed out and subsequently the numerous object handlers - some 67 of them - became a lot more apparent in their function. Literally hundreds of accesses to the same table entries makes for some tedious documentation but at least the bulk of the code is now clear.

In fact I would estimate at least 95% of the code has been commented now, if not 97%.

I have purposefully left a few choice sections uncommented while I pressed on with the straightforward code. Those sections remaining comprise:
  • The Domogram (path-following dome) - the movement calculations
  • Object moving and shooting involving directional calculations. Most, but not all of these involve the relative location of the Solvalou. Or to put it simply - enemies aiming for the player
  • A handful of AI variables that factor into the difficulty of the game
 Xevious is famous for claiming that the "...computer program self-adjusts the difficulty level of game play to the ability of the player at the controls - moment by moment". I have certainly seen some indication of this in the code, although I haven't sought to understand it in any detail just yet.

I have documented some of the variables that control the difficulty of the game. It's worth a separate blog entry on the subject, but the flying objects are primarily used to adjust the game play - not only the frequency at which they shoot bullets, but also the type of flying enemy that is spawned.

I was also surprised at the number of different enemies that have subtly different behaviours, but are otherwise indistinguishable apart from their point values. Not only the more obvious like the various Grobda (tanks) that move in different ways, but also some enemies that use different logic to shoot, or that respectively do or don't take into account the proficiency of the player. Again, more details in a later post.

On that note, I'm considering writing a series of articles that document the architecture of Xevious.

And it's a bit premature, but I've also been thinking about where I want to take the project from here, once the RE is complete. I'm still deciding whether I will actually attempt a transcode. And whether it will be more of a hybrid transcode/port to facilitate running on a single-processor system. And whether I'll do a C transcode, or a 68K transcode, or both. My holy grail would be to see it running on the Neo Geo, but of course that would likely only be in tate mode. I think a C transcode would probably hold up on the Neo Geo, and facilitate porting to other capable platforms. A 68K transcode would be a lot of work, but would be interesting too. Given the nature of the code, I'd even think about some sort of program to auto-generate a lot of the object handler code.

As an aside, it was announced way back in 2015 that someone was writing a port from scratch for the Atari Jaguar. It was even demonstrated at some show a while back, but since then there has been no news at all about a release. I'm wondering whether technical issues, or legal issues have been the cause of the seeming abandonment of the project... would love to get in touch with the author.

And then there's the subject of Super Xevious, which I'm sure will be heavily based on the original source. It would probably be very straightforward to work through an RE of that game.

Finally, Xevious Arrangement on the Namco Classics Vol. 1 68K-based arcade PCB. Incidentally the first two games are also included on the board - I'd be interested to see how they're implemented - maybe a transcode themselves!?! I'm actually reasonably familiar with this board as - aside from owning one myself - I wrote the MAME driver for it many years ago, and did some preliminary RE for it. There's even some debug tools hidden in the ROM!

But I'm getting ahead of myself. For now, I'll probably go back and finish the Domogram handler, then look at the directional calculations. That will allow me to finish off the few small sections of the object handlers that remain.

I think it would then be advisable to step through all 11,000 lines of the ROM code with a particular attention to detail in order to correct any mistakes or add any missing detail. This would be a good point to document all the objects and their behaviour in detail - the Namco Wiki is a little lacking in some areas.

Then the AI...

Plenty to do...

Monday 17 October 2022

The missing Sol Tower - explained!

I thought I'd have a bit of a break from RE today, and go looking for the missing Sol Tower bug.

To recap, parsing the object table in the SUB CPU ROM lists 46 Sol Towers in the game. However, one of those Sol Towers, in Area 6 it turns out, does not appear in the game. Let's see why...

First, some background information on how these objects are implemented, starting with the SUB CPU. The SUB CPU is responsible for reading the map data from the ROMs and generating the background tile information for the map - one row at a time - before it scrolls onto the screen. As it generates each row, it looks up an object data table in its own ROM for any objects that are to appear on this row.

Any objects that are to appear are added to the (active/dynamic) object tables in shared RAM. These object tables keep track of all objects in the game, from enemies to bullets to the Solvalou; they contain state, coordinate, sprite, colour, timer and sundry information in a series of tables linked by object index. The SUB CPU fills out the object type and y coordinate tables.

Interestingly, the object index is actually hard-coded in the object ROM data as well, rather than searching for a free entry in the table. That's because the table is partitioned into different categories of objects, and a number of object entries are referenced directly by other objects, primarily the Solvalou, which needs to be at a fixed position in the table. And also relevant to this discussion is that the object state isn't actually initialised at this point, but rather relies on the state of the (now defunct) object previously at this location in the table (you can probably already see where this is going to go wrong).

Once an object has been added to the type table by the SUB CPU, it is handled by the MAIN CPU thereafter. The MAIN CPU processes objects with a type-specific function for each object type. The object handlers are actually patched into an array of functions called in a round-robin fashion. Initially the array consists of 'empty' handler functions that inspect the object type table and, depending on the object state, patch in the specific handler and execute it. These handlers can relinquish control back to the main routine and be called again in subsequent rounds. Ultimately each handler removes itself when the object is destroyed or scrolled off-screen by replacing itself with the 'empty' handler again.

It is worth noting that for ground-based objects, the object persists in the table after being destroyed - until the crater is scrolled off-screen.

So what should happen with the Sol Tower in question?

In Area 6 the SUB CPU is constructing row $4F and has a Sol Tower (type=$1D) in the object data table to be inserted as object index=$03 in the dynamic object tables. It writes $1D to the object type table and (incidentally) $001A to the object spriteY table.

The MAIN CPU then gets around to executing the handler for object $03, which is the 'empty' handler. It checks the object type table ($1D) and then the object state table, which should be set to $01 during the removal of the previous object. It then patches the Sol Tower handler function into the array, which initialises the state and is executed periodically until the tower is destroyed or scrolls off-screen.

What happens to the missing Sol Tower?

At the time the SUB CPU writes $1D to the object type table, the state is not $01, but either $02 or $03. This indicates that there is an active object still in the table at this index ($03).

Turns out, the Boza Logram (aka Dome Array) from row $77 was also object $03 but is yet to finish scrolling off the screen and hence be removed from the object tables. So the Boza Logram handler is still executing, impervious to the new value in the object type table. A few rounds later and the handler finishes scrolling, removes the object from the tables (including type), and unhooks itself. It is as if the Sol Tower never existed!

The Boza Logram bottom left (destroyed here) is the problem

The root cause of the problem is that the vertical distance (number of rows) between two objects (Boza Logram and Sol Tower) with the same object index ($03) is too small. Moving either the Boza Logram down one row ($77->$78), or the Sol Tower up one row ($4F->$4E), fixes the issue. Alternatively, moving the Boza Logram to object index $04 also fixes the issue (although it causes other problems). So technically it's not a coding bug, but a bug in the map data!

Moving the Sol Tower up 1 row causes it to appear

It begs the question of whether there are other (ground-based) objects in the map that are similarly missing from the game?

There are Grobdas, and then there are Grobdas...

Sunday night update. Ploughing through plenty of code, including most of the code for the Andor Genesis (mothership). Mostly straightforward and I've tended to leave unexplained snippets for now, just to get the bulk of the code commented.

A quick scroll through the MAIN CPU listing would suggest around 80% of the code has been commented now. I think the only ground-based enemies that I haven't finished are the Domograms (vehicles that move along paths). I have some idea how they move now, I just haven't dug down into the code yet.

I just hope the law of software development doesn't apply to software reverse-engineering; that is, the last 20% of the code takes 80% of the time!!! 😵

I've also done a few of the airborne enemies, although I'm still unsure of how those enemies are spawned. No doubt buried in some AI, as these formations are somewhat random and as detailed on the flyer itself - depend on how well you're doing in the game. A few details that don't gel with the Namco Wiki information, but I'll get to the truth soon enough.

There are also a few enemies that appear to be unused; not just defined in the object table, but with partially complete handler functions coded, or are functional equivalents of other enemies. Some differ only in the parameters of their behaviour (eg. firing frequency), I'll try to document those in detail when I've finished the RE.

I've been updating my map tool to generate statistics for objects and handler functions. Aside from interesting totals on the numbers of various enemies, it has also aided in identification of unused code. One example is that there are no less than 108 Domograms throughout the 16 areas in the game. Another is that there are a staggering 12 different types of Grobda (tanks) defined in the code (generally with different behaviour).

I should probably press on and comment the remaining sections of the code that can be done with little further actual RE, just to get it out of the way. Then I might take a bit of a break before diving in to try and unravel the AI - maybe update the map tool to graph all the ground-based enemies, and maybe try to get to the bottom of the missing Sol Tower.

Friday 14 October 2022

Thousands of lines down, thousands more to go...

Today was a day of waiting around and fortunately I had my laptop with me so I got quite a bit of work done on Xevious. Still churning through the code and slowly discovering not only new things, but old mistakes/assumptions I had made. But progress has been good.

My understanding of the function of the various object tables is firming up as I complete the handlers for more and more objects. There is some AI (difficulty) logic that has revealed itself as well. Quite a few "objects" in the SUB CPU table are in fact placeholders for AI/difficulty parameters that change as you progress through the levels. Pretty clever way to do it, and easy to tweak during development. More on this in a later blog.

Oh and the placement of the bonus flags is (in theory) pseudo-random, but it is designed not to appear too close to the Solvalou. So I'd imagine the trend for each of them to appear on one side or the other is probably related to the pattern of (ground-based) enemies leading up to them!?!

The (active) object table is divided into sections and dictates limitations on the number of various elements of the game. These limits include; 14 ground-based enemies (note that some take multiple object entries, eg. Boza Logram (Dome Array) takes 5), 16 Bacura (indestructible rotating shields), 3 Solvalou shots, 19 enemy bullets and (only) 6 airborne enemies.

The game also only uses half the number of available hardware sprites (64/128)!

The amount of code to comment in the MAIN CPU is a bit daunting when I look at what I've done, and what else needs to be done. Not surprisingly the bulk of the code is handling the various objects in the game; I think I've commented the rest of it already. Last time I checked the listing was some 21,000 lines, but that still contains a lot of single-byte data storage that I haven't compacted yet.

EDIT: I've just checked and there's about 11,000 lines in the listing that is ROM code/data.

I've only got a few ground-based enemies left to RE, including what I think will be the most interesting (and complicated) - the Domogram (Slider). I'm keen to know if the movements are pre-programmed (as I suspect), or follow the background map...

The code for airborne enemies still eludes me, though that's because their appearance in the game is driven by AI logic (and probably some randomness) rather than appearing on a map. That code is going to be the most challenging I fear.

Onwards!

Tuesday 11 October 2022

Tedium and how Easter Eggs are made.

Plenty of code commented in the last few days!

It's all pretty tedious atm actually; numerous routines to handle the various objects which all reference the same table locations over and over again. There's a ridiculous number of different Grobda (tanks) in the code for example (I think some of them are unused) and some of them seem to be exact copies of others.

I recall being at this stage during the RE of Knight Lore. Very productive for a while, but tedious.

I've managed to identify a few of the other objects purely from their sprite codes. And I can confirm that some 'objects' in the SUB CPU ROM object table are actually place-holders for parameters, such as the firing frequency for subsequent Lograms for example.

I haven't tried to estimate what percentage of the object handler code I've commented so far, but there's still at least a few days more to do. Some of it, like the Andor Gensis (mothership), looks even more tedious. Some objects have fixed positions in the object table, and are referenced directly from other object handlers; the player's Solvalou a prime example. And one or two parameters in the object table still elude my understanding. But still lots to do before I hit any walls.

Some trivia. The Easter Egg is implemented as an object with an invisible sprite. By moving to the right and holding down the bomb button at the start of the game, you're guaranteed to hit it because you're basically bombing every row. But if you know where it is, you can trigger it with a single shot. I patched the code to show the position with a Solvalou sprite instead - here's where it is located:

The Easter Egg, patched with a Solvalou sprite

Onwards with the RE'ing...

Saturday 8 October 2022

SUB CPU 90% complete

Very brief update.

I've made quite a bit of progress in the last 48hrs. The main data structures are more-or-less complete which has opened up quite a bit of code in the MAIN CPU for commenting. That will probably keep me going for a few more sessions before I need to stop and think too much again.

The SUB CPU is around 90% complete now. Much of the remaining code is concerned with adding objects that I haven't identified to the object table. I'm beginning to suspect that some of these 'objects' aren't in fact physical objects, but flags/placeholders for logic/events.

I've also had some insight into a small portion of the AI logic for the game; after recently reading on the Namco Wiki about how destroying the Zolbak (Detector Dome) will reduce the amount of enemies that appear, I came across that logic in the code.

There's a decent number of discrete variables in the code that will be more difficult to RE. That's not unusual for this type of exercise. I recall the last few variables in Knight Lore were stubbornly refusing to reveal their purpose!

Thursday 6 October 2022

Code and data structures starting to take shape

Now that the "secrets" map is complete I've returned to RE'ing the code.

The architecture of the code and data structures in memory are slowly starting to take shape. I won't go into any detail at this point - mainly because it's early days and I could have made some wrong assumptions - but there are some interesting aspects to it. And some puzzling ones too. But as I said, early days yet. I will say it's similar to a few other arcade games I've RE'd recently, yet more complex.

It's becoming clear that the SUB (graphics) CPU does little more than set up map and graphics-related data for the MAIN CPU. It doesn't seem to handle any of the game logic at all. There are sections of it that I still need to understand but, if I'm not mistaken, I've RE'd the majority of the functionality.

[I'm wondering now whether it was used - unchanged - on Super Xevious? I should check that.]

There's a fair bit of RAM shared between the CPUs, but very little in the way of communication between them. I haven't found any mechanism for passing or queuing of any messages, for example. I suspect there's a handful of interlock/semaphore bytes, but that's probably about it.

I have actually identified how/where the MAIN CPU handles each of the objects now. I'm still fleshing out my understanding of it but I have, for example, identified a few routines for certain objects from the map. It's interesting how it's done, and probably worth a blog entry on its own.

For now there's still plenty of work to be done in this area, so I'll forge ahead.

Tuesday 4 October 2022

Now with bonus Bonus Flags!

Very quick update. A slight tweak to the sprite positions for the objects on the map, removed the Sol Tower in area 6 that doesn't appear in the game to avoid confusion, and added the bonus flags.

All secrets that appear in-game


Those pesky Sol Towers!

 More eye candy, and another mystery!

First something I mentioned in a few entries back; namely not understanding how two (2) banks of background tiles were selected. Turns out that bit 0 of the attribute byte (in bg_colorram) selects the tile bank. Easy explanation in the end.

And although I haven't exactly wrapped my head around it, it would appear that the two ROMs that handle the address mapping for the 3rd map ROM do indeed implement some sort of meta/macro tile mechanism. Now that I say that out aloud, it's not that surprising. Given that it provides both a tile code and colour/attribute byte for 32K tiles (ie. 64KB) in just 16kB of ROM, it's not a bad compression ratio.

Onto the eye candy and the mystery then.

I've done a little more decoding of the object table, and identified a few more ground-based objects, some of which aren't stationary. It's worth mentioning that this encoding also differentiates between the Grobda (tanks) with different behaviours; those that are stationary, those that stop when fired upon, and those that dart forward, for example.

As well as decoding more of the table, I've updated the map tool to indicate the location of the Sol Towers using the actual sprites. As well as producing a BMP file for each area, it also merges them onto a single BMP for easier reference. It's rather large, but looks very pretty. Here is the PNG version:

All 16 areas showing the Sol Tower locations

And it's pretty obvious now that towers don't appear in the same locations of the global map in areas that have overlapping global map space. At some point I'll update the tool to indicate locations of all the objects. And probably produce the iconic global map as well.

And finally, the mystery. Last entry I mentioned a 46th Sol Tower that hadn't been documented yet. There's a good reason for that; it doesn't actually appear in the game! Why not? I have no definite answer - I can step through the code and see the tower being read from the object table and handled just like every other tower. But the end result is, well, nothing!?!

It could be a bug related to the fact that there is a Logram (Sphere Station) on the same row - I've yet to determine if any other towers have other non-tower objects on the same row. As an experiment I patched the object table to move the tower one row later - and it appears - which suggests I could be right!?!

The missing Sol Tower in-game in Area 6 - one row above where it should appear

So now that I have finally done what I've wanted to do for a very, very long time, I will return to RE'ing the rest of the code. I am intending the next task be working out how the objects are handled once they're copied from the object table; that'll be very interesting, and will open up a lot of the code I'm thinking (and as a result be very time consuming).

Monday 3 October 2022

The Xevious Map starts to reveal its secrets!

A little more RE'ing and a lot more eye candy to come in the next few sessions!

More work on decoding the area object tables; I can (syntax) parse the complete tables even though I have only identified (I think) the EVEZOO Easter Egg, ground-based objects and the bonus flags. And for the abovementioned ground-based objects I know the x-coordinate of the sprite now.

Between some dynamic analysis and the MAME source, I've managed to create a new tool to extract each of the area maps from the ROMs and save them as bitmap files. And as the maps are generated row-by-row, I now parse the object tables. It should be trivial to (also) produce the global map.

With a quick 'n' dirty hack I can show the location of the Sol Towers with a red square.


Area 6 with Sol Tower locations in red.

This will get built on as I further RE the tables and ultimately I should be able to show all the objects. I'll update the tool to show the correct sprites for the currently-identified objects, then return to the task of RE'ing the rest of the code.

Some game trivia; there are a total of 46 Sol Towers in the game, many more than were originally documented in the StrategyWiki Walkthough, and even one more than documented in SPM's comprehensive Xevious Secrets YouTube video (in area 6, as shown above!) I knew most of them when I played back in the day, but looking at the video/maps now, I'm sure there's a few that I didn't in fact know about!

Saturday 1 October 2022

Characters, Tiles and Sprites

Just a quick update.

Yesterday I made some inroads into decoding the object tables for each area. I know the identifier bytes now for most of the static ground-based objects, including the Sol Citadels/Towers.

What this means is that I can now, in theory, generate the definitive map with the locations of all the Sol Towers. This is something I've wanted to do for well over a decade now.

It's interesting to note that the locations are per-area, which means different areas can (and likely do) have different locations for Sol Towers even when comprising overlapping areas of the global map.

And as an aside; these objects are all hardware sprites, not tiles, which surprises me a little. It would explain why you sometimes see them jitter by 1 pixel against the background when scrolling in MAME. It will be interesting to deduce whether it's a 'feature' of MAME, or a feature of the real hardware.

And way back in 2011 I was working on an FPGA implementation of Xevious and, like for my other FPGA projects, had developed a tool in C to convert the graphics ROMs and palette/clut PROMs to a more convenient format, as well as display them. I was using gcc (MinGW) and the (old) Allegro graphics library on Windows at the time.

Tonight I resurrected that tool, using a more up-to-date build toolchain and the new Allegro library. That took quite a bit of stuffing around identifying, downloading, installing and configuring the right components. Then I had to port the tool to the latest Allegro API - it's quite different from the old one. Fortunately I had my more recent Scramble tool as a reference.


Foreground layer tiles

Background layer tiles

Sprite tiles

This means I can now attempt to generate the maps; both area and global.

At this point I'm undecided whether to continue with the RE, or continue with the maps...