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

Tuesday, 26 November 2013

Less hacky

Last night I managed to clean up the linker script and it now builds with multiple ASM files linked together, as opposed to a monolithic source file with .includes scattered throughout.

And today at lunchtime I put together a minimal header include file and linker script for the NGCD.

Have to say, the NeoCD emulator does a better job of rendering the scaled sprites than MAME does. Whether it looks that much better on real hardware - I have no idea. Unfortunately, developing for the NGCD is a more tedious process, as each build requires un-mounting the virtual CD image, burning another with ImageBurn (which I've managed to reduce to a 2-click process) and then re-mounting and launching the emulator. There's also the lack of a built-in debugger, which I've already used in MAME extensively whilst trying to solve my numerous NOOB mistakes, and I haven't even scratched the surface of the port yet!

EDIT: After proof-reading this I realised I could probably leave the image mounted and copy the PRG file directly to the virtual CD drive - DOH!

As a result I will primarily be working on the cart version, which can be up-and-running in MAME well within 2 seconds from the last edit change. Every now-and-then I'll check that I haven't broken the NGCD build.

So now it's down to the business of porting the Z80 code. My first milestone is to have the attract mode screens (minus the game-play demo) ported and cycling through. That's at least a few week's work given my time constraints, so probably not a lot to blog about (except for hardware news) until then.

Monday, 25 November 2013

Same Same But Faster

After lunchtimes and nights stumbling my way around GNU assembler and linker, Neo Geo hardware and 68K ASM, I've finally managed to replicate my Donkey Kong rendering demo in 100% assembler.

This time 'round, I've got it rendering in both horizontal and vertical orientations, the plan being to develop both variations if practical - even if it means assembling both variations in their entirety and having them side-by-side in the same PROM image (after all, it's only 16KB of Z80 code!).

100% ASM rendering - horizontal and vertical orientations
It's not perfect yet - there are obviously a few nuances of Neo Geo sprite hardware I need to tame - but it's enough to get me started on porting the code. The demo comprises a single render function for the entire screen (which handles either orientation, selected with the controller A & B buttons) and is being called from the demo VBLANK handler (after executing the BIOS handler).

I'm still yet to decide the best approach for rendering in-game graphics, so for now I'll take the 'easy' way out, and maintain a copy of Donkey Kong's 1KB VRAM in Neo Geo RAM, and render from that every VBLANK (as the demo is doing now) until the best solution becomes clearer. I figure if I use macros to address the VRAM it'll be easier to adapt them to direct Neo Geo (and other platform) hardware accesses at a later date, as well as facilitating rotation of the display.

Before I get much further though, I need to step back and configure the linker properly, and I should also set-up the CD version as well rather than wait until the end. Regardless, there's a decent amount of code to port until I get anything at all to show for it, so probably not much to blog about in the next few weeks... although I am attempting to get the NGPACE hardware moving along...

Friday, 22 November 2013

(Not Sega) Genesis

Today I spent my lunchtime setting up a new 68K ASM project that will become NeoKong (aka Neo Geo port of the arcade Donkey Kong). I've decided to stick with the GNU assembler for compatibility with C projects and the devkit, and I also figured (rightly or wrongly) that it was the de-facto standard assembler for Neo Geo development.

As it stands, my code instructs the BIOS to run the eye-catcher animation, sets the stack pointer, acknowledges interrupts and then loops kicking the watchdog. Not too exciting I admit, but it took a bit of time to convert the header files from the (ASW-based) sprite sample source from the Neo Geo Development Wiki page for GNU AS.

Now the fun begins.

No brute force for Kong?

I've been pressing ahead with the disassembly during my lunchtimes and evenings, where possible. Right now I've completed the bulk of the non-game-play portions of the code, which includes the initialisation, title and coin-screens, and the high-level program flow. I'd estimate about 25% code coverage so far, which perhaps sounds less advanced than it is, considering a lot of the data areas have been identified. These data areas appear all throughout the non-commented portions of the ROM code, giving valuable time-saving clues to their function. There's also a fair amount of drawing and animating code that has yet to be commented, which should prove more tedious and time-consuming than technically challenging.

I have to say that the code is rather well structured, and obviously well thought-out. After initialisation, the main foreground loop is responsible for mundane tasks like checking bonuses and updating scores, whilst the rest of the main logic is scheduled from the 60Hz (VBLANK) NMI. Here the inputs are read, sprites and sounds updated, and the rest of the logic dispatched via a hierarchy of function vector tables, not unlike Pacman.

The hardware is also funky; two (2) banks of up to 128 sprites (a total of 16 per scan-line) whose registers are DMA'd from CPU memory space every NMI. Not unexpectedly, Donkey Kong only uses a handful of those sprites.

As I become more familiar with the code, I'm now considering re-thinking my approach to a 68K port. A brute-force, line-by-line translation would not only be mind-numbingly tedious and error-prone, but I'm starting to think also unnecessary! Previously I was worried about implementing portions of code that weren't understood, and whose side-effects were unknown, but now I'm thinking that those incidences will be kept to an absolute minimum.

It also tends to negate the need to maintain a side-by-side Z80-68K ASM listing. I would retain the overall architecture whilst organising the code and data in the same sequence as the original Z80 code, but in a separate file. Perhaps a little more cumbersome during development, but ultimately more flexible in the long-run. For instance, it would be easier to start implementation before 100% completion of the disassembly - for example right now I could code the attract screens without the game-play portion (and I may do just that) - and easier to patch functions and/or modify program flow for debugging/development.

The end result would be cleaner, more native 68K code, and easier to maintain. I would also strive to separate the Neo Geo hardware aspects of the code, facilitating easier porting to other 68K-based platforms, such as the Amiga.

All still pie-in-the-sky atm, but I firmly believe completely achievable!