Friday, 6 December 2013

Let there be sprites! And when X=Y...

I've got the 1st sprites showing in Donkey Kong - Kong himself on the title page.

Now with added sprites - albeit in the wrong location

You will, no doubt, notice that the sprites are not in the right location - more about that later...

But first, after hooking up the palette to the sprites, I discovered that the bitplanes were reversed in the Donkey Kong sprite ROM's w.r.t. the tilemap ROM's... something that may simply be a 'bug' in MAME as the ROM's are organised in the driver arbitrarily to some extent. Either way, a simple fix to my conversion tool and I was up-and-running with correct colours just a minute or so later.

In the process I fixed a bug (which was disabled anyway) in my tilemap rendering routine and did a few minor optimisations. I'm still not convinced that a complete rendering of both tilemap and sprites every VBLANK is going to cut it on the final version, but gee it'd be nice - very nice - if it did!

So, about those sprite locations; stepping back a bit the whole X-Y issue has been somewhat clouded from the beginning, given that the display on the Donkey Kong cabinet is rotated 90 degrees. I've referred to coordinates as 'X' & 'Y' and also referred to 'rows' and 'columns' throughout my commented disassembly and, to be honest, I'm not sure I haven't been inconsistent in some areas. And whilst it's easier to think about Mario's X coordinate changing as he runs across a girder, it is in fact his sprite's Y coordinate that is changing in the hardware. And of course, a row of text spanning multiple columns is actually a single column of text on the display spanning multiple rows. So what convention do you choose, and how do you make it clear? My brain started hurting right about now.

So when mapping all this to the Neo Geo hardware, it complicates the issue. And to make matters (much) worse - at least where sprites are concerned - it's not a nice 0-N range on one/both axes on either hardware platform! The sprite rendering code in MAME, for example, looks like a veritable dog's breakfast, somehow involving the current scan line! Arrggh! And of course, supporting both orientations means I have to solve the problem twice. If my brain was hurting before, it's throbbing now!

As a result, thus far I've managed to place the sprites somewhere on the screen for now.

To be honest, I haven't decided my plan of attack from here (sprite coordinate issues aside). I'll have to take some time to study the uncommented areas of code to work out how best to proceed. Ideally, it'd be nice to get Mario running and climbing, without the distractions/complications of timers, barrels and fireballs, and possibly easier to understand the sprite coordinate issues. Having said that, I have no idea at this stage what proportion of the remaining code would need to be ported to achieve that.

To give some very vague idea of what I've done so far, the PDF listing from IDA is approximately 80 pages of code. But that can be rather verbose with comment lines between functions, and added lines for cross-references - let's say 20%, so maybe 60 pages of Z80 code. My main.68k file, which contains (mostly) non-Neo Geo specific code, is currently 8 pages of code. However, operations can be done rather more efficiently in 68K code, so I'm going to estimate that would represent at least 10 pages of Z80 code. Using these very rough figures, I might say that I've ported about 1/6th or 17% of the code; doesn't sound like much when you put it like that. But there is an awful lot of 'grunt work' code remaining - code that will simply be a matter of turning the handle. Tedious but straighforward.

Wednesday, 4 December 2013

Sprites

Tonight I converted the Donkey Kong sprites to Neo Geo format.

Next task is to write the sprite rendering code for the Neo Geo. In theory DK has two (2) banks of 128 sprites, although according to MAME only 16 sprites are visible on each line. Regardless, from what I've gleaned from the code thus far, nowhere near that many are actually used. For now I'll need to devise some algorithm for selectively displaying only those sprites that are actually used. Ultimately I'll probably rationalise and condense the sprites that are used on the 68K port.

Tidy-up, bug fixes and the GCW-ZERO

I decided to give my 68K code a once-over before I move onto sprites; fill in any missing functionality in the execution path of the attract mode that I've already commented but not ported.

In the process I fixed a few minor bugs; the score and high-score display routines were always showing "000000", and the palette for the conveyor/cement level was wrong.

I also decided to finish off commenting and porting the level background rendering routines, which were decidedly simpler than the girder and ladder drawing routines; each level is a mixture of generic and special-case routines, the latter being simpler to reverse-engineer. As a result, here are the four levels as rendered before any sprites are added:

All 4 screens, fully rendered before adding sprites
I really am at the stage now where I need sprites to see what is happening in the code. Again, the conversion to Neo Geo sprite format should be straightforward, and shouldn't take me more than an hour or so. Then I need to write the sprite rendering routines for the Neo Geo hardware. One interesting aspect of the Donkey Kong hardware is that the sprite registers are shadowed in ordinary RAM and then DMA'd to the hardware registers each VBLANK interrupt. That actually makes my job really easy (for the initial implementation) as I can essentially do the same (although I'll be using the CPU to move the data). It's not necessarily how I'll implement the final version, but again, makes it very easy to debug and also rotate the screen!

I do have a particular issue with sprite placement due to the fact that I'm scaling the tiles (Neo Geo sprites) to fit the entire Donkey Kong screen on the Neo Geo display, but I'm pretty sure I have a solution for that issue.

As an aside, I received my GCW-ZERO yesterday and have spent a bit of time installing emulators - including the Neo Geo of course - and playing a few things. Whilst the emulations themselves are excellent, and the screen is nice and bright, the build quality is absolute, complete and utter GARBAGE! The controls are so horribly crappy and sticky, it's almost unusable. I'm not sure what my options are given that it's a Kickstarter project, but I'm sure as hell not happy about it! Consider this a Public Service Announcement.


Monday, 2 December 2013

Every man and his dog...

It seems Donkey Kong is a ripe candidate for (commented) disassembly - I now know of possibly three (3) disassemblies which would make mine the 4th!

The first as I mentioned is Sockmaster's listing, created when he ported it to the 6809-based TRS-80 Color Computer (aka Coco). The 2nd I learned about only yesterday, Jeff Kulczycki's listing, created when he added the 5th Foundry level. AFAIK this listing hasn't been released in the public domain. The 3rd I discovered today on the Donkey Kong forums; a reasonably comprehensive disassembly from what I've seen so far.

With all these available you may wonder (as do I) why I'm bothering to do my own. You can be certain I will be using all the information from the latter, just as I have Sockmaster's, but even that is lacking in some key areas I've already encountered. For example, the code to draw the levels is relatively uncommented (save for rather pointless comments such as 'subtract 10 from A'). So I will be taking everything available, verifying it to my own satisfaction, and merging it into my own IDAPro disassembly. Ultimately I aim to have the most comprehensive disassembly, and I should be able to generate fully-relocatable Z80 code (alongside my 68K port of course).

For instance, tonight I have been working on the aforementioned code that draws the levels, and thus far have deciphered the routines for drawing girders and ladders. The rest of the draw routines should follow quite easily from here. I suspect Jeff has managed to do as much (as he added a 5th level) but no-one else seems to have done so before.

But enough words and more eye-candy. The attract mode now cycles through all three screens, but of course the game-play demo is currently a static, tilemap-only, rendering.

The Neo Geo cycles through all 3 in attract mode

On par with the disassembly, I have coded the girder and ladder drawing routines, and made use of the ability to specify any level for the attract mode. The results vary from level-to-level, but it's a good indication that I've got these routines working correctly.

The 4 levels, girders and ladders only

And that's about as far as I'm going to get without any sprites. So it's back to my ripping software to convert Donkey Kong's sprites to Neo Geo format; nothing too different than the tiles so I'm expecting that to be a straightforward process. Then I can get Kong rendered on the title screen, before the infinitely more daunting task of delving into the game-play (attract mode).

Saturday, 30 November 2013

A title fit for a Kong

Not a lot more work required to produce the title screen (sans sprites)...

Donkey Kong (left) vs. Neo Kong (right) sans sprites

I've patched the main sequencer to skip the game-play demo and go to the title screen, which flashes for a few seconds like the real deal. Obviously Mr Kong is made from sprites - 10 to be exact. Now it's time to undo the patch and at least get the game-play demo screen rendered. Here the code gets a little more involved and again there are some sections I'm yet to reverse-engineer. However, I don't think it's going to be a huge amount of work to see the main background for level 1 (a.k.a. the barrel level).

I've also got a 'define' in the source for which level the game-play demo uses. Obviously Mario's attract-mode movements aren't going to be suited to the other levels, but at least at a later date I can have each of the levels rendered without delving into the game-play proper.

Friday, 29 November 2013

Insert Coin

Neo Kong is coming along nicely, and now it displays the 1st attract mode screen - the 'INSERT COIN' screen - in its entirety. It doesn't seem like much, but there's a decent amount of infrastructure code behind the scenes; as well as the main program flow I described last post, there's also the routines for displaying general messages, credits and scores, for example.

Donkey Kong (left) vs Neo Kong (right)

One of the more interesting areas I reversed-engineered last night was the mechanism for queuing functions to be executed in the foreground loop. Up to 32 functions can be scheduled by storing the function's jump-table offset, together with a 1-byte parameter, in a queue. Typical functions that may be queued include messages and bonus & score updates. Perhaps not surprisingly, the code for this mechanism has deviated the most from the original Z80 code.

With a reasonable amount of the infrastructure now in place, I'm hoping that there's more eye-candy to show (i.e. attract mode screens) for relatively little more effort.

And here I may have found a 'bug' in MAME. "L=00" isn't supposed to be updated in attract mode; but the code to initialise the attract-mode flag after power-on is executed from the VBLANK interrupt. In MAME the foreground loop gets executed at least once before the 1st VBLANK interrupt, which results in the level being displayed. Not so on the Neo Geo (I've fudged it for comparison). I'm wondering what the real hardware does!?!

EDIT: Seems I was a little too quick to blame MAME. Turns out that the update of "L=00" is a side-effect of the routine being called before the variables are initialised; the score is compared against the bonus life setting ('00,000') and an extra life awarded, causing the level to be displayed. I hadn't finished coding the routine that is responsible for the erroneous update.

I'll skip the game-play demo - which appears after the 'INSERT COIN' screen - and start on the title screen next (sans sprites).

Thursday, 28 November 2013

Not so horrible after all!

After a few sessions of getting into the business of porting Z80 code, I must say it's not nearly as onerous as I first feared. Having said that, there's a big difference between blindly porting code instruction-for-instruction, and re-writing commented Z80 code in 68K.

The former would be unbearably tedious, not to mention horribly error-prone, and in hindsight I don't think I'd ever attempt such an exercise. The latter is almost fun!

Whilst technically I'm porting the code line-by-line, I'm striking a balance between keeping the code as congruous as possible, and taking advantage of the 68K instruction set. For the most part I'm using a one-to-one mapping between Z80 and 68K registers, but not strictly adhering to that when it's more efficient not to. I'm also taking care to keep the routines (and data) in the same order, with the intention that once it's all complete, I should be able to merge the Z80 and 68K listings to produce a side-by-side code listing.

Thus far, both the foreground (main) loop and background (NMI/IRQ1) loop structure is there and running. The hardware initialization (video h/w and dipswitches) is done as is reading the controller inputs (which happen to map nicely to the Neo Geo controller). Right now the 1st attract screen is shown (incomplete) and it then transitions to the 2nd (game-play demo, barely started) after a time delay. Here is where the code starts to get more interesting - drawing the in-game screens!

I'm also using macros for all VRAM accesses which means, in theory, I can alter the mapping at a later date by editing a few simple macros. This should allow me to, for example, rotate the screen or map the video accesses directly to non-contiguous / sparse memories such as the Neo Geo sprite tilemap memory.

I'm starting to encounter areas of the code that I haven't commented yet, which means I'll be switching back-and-forth between commenting the Z80 code and porting it to 68K. Actually it's not a bad way of doing things at all, and in some ways makes it a little easier from the reverse-engineering perspective - not to mention a little more interesting!

In the back of my mind I'm trying to think of other classic video arcade candidates for a Neo Geo port. I chose Donkey Kong only because I had access to a (partly) commented disassembly. I'd like to try my hand at a horizontal game next; something more suited to the Neo Geo screen. Unfortunately, most of my favourites are vertical shmups. In particular my all-time favourite, Xevious, which is another Z80 game. The interesting thing about Xevious is that there is already a 68K port - as part of Namco Classics Vol 1. What's perhaps even more interesting is that I wrote the MAME driver for it, and so I'm familiar with the graphics processor that is used!

I wonder if there's a market for an MVS cartridge with a compilation of classic arcade games???