Thursday, 13 November 2014

Putting my case forward

Lode Runner for the Coco has languished in the 95% complete state for an embarrassingly long time now, mostly for reasons completely unrelated to the project itself.

From the outset I wanted to release Lode Runner for the Coco in cartridge form, before offering disk/download formats. It wasn't development of the cartridge that held me back though, it was actually the case; I just didn't see any viable solutions in the short term. As a result, subconsciously I was avoiding completing the disk-based project.

Well that changed recently with Tim Lindner's CocoSDC case, seen here, or more specifically when he offered them up for sale. I have duly ordered a small batch of them, with the intention of producing a limited run of the Coco Lode Runner cartridge.
 
The cartridge design - not yet started - will in fact be a generic flash-based cartridge programmable from the Coco itself, with flexible bank-switching options to make it suitable for all manner of homebrew projects including Lode Runner.

Wednesday, 20 August 2014

Extra Nothingness

I'm writing a new entry for no other reason than I just updated the NGPACE blog and thought it high time I did so on this blog too.

After learning (from the Retro Gamer article) that the Sega Saturn version of Lode Runner had a sequel - Lode Runner Extra - a quick eBay search turned up the same Japanese seller I'd just bought the former from, so I just had to have that as well. It has arrived and looks to be in excellent condition, though as-yet untested.

Little else has changed since my last entry; time is still very hard to come by so I'm going to have to start making a dent in my sleep time again. Either that or work out a way to program whilst cycling.

Oh yeah, another idea for a retro port - an enhanced (additional processing power) cartridge for the Vectrex that would enable a perfect port of the arcade Battlezone. Not sure at this point whether the enhancement would involve a micro, or an FPGA, or something else.

Friday, 8 August 2014

Move along, nothing to see here... yet.

Over the past few weeks I've had zero time to work on my retro projects, which of course includes Lode Runner. In an attempt to get my physical well-being back on-track, I've just taken up cycling and also resumed my weight training after a long hiatus courtesy of a disc bulge. This not only reduces the number of 'free' hours in a day that I have, but also leaves me without the energy to even attempt anything that remotely requires brain power, and I fall asleep instead.

However, I feel I'm starting to turn a corner now and I'm slowly adjusting to the new regime. I won't regain the lost hours but the bodily fatigue is much reduced - almost non-existent - leaving me feeling like I am more able to spend the odd late night at the keyboard again soon.

To coincide with this, I've just received my back-issue (#111) of Retro Gamer magazine, which features Lode Runner on the cover and a "Making Of..." feature article inside. Whilst I was a little disappointed with the lack of depth in the article, it was still fun to read it, despite the fact that for some unknown reason they neglected to mention the Coco 3 and Neo Geo ports!?!

I should also mention that I recently acquired the Atari 8-bit XE cartridge (near mint, complete-in-box) for my Atari 130XE and the Sega Saturn Lode Runner - The Legend Returns (Japanese) CD, both of which were refreshingly cheap considering the current, disgusting state of the retro computer/gaming market.

So, my plans haven't changed since the last post - namely, finish off the Neo Geo port and then finish a disk-based version for the Coco 3 before releasing the original 6502 commented disassembly. Any further ports, such as Amiga & Genesis, will happen whenever I feel like working on them.

Beyond that, I'd like to start a new port, but have a few different candidates and - depending on the game I ultimately decide on - also a few different targets in mind. As well as another Coco 3 port, I've got some ideas for the Vectrex, and after listening to the ANTIC podcasts I'm starting to get a little more interested in the Atari 8-bit machines. And recently, the VTEC CreatiVision (aka Dick Smith Wizzard) also caught my attention, mainly for the fact that its entire game catalogue is bereft of a single decent game, and I think the hardware is definitely capable of one.

Stay tuned.

Thursday, 24 July 2014

Eye-catching?

Haven't had much time over the last week or so; the whole family has been sick at various times and I've been trying to fit more physical exercise in which is not conducive to other non-essential activities.

Whilst sick, and not feeling up to a full assault on the Lode Runner code, I started looking at the so-called eye-catcher routine in the BIOS. This is the routine that displays the spinning NEO GEO logo and the other bits of text on the screen at power-up (or reset) before the cartridge takes full control of the system.

The routine itself can be enabled, disabled or overridden by the cartridge with a single byte in the header. Even when enabled, the BIOS routine uses tiles and sprites defined by (stored on) the cartridge itself. Since I'm not interested enough to code my own eye-catcher routine, I thought I'd see how difficult - or otherwise - it would be to produce my own custom text for the BIOS routine.

The results of my investigations have been documented on the Neo Geo Development Wiki here.

My first experiment was to replace the "MAX 330 MEGA" text. It looks pretty good, but needed something on the following line (to replace "PRO-GEAR SPEC"). There was an issue with that (see the wiki entry) but I might return to this option.

My next experiment was to replace the SNK logo. Not quite sure whether or not I like it yet!?!



Anyway, at the very least, I learnt something new.

I've also had a think about what I'll be releasing and when. I was toying with the idea of the initial release of the Coco 3 port being cartridge-only, but I've now decided that it would significantly delay the release and also further delay what should be my primary focus - NGPACE.

As a result, I'm going to finish off the C port as a matter of urgency and release the Neo Geo MVS and CD versions, then immediately move on to finishing a disk-based Coco 3 port and release that in the near future. I'll still work on the Amiga and Genesis ports, but I don't want them to delay the above-mentioned releases.

I also plan on ultimately releasing the original 6502 disassembly and the C source code, probably once the Amiga & Genesis are done. Then it's time to move on to another game.

Tuesday, 15 July 2014

The Genesis of another port...

I couldn't contain my curiosity, so tonight I installed the SGDK - Sega Genesis Development Kit.

A few hiccups but nothing that further study of the sample makefiles couldn't solve. There's a bit of jumping through hoops to create a ROM image, but it's all in the generic Lode Runner makefile now, which is becoming a bit of a dog's breakfast, but I don't think I'll be adding too many more targets at this point in time.

Sega Genesis Lode Runner - admittedly not very impressive yet

Not particularly exciting output, but I was pleasantly surprised to see it on the very first attempt, given the number of steps in the makefile. My blind cut-and-paste skills must be strong!

I could add targets for Atari ST, (68K) Macintosh and X68000, but I'm going to stop myself here before it gets too silly. I need to actually finish off the C core and the ports that I do have before going any further. I'm also growing a little tired of Lode Runner, and want to start on a fresh port in the not-too-distant future.

Monday, 14 July 2014

What I don't know about the Amiga...

I've been sick the last few days so instead of finishing off the Neo Geo port - which also included tackling the AI bug - when finally feeling a little better this afternoon I decided to do something a little less intense, and look at what was involved in developing Amiga software.

I knew the Amiga scene had been evolving for years after I stopped using my A500, and delving back into it in 2014 involves a whole bag of confusion. 68K vs PPC, Commodore vs new Amiga hardware, Workbench 1.3 vs 2.x vs AmigaOS 3.x vs 4.x, and AROS (still not really sure what this is)... and of course the scene assumes you already know the lay of the land. Google was my friend.

Cross-development tools seem to be thin on the ground, and those that do exist tend to be linux-based. Perhaps not surprising because a hard-disk equipped high-end Amiga is more than capable of hosting its own development toolchain. Regardless, my preference at this point was a Windows-based cross-toolchain that I could invoke from the command-line, utilising the existing makefile.

I eventually found a site that hosted the gcc (3.4.0) binaries and a bunch of libraries that ran on Windows under cygwin (not unexpected, but bleh!). After installing both and downloading a missing DLL, I could finally compile hello_world.c.

Next step was configuring an Amiga environment. Normally my go-to emulator is MESS, with its integrated debugger and simple command-line launch. But in this case I opted for WinUAE due to it being reportedly significantly more advanced than MESS when it comes to Amiga emulation. So I downloaded and installed the latest version - I won't go into details but booting from ADF (floppy image) wasn't going to cut it so I had to learn how to install onto a hard disk.

I opted to mount a (PC) directory instead of a hard disk file, mainly because it simplifies the process of transferring files to/from the emulator. After installing WB3.1 and subsequently a missing library (ixemul) I finally saw the words "Hello World!" appear in the Amiga Shell!

Next step was to create the amigaos branch of the Lode Runner project, enhance the makefile and get it compiling under the new toolchain. After stubbing out all the os-dependant routines, and enabling debug messages via stderr, I was greeted with the following:

Lode Runner on the Amiga - debug output (stderr)


So Lode Runner is actually running - albeit headless - rather nicely. I'd be worried if it weren't.

Of course now comes the interesting part, though I may deny temptation and finish off the Neo Geo port (and the C core) before progressing further on the Amiga. Or whilst on a roll, I may look at setting up the toolchain for the Sega Genesis/Megadrive...

Friday, 11 July 2014

Is it Game Over for the Neo Geo? Yes!

Tonight I finished the GAME OVER animation - for colour mode at least. When I was testing monochrome on the Neo Geo the animation still appeared in colour, so I went back to check the Coco3 port and it was the same. Oops! I'll fix that in the near future.



So the bells and whistles in terms of graphics are complete. Just high score entry, special keys and game speed tuning. And fix the last guard AI bug of course. The Neo Geo port is looking good, and the speed of the C code has not been an issue at all!

As I mentioned, the NGCD version is also running in MESS, so this weekend I'll burn a CD and confirm that it runs on real hardware.

UPDATE: It runs! And looks good too!

Once the above issues are addressed, I'll do a full MVS & NGCD release. No point waiting for a cartridge release on the Neo Geo - that's a while off yet! ;)

Next? I might crank up the Amiga emulator. Ideally I'd like to use the same (cross) toolchain, so I can simply add another platform to the make file. But something tells me it's going to be easier to develop on the Amiga itself.

Then there's the Sega Megadrive/Genesis...

Quick update

Found the issue with the NGCD build not running and the palette - works now under MESS. Tomorrow I'll bring home my one-and-only Neo Geo controller from the office and burn a CD and try it out on the real console over the weekend.

Also constructed the title screen graphics. It's close but corrupt in some areas for some reason I can't fathom. Hopefully a fresh look at it tomorrow will reveal the issue!?!

EDIT: Title screen sorted! Now working on GAME OVER graphics animation.

Wednesday, 9 July 2014

I'll 'C' your Lode Runner, and raise you a Neo Geo port

Very good progress today! The AI isn't quite 100% correct, but it's very, very close. The demo runs most of the way through the 2nd level, so there can't be too much wrong now. That aside, the Neo Geo version is definitely playable, even more-so than the PC port in fact.



Most of the battle has been learning the nuances of the Neo Geo sprites. I'm still unsure of how the sprite size field of the SCB3 register is supposed to work. I won't bother going into the details, but I still haven't ruled out the possibility that it's not implemented 100% correctly in MAME. I have more experimentation to do...

...but the upside of all this is that it has definitely been a worthwhile exercise with respect to learning Neo Geo hardware in preparation for the NGPACE project!

FWIW you can select COLOUR or MONOCHROME (GREEN/WHITE) rendering from the soft dip settings in the BIOS. There's probably a few more settings I could add at a later date.

I'll press on with the Neo Geo implementation, fixing the AI and adding the bells and whistles such as title screen, GAME OVER animation and high score entry. And as I've done with Donkey Kong, I'll burn a CD and verify that it runs on a real NGCD console!

EDIT: I've got the NGCD target building, and it runs far enough to show the title screen (place holder) - interestingly in the wrong colour - and then hangs. No further clues at this point.

Then I might look at reverse-engineering one of the most common sound drivers so I can add sound to the game, which I need to do for Donkey Kong as well.

Monday, 7 July 2014

Scaling new sprites

I've been working on the Neo Geo port when I've had the chance, and after a few red herrings of despair, I've managed to get it showing the 1st level with minor glitches.

Apple II Lode Runner - Neo Geo style

At one point I'd given it up as impossible, but further investigation (and a peek at the MAME source) put me onto the right path and confirmed that my initial theories were indeed correct, and I am able to implement it the way I'd originally planned.

The whole question of whether or not it could be implemented revolves around the sprite scaling on the Neo Geo; more specifically, if it is indeed consistent for each tile within a sprite. For the most part it is, although you'll notice above that the game status text at the bottom of the screen is corrupt - this shouldn't be an issue as I will ultimately be moving that text onto different sprites and the issue should resolve itself.

EDIT: Closer inspection of the MAME driver reveals the answer to the corruption; but as I mentioned it won't be an issue as I need to move the bottom 2 lines to another sprite chain for other reasons.

What I have discovered, however, is that the admittedly rudimentary video library is rather unsuited to selectively manipulating large, chained sprites and I will have to revert to programming the hardware directly. Not a big deal, but perhaps a little disappointing. Having said that, there's not a whole of lot functionality to implement in the OSD layer, and it shouldn't be too long before I have a playable, if vanilla, implementation running on the Neo Geo!

Friday, 4 July 2014

C++ --

Last night I had a few spare minutes so rather than get entrenched in debugging the C port, I thought I'd start to set up the project for the Neo Geo target.

I duly discovered that my 'C' port was, in fact, a C++ port! Doh! It's been so long since I've been restricted to pure C code that I'd inadvertently used some C99 and C++ language features. Although it is technically possible to develop in C++ for the Amiga (though a right royal PITA according to what I've read), the Neo Geo toolchain is definitely C only.

Tonight I reverted the Lode Runner core code to pure C and can finally compile and link both PC (Allegro) and Neo Geo targets, from the same makefile. In fact, the Neo Geo target will in turn support both cartridge and CD build options.

Right now running the Neo Geo build I get the hash screen. I was expecting a cheesy FIX-layer text message, so clearly something is not quite right in the build, but I've run out of time tonight. It shouldn't be too difficult to rectify, since I have successfully built the Neo Thunder homebrew project using this toolchain in the past.

EDIT: It's now running - cheesy FIX-layer message and all!

This exercise has also unexpectedly rekindled my interest in finishing off my Neo Geo Donkey Kong port!

Thursday, 3 July 2014

404: Pun not found!

Sorry George, couldn't come up with one tonight. :(

What I have been able to do, however, is finish porting the guard AI logic to C. It's finished in the sense that I have no more lines to port - not in the sense that I have finished debugging. That said, it looks close and I certainly found it challenging enough to play in my 2-minute test. There's a chance I guess that the AI is actually spot-on - it's symmetric to a degree and it's much easier to see inconsistencies and certain other types of bugs in C.

In the process I actually found a (subtle) bug in the AI logic of the 6809 port. In a nutshell this bug means that the Coco 3 version is ever so slightly easier to play than the original when the player is on the very top row of the screen. I've fixed it but am yet to perform any testing on the Coco itself.

Speaking of bugs; I had to go out of my way to implement the AI bug that I documented in my blog some time back, but it's there now so the C version is still faithful to the original.

Once I've sorted any AI bugs that leaves the high score entry (trivial), the GAME OVER animation (also trivial but somewhat tedious) and the oft-maligned circular wipe effect. It turns out that I tackled the C port in pretty much the same order as the 6809 translation.

I've decided to tackle the Neo Geo port (in C) next, if only to verify my hardware abstraction and also my proposed sprite hardware extensions to the code. If all goes well, I should be able to knock this over (at least implement a playable game) in a week or so. I'm not so concerned about the bells and whistles on the Neo Geo at this point.

Depending on how that goes, I might then look at another quick C port - the Amiga!

Finally then I'll return to the Coco 3 for a full-featured release before putting Lode Runner to bed for a while and starting on another game altogether.

Sunday, 29 June 2014

Quick Sunday night update

Nothing too exciting to report. Still working on the C version; working on it in blocks of 15 or 30 minutes when I get the chance. Just finished the guards moving around, which only leaves a bit more of the guard mechanics - getting trapped and re-spawning - before tackling the AI. That then just leaves the sundry bells and whistles to round out the finished product!

In the back of my mind I've been thinking of how to implement this on a tilemap/sprite system, and I think I've got a pretty good idea now. It should be a simple matter of passing through a sprite index - player or guard number - to the generic sprite render routines. Bitmap-only systems can ignore that index, whereas sprite-based systems will use it to update the appropriate hardware sprite. It definitely helps to write the logic in a (slightly) higher-level language to see things a little more clearly.

This all has me wondering now about the best approach for future ports. Early on in the 6809 port process the only option I'd considered was repeating the whole hand-translation exercise for the 68K. A colleague then suggested an automated static translation which piqued my interest. Now I'm wondering whether a direct C translation would do more to assist even in subsequent assembler ports?

Anyway, it remains to be seen how easily the C port can be adapted to, and how well it performs on, systems like the Neo Geo and/or the Amiga. I consider these more academic exercises than anything else; I'm not sure there's much interest in Lode Runner on either platform these days. What's more important for me is that I learn something from the process.

Thursday, 26 June 2014

C-ing things clearer

I've been working on the Lode Runner C port rather than tackle the disk issues on the Coco3... thought I'd let people do some beta-testing for me whilst I psych myself up to finish it.

My weapon of choice is the Allegro graphics library on Windows 7, only because I'm familiar with it. As it turns out, it's looking like it's not quite suited to the task - or perhaps more likely I can't drive it properly. Attempts to create a virtual screen for page flipping (yes, I know it's frowned upon) have resulted in crashes. But I can hack enough to see both screens at once. There are also sprite issues with ugly hacks atm.

As I am interested in preserving the 'style' of the original implementation, I've used more goto's in this one piece of code than I have in my entire history of C programming up until this point. Most of the code can be implemented in functions, but the higher-level routines are sufficiently convoluted that any attempt to structure them will invariably result in subtle differences in behaviour - not to mention no longer resemble the original code. In any case, there's only a few routines with goto's but each of those few use them quite liberally.

The rest of it hasn't been too painful up until this point. I know it's second-time around for me, but some of the routines that took me a few hours to port to 6809 have taken me a few minutes in C! Debugging with printf also tends to be quicker than setting breakpoints and watchpoints and inspecting memory dumps in the MESS debugger too!

The title and high score screens are there. I have the player running, swinging, climbing, falling & digging and the holes fill themselves in. The player can collect gold and progress to the next level. The demo runs too, but without the guards it doesn't get very far before the player is trapped. Deja vu.

Along the way I've attempted to implement an OS-dependent layer so that the core code should never have to be modified when porting to other platforms. Not surprisingly this entails the graphics, keyboard and sound routines.

I've probably got another week or two on this before it's finished. Aside from the mechanics of moving the guards, there's the guard AI on which I'll try to spend the most time crafting the C implementation. I'm hoping that this will serve to (better) document the core game implementation. I should also note that during the course of the C port, the purpose of both code & variables in a few places has become clearer; I'll have to go back and re-annotate the 6502 & 6809 code.

Once that's done I'll probably have a go at a Neo Geo implementation - or at least get the game running - before I get back to the final Coco3 release. At this point I'm not sure how I'm going to handle the bitwise collision-detection on that platform, but I'm sure I can conjure up something. A colleague has also thrown down the gauntlet, challenging me to get the circular wipe working on the Neo Geo. It won't be pretty, but I'll have a crack at it.

I'm also getting calls to resurrect my ill-fated arcade Tutankham port to the Coco3. The port consisted of patches to the original ROM image, which resulted in the game actually running on the Coco; you could coin up and play a game. Too bad the screen was rotated and there was no scrolling implemented. It's a tough call...

Saturday, 21 June 2014

lode_runner.c

I've had enough of hardware bashing for one day so tonight I started work on writing a C implementation of Apple II Lode Runner. There will be a hardware abstraction layer so that it is as portable as possible. I'm hoping I'll be able to port this to the Amiga or the Neo Geo without going through the pain of producing a 68K assembler translation.

The purpose is two-fold; to assist in the understanding and documentation of the original implementation (specifically the guard AI) and also facilitate ease of porting to more platforms.

To this end, the aim (again) is to preserve the style and nuances of the original code as far as possible, to the extent that it doesn't cloud the more interesting aspects, such as the AI. For instance I'll be retaining the bulk of the zero-page variables - although some data types will be changed, such as the score, which will go from four (4) BCD bytes to a single uint32_t. Similarly the rendering routines are considered to be uninteresting and in any case will be abstracted away from the main code.

Thus far I have it displaying the title screen, waiting for a key, and then starting to render the game screen for the demo. All this in about an hour; a bit faster than writing - or even porting - assembler code!

Friday, 20 June 2014

Apple II Lode Runner for the Coco 3 Beta 2 available

Today I finally got to see Lode Runner on my real Coco 3 - and not the way I expected to, either. Still waiting for the DriveWire cable 4-pin connector to turn up (I only ordered it yesterday), I realised late last night that I should be able to get it running from cartridge!

I spent a few hours last night re-arranging the memory map, getting it ready for cartridge release. After a few false starts, by today lunchtime I was able to get it running under MESS. The secret is to have the cartridge copy itself into RAM, and then switch into all-RAM mode, so that there's enough RAM to run the game. The added bonus is that the same build also runs from floppy disk!

The world's first Apple II Lode Runner for Coco 3 game cartridge!
 

Unfortunately I still don't have my analogue-to-DVI converter up-and-running, so I've had to make do with an old television set. After learning about RGB vs composite palettes and burning another EPROM, this is what I saw:

Somewhere in the junk pile is a Coco 3 running Apple II Lode Runner from cartridge


Along the way I've added enhancements to the graphics handling; you can switch between RGB and composite palettes for colour mode and green or white screens for monochrome mode, on-the-fly.

I should add that I haven't fine-tuned the game speed yet, but it should be close!

The beta archive comprises a floppy disk image that contains both monochrome and colour versions. I've also included the ROM image for anyone who wants to burn their own EPROM or flash it into a SuperIDE controller or similar - it requires 32KB cartridge emulation.

Now to the final release...

Thursday, 19 June 2014

Sound at the end of the tunnel

I squashed the aforementioned sound bug this lunchtime.

Phew! This brings me to a major milestone now - the port is basically complete! I need to add the rest of the levels, and the high score load/save, but these are more an exercise in memory management and interfacing with the Coco 3 disk I/O routines than a porting exercise.

And there is still an issue with DAC sound output affecting keyboard input I need to resolve, but for now the 1-bit sound output is perfectly adequate.

I've done a little more quick 'n' dirty hacking for the beta release, to support both monochrome and colour versions on the same disk, and also allow the choice of green or white (for NTSC artifacting via composite output). These will be tidied up for the real release.

I've been thinking about what to work on next. I have a few ideas for more games that can be ported to the Coco3 - including more Apple II and also some Spectrum titles - as well as an interesting proof-of-concept for the Coco3 that wouldn't necessarily result in a playable game in the short term, but is exciting none-the-less. I also have other targets in mind, and will probably work on both Donkey Kong and Lode Runner Neo Geo ports in the immediate future.

Stay tuned!

Wednesday, 18 June 2014

Sound advice

I've ported the sound code to 6809 and after deafening silence last night, managed to elicit sound from the Coco speaker today. Since I'm porting the Apple II's 1-bit sound, I actually have the choice of using the Coco's 1-bit sound output, or the 6-bit DAC. For now, I support either (at build time).

As it stands without any debugging, the sound of the player falling already sounds more-or-less correct. Since the PWM is done in a tight loop, it's all critically dependent on the CPU speed and cycle counts, and without tweaking the values (or the routine) it's invariably a different pitch - slightly higher on the Coco. When it's all debugged, I'll evaluate my options for fine tuning this and see where it goes. Other - more complex - sounds wreak havoc with the game speed atm, but I haven't even started debugging yet.

The sound routines consist of playing back a series of notes (frequencies) each with an associated duration. The durations are specified in absolute time, rather than multiples of the frequency, making 'composing' and game speed tweaking a little easier. And here-in lies a bug that had me scratching my head for a while until I worked out what was going on...

The duration is actually a multiple of 256 iterations of the sound bit-bash loop. The routine to play the sound uses the 6502 Y register to count these 256 iterations before decrementing the duration. The issue is, the Y register is not initialised in the routine and starts with what is effectively a random value. This means that the first count of the duration is - on average - shorter and results in a wrong sum duration for the note. Obviously the relative error is dependent on the note's duration.

Anyway, I decided to retain the bug in the 6809 port, although the randomness of the error will differ given the differences in implementation (Y register vs direct-page register) but you likely will never hear it.

Hopefully tonight I'll get a chance to debug the rest of the sound. The main difference between the falling sound and other sounds is that the former plays a single note at a time, whereas the latter queues a series of notes to be played in a sound buffer. Subsequently the latter implements a different algorithm to adjust the game speed for the sound and I would suspect that this is the source of the bug since the game 'stutters' when a sound (other than falling) is played.

UPDATE: The sound has been debugged, except for a start-up issue where the queued sound has an extraneous note on the end. It seems to disappear permanently as soon as a note (as opposed to a multi-note sound) is played. I suspect the sound queue isn't initialised properly, but it's too late to track it down. Tomorrow...

That aside, it's sounding pretty good. The Apple II Lode Runner sound was never going to win any awards - being little more than beeps and trills - so I'm happy enough with the port even without adjusting the pitch. So I guess the next beta will be the full release just without 150 levels or high score load/save. These have been left to last because they present a challenge, and also will have completely different solutions for floppy disk and (if it happens) cartridge releases.

It would then take me a day to do a Championship Lode Runner release.

Tuesday, 17 June 2014

Finally got a-round to it!

Today lunchtime and tonight I tackled the circular wipe function. I'm pleased to say that it's working in both 1BPP and 2BPP mode. Again, somewhat paradoxically, it's (slightly) faster in 2BPP mode.



It's not enough to simply draw concentric circles; that leaves gaps which give rise to the moiré patterns we so often marvelled at in our BASIC type-in listings. So you need to draw thicker circles to overwrite the gaps. Although three (3) pixels is sufficient in this case, in assembler it's a nightmare, and slow. So I settled on 4 pixels - or a whole byte in 2BPP mode - and I defy you to detect a difference with the original Apple version. In fact, I strongly suspect it's doing the same (I haven't reverse-engineered the actual function itself).

After some first-pass optimisations the 2BPP mode is about 15% faster than the Apple version, so I've left it at that. 1BPP mode is roughly the same speed. I won't bother throttling it at all because after a while it is actually a bit annoying (but all part of the experience).

That just leaves sound and high score load/save, before I add all the levels.

Memory is really tight; in fact the stack is perilously close to the data in the latest build. There's still a bit of shuffling and slight memory optimisation I can do, and I'm also considering revisiting the title screen compression. But all this can wait until after the beta.

Unfortunately I didn't get the chance to order my DriveWire cable components today. I'll endeavour to do so tomorrow.

Monday, 16 June 2014

Back to BASIC(s)

Whilst I wait until I can get a DriveWire cable sorted, I've started looking at the circular wipe.

Tonight I was reacquainting myself with ECB (BASIC) graphics commands and prototyped the code, using Bresenham's circle algorithm (a.k.a. the midpoint circle algorithm). Straightforward stuff, and I don't see that it's going to be particularly troublesome in 6809 assembler. Looking forward to giving it a go, in fact!

Might even be able to sneak it into the beta release...

Friday, 13 June 2014

The Universe conspires...

After mucking about with 80 column text mode, the one last thing I wanted to do was grant myself the small honour of being the first to see Lode Runner running on a real Coco3 in glorious colour.

Given there are several ways to transfer a coco program to a real Coco - cassette, floppy or DriveWire to name a few - I figured it shouldn't be that difficult. So I gave myself a few hours off this afternoon and set up my Coco 3, which has been sitting on the shelf for a few years now.

The first hurdle was video display and, with no suitable monitors at hand, I hooked up my custom analogue RGB to DVI box that worked a few years ago. Except all I got out of it was a solid blue screen. With limited time, I abandoned that idea and instead hooked up the TV's composite input, a process that involved going out and buying some batteries for the remote since there was no other way to switch to AV mode. Finally, at least I had some manner of display.

Next step was the floppy disk drive. The drive I used last time - several years ago - clunked when selected but wouldn't spin up. Fortunately I had a stack of them on hand, but I was fast running out when the 4th one I tried finally sprung to life. Popped-in my (Sockmaster) Donkey Kong floppy that I wrote all those years ago, and it loaded! I had also acquired a pair of joysticks since then, and couldn't resist a quick play since I'd never been able to actually play it before - wow!

Last time I wrote Coco disks with a 5-1/4" floppy in my PC; that machine is now long-gone and the floppy drive whereabouts unknown at this point. I found a few PC floppy drives, but unknown capacities. A moot point though, because I soon discovered my office PC BIOS doesn't support floppy drives. Next option was to power-up a few of the old PC motherboards sitting out the back, but I was running short on monitors and the state of the few power supplies I'd found was dubious at best. It just wasn't looking like it was going to happen that way.

Next option, DriveWire,but I needed to boot-strap the driver. CLOADM (cassette) seemed to easiest option so I grabbed my cable and attempted to download via the WAV file from the PC. All I could manage was "BOOT FAILED", and gave up after 10 attempts. Then I remembered my custom cartridge PCB's; after powering-up the positively ancient laptop connected to the EPROM programmer and waiting 35 minutes for an erase, I managed to burn a copy into ROM (and subsequently found another with HDBDW (HDBDOS-DriveWire) written on it!). That resulted in "BOOT FAILED" again, though I suspected this time what I needed was a DriveWire server on the other end.

Unable now to find my DriveWire cable, I was scratching my head because I knew I'd used it before. In the end I gave up, and on the drive home I realised that I'd used it on Coco3FPGA running on the TerASIC DE1 board, so the cable was different anyway - Doh!

Last resort was converting the Lode Runner files to WAV files and then loading the via CLOADM. When I finally found a utility to convert Coco BIN files to cassette WAV, I was disappointed to discover that it wouldn't work with multi-segment BIN files, and Lode Runner is definitely multi-segment. As an experiment I tried one of my small files and it wouldn't work anyway. I was defeated.

So at this point I am unable to get Lode Runner across to my Coco3, without either setting up a PC with a floppy drive (my preferred option) or making up a DriveWire cable. So I'm afraid I'm going to take my bat and ball and go home (not release the Beta) until I've done so. Sorry!

Thursday, 12 June 2014

Beta 2 release imminent!

Found and fixed the 'last' bug! The demo runs through all three levels in lock-step, as far as I can ascertain with the naked eye. As I mentioned, it's pretty solid evidence that the game logic is spot-on.

The issue was an uninitialised zero-page register that is used in determining when to update (move) the guards. Not sure exactly where it's initialised in the Apple II code (perhaps the bootloader, or maybe not at all), but I had to add explicit initialisation to a single byte to bring it into sync with the Apple II version.

Interestingly, this byte is never re-initialised, so subsequent iterations of the demo mode - if interspersed with an actual game - may end with slightly differing results on the 3rd level. This has been confirmed on the Apple II version as well.

Right now the game is running slightly faster than the Apple II version, but still pretty close. I won't bother fine-tuning it yet because the sound code will change all of this again.

The 2nd beta release will likely be tomorrow (Friday AEST) now. Although I don't plan to do any more tweaks to the program itself, there are a few things I'd like to do before the release. One of those things is to get it up and running on my real Coco3 - something I haven't personally done yet.

That just leaves the circular wipe, sound, all 150 levels and (hopefully) high score load/save!

One last subtle bug

I found the bug I mentioned in the next-to-last post, namely the guard dropping the gold in the wrong place right at the end of the 3rd demo level. I actually found it quite quickly - yet another missing piece of code! Although guards always drop the gold when falling into a hole, they also drop them under other conditions - at least when the code to do so has actually been written! Doh!

So having fixed the "last" bug I fired up the demo's again side-by-side - only to notice that the guards were re-spawning in different places at the end of the 3rd level. Since the whole game is deterministic (otherwise the demo wouldn't run) this can only mean a bug in my port. Damn!

After an hour or two of debugging I've discovered that the game state is out of sync somewhere in the first demo level, between the time the 1st guard is killed to the time the 2nd is killed. I know this because the re-spawn column, which is incremented every main in-game loop, is wrong for the 2nd guard. This can only be the case if the guard movements (guard state update) are inaccurate. Further debugging reveals that the state of the 3rd guard is wrong by the time the 2nd guard is killed.

Further debugging has thus far been fruitless but I'm yet to exhaust all avenues - it's just very, very late now and time to get to bed. One area of possibility I've yet to explore is the AI... and I'm not looking forward to that. So I'll continue when I next get the chance.

The one positive to come out of all of this is that, by the time I've found this bug, I can be 99.9% sure that all of the game logic has been ported accurately. The demo mode has been an invaluable tool in that regard!

Wish me luck!

Wednesday, 11 June 2014

Front and center

I thought I'd upload a quick video showing what I've been working on, including centering the display (thanks Jason) which I neglected to mention in the last post.


Note the centering of the display, the GAME OVER animation, and the high score initials entry.

And if for some reason you still prefer the monochrome graphics, they're still supported.

Hopefully I'll be in a position to release the final beta later tonight (AEST time).

EDIT: This morning I've been fine-tuning the 2BPP game speed and running it side-by-side with the Apple II. I've noticed that the demo seems to be running lock-step until right at the end of the 3rd level, just as the guards get to the top of the ladder... so there can't be too much amiss?!?

A whole stack of bugs!

Tonight I found no less than three stack-related bugs!

The most glaring was the fact that I was initialising the user stack, instead of the system stack (cut-and-paste error) which would eventually (due to the other bugs) overwrite the zero-page variable area and cause all sorts of issues - and almost certainly explains the crash and corruption reported by Keith! Yah!

I also noticed that the stack was ever growing downwards as I cycled through several games; by three (3) bytes if I obtained a high score, and two (2) if I didn't. In the high score entry routine I was pushing B onto the stack to juggle the 6502 registers, and branched over the pull in some instances. That explained the 3rd byte.

The other two bytes were a mystery, until I noticed that the high score entry routine was called from the main loop, but jumped back to it! A quick test on the Apple II version under the MESS debugger confirmed that the original version has the same bug! But because of the circular nature of the 6502 stack, I suspect it never manifests itself as an actual bug in the game. A different story of course on the 6809, hence the aforementioned overwriting of the zero-page area. I fixed it by pulling the extraneous two bytes from the stack before jumping back to the main loop.

All that remains now before the next beta release is a curious inconsistency that I noticed a week or so ago but ignored until now. It may occur elsewhere but where I noticed it was right at the end of the 3rd demo level, where the guard on the Coco3 version drops the gold on a different square than on the Apple II version. Perhaps related is the slightly different spawn-point of another guard and slightly different ending to the demo. I'm not sure at this point how difficult this will be to track down... it's subtle but of course does affect the accuracy of the game-play!

But the good news is that the only other features left incomplete are the circular wipe function, high score load/save, all 150 levels, and the sound. Everything else is there and running - and in 128KB (not 512KB as was required for the first beta)!

Taking another quick look at the circular wipe code today, I'm almost certain that I won't attempt to port it from the 6502 code, but rather write my own. And for the high score load/save, I've had an idea that utilises the task-switching capabilities of the Coco3 GIME that should allow me full access to the DECB ROM (and therefore the disk routines) relatively easily. That just leaves sound.

And then Castle Wolfenstein! ;)

Monday, 9 June 2014

More than meets the eye

Tonight I finally got the colour mode working - or at least I think it's working with the limited testing I've had time to do. I've literally seen it running for about 4 minutes and it's time for bed!



Turns out the complexities of the Apple II artifacting introduce subtleties that aren't immediately apparent when you're trying to reproduce it on a 4-colour display. I first noticed this when I got to the stage where my 2BPP rendering routines should have produced a faithful static display - yet I had gaps between my brick tiles.

After chasing red-herrings for a while it occurred to me that the tile data I had imported wasn't quite right - the bricks, for example, were only 9 pixels wide, not 10. So I went back to the MESS algorithm in my import routine, and deduced that the root cause was the fact that the artifacting is dependent on the bytes following the pixel in question! Because I was rendering single tiles in isolation, the artifacting algorithm wasn't producing the 10th blue pixel on my bricks.

I subsequently modified my import routine to render two (2) of each tile next to one-another, and lo-and-behold the gap disappeared! After (eventually) realising that I had to wipe the 2nd tile before importing the tile data, I finally had no gaps in the bricks and the graphics all looked, as far as I could tell, correct.

On this point, it is actually impossible to 100% accurately render the artifacting, because bricks adjacent to gaps or ladders or ropes are actually rendered only 9 pixels wide on the Apple II, whilst adjacent bricks are 10 pixels wide. It's also somewhat evident via the gaps next to the ladders. However, the effects are so subtle that they're practically undetectable, and they certainly have no bearing on game-play what-so-ever.

Similarly, there's some fringing effects on the guard and player sprites; however for the most part they are identical to what gets produced on the Apple II (according to MESS at least), except for complex interactions with multiple guards and backgrounds etc, and even then, they're subtle and again, have no bearing on game-play.

Overall, I'm very happy with the colour version and it certainly captures the look and feel of the Apple II version. And after several months of play-testing the monochrome version which, incidentally is the version I'm traditionally familiar with, it does look quite a bit nicer!


I'll do a bit more testing, and I want to attempt to centre the screen and also add the high score initials entry (tedious but trivial) before I release the next beta demo. That will probably be the last beta before the full release, which will include sound.

Saturday, 7 June 2014

More is less

Somewhat paradoxically, the tile data for 2BPP mode is actually less than that required for 1BPP mode.

Why? Because in 1BPP mode, 2 bytes are required per scanline to store 10 pixels (10 bits) of tile data. In 2BPP mode, 3 bytes - only 50% more - are required to store 10 pixels (20 bits). Note however that whilst four (4) copies of the tiles are required for 1BPP mode (corresponding to shifts of 0, 2, 4 & 6 pixels), only half as many copies (2) are required for 2BPP mode (shifts 0 & 2 pixels only). Hence the smaller data requirement.

This is also somewhat fortuitous because the title screen data has increased in 2BPP mode, and now it fits without having to beef up the compression.

I've imported the 2BPP mode tile data and hacked the rendering routines just enough to get the left-most 16 pixels of each tile displayed. Results below:

WIP modification of the rendering routines for 2BPP mode


The remainder of the modifications to the rendering shouldn't take too much time - I've already been through this with the TRS-80 Model 4 (Z80) port when implementing the pixel-doubling, which is actually equivalent from a memory-usage perspective.

At this rate I might even have the next beta - in colour - available for release in a few days!

Friday, 6 June 2014

Mysteries of Apple II artifacts

I took a look at the MESS Apple II video driver, and discovered that the artifact emulation (and there's no way of knowing exactly how accurate that is) is definitely more complicated than my quick 'n' dirty on-the-fly conversion.

So with this knowledge in mind, I hacked the MESS algorithm into my graphics conversion utility and managed to produce colourized versions of the title and tile graphics. Unfortunately the 2BPP title data is slightly larger than I bargained for, so I'll need to find a better compression algorithm, but that's for later. Here's the new colour title screen running on the Coco3, which in theory is identical to that rendered in the MESS Apple II driver:

4-colour title screen - in theory identical to Apple II display

And here is a screenshot from my utility, showing the original and colourized tile graphics:


The monochrome and 4-colour tiles, ready for import


So I now generate three (3) variations of the Lode Runner graphics; 1BPP and both monochrome and 4-colour 2BPP formats. I can build any variation simply by commenting (or not) each of a pair of .define statements.

The other area I've been working on today is the generation of the graphic data .BIN file. With thanks to Jason Law, I have a single .BIN file that contains the title and tile graphics data, that is generated not from binary data but in fact assembled from source .db statements. No more generating segments and binary data from a utility; Jason pointed out that it could all be done with .org statements in a single .ASM file! It also means that the memory map (including the graphics data addresses) can be defined in a single location in the source file - which of course is easy to tweak now!

Jason has also been hacking my code (in a good way) and has advised me on how to center the display on the Coco screen, and also get the code running on a 128KB machine. I'll be implementing his suggestions soon!

But for now, I need to finish the 4BPP tile import and then update the rendering routines to suit.

[And on this note, I've realised that the 4BPP mode will, in fact, affect the collision-detection algorithm used by Lode Runner. That's because I'm actually adding pixels to emulate the artifacting on the Apple. However, I would claim that it will not have any significant impact on the game-play.]

Game Over and Apple II colours

Firstly, I've ported the GAME OVER spinning animation. It was quite straightforward (although I had to convert the graphics format) but it looks pretty cool. Curiously enough, achieving a high score means you don't get to see the animation!

A few other fixes and enhancements; added support for the game freeze (pause) function, and fixed the key debounce on the extra life cheat and a few other CTRL key commands. I also added support for the Coco arrow keys, and also the Z & X keys for digging.

In preparation for colour mode, I've re-arranged the memory map to accommodate the larger screen memory required. To do so, I had to relocate the program code from $4000 to $8000, and the graphics data from $8000 to $C000. This presented a new challenge for me - how to load code at $8000, over the BASIC ROM.

I may have mentioned that you can load segments of a BIN file into arbitrary memory banks by having the previous segment load directly into the MMU bank registers to switch them into the 6809 address space. This is the method I've been using to load the graphics data into high memory, by writing a small utility to effectively wrap a custom .BIN file format around the raw binary data.

With the program code, however, the linker already produces a .BIN file which loads at $8000 - as I mentioned - directly over the BASIC ROM. So I wrote another small utility that relocates the .BIN file to an area of empty RAM, prepends a segment to set up the MMU bank registers accordingly, and finally appends a small loader that simply switches in the previously loaded memory pages and then jumps to the Lode Runner main program. The end result is a single binary that can load itself (effectively) over ROM.

With that working, I could turn my attention to implementing actual colours. Since I've been toying with the idea of reverting the title screen graphics data to the original 7-bit format to save some memory, I decided that I would (also) convert the graphics on-the-fly from 1bpp monochrome to 2bpp colour. After some preliminary investigation into how the Apple II colour artifacting actually works, I modified the (still 8-bit) title display routine to display 4 colours.

4-colour title screen generated on-the-fly from the original Apple II data

Not a bad result but the artifacting around the white characters is clearly emphasised, and doesn't gel with the results in MESS. I will probably need to do more thorough research, but it's a pretty good result for what amounts to a few dozen lines of assembler.

I should also note that I am preserving the ability to build 1bpp (mono), 2bpp (mono) and 2bpp (colour) versions of the game - all via .define directives. I could in theory use the same method to (inefficiently) generate the in-game graphics on-the-fly for the 4bpp modes, but there's probably little point. So my next task will be to produce 4bpp mono and colour versions of the tile data and update the rendering routines accordingly. I shouldn't imagine this will be particularly difficult, providing the colour generation falls out easily.

Once I have colour working I'll (hopefully) be able to add some more levels and release a new Beta.

Finally, there is a report of the game crashing (twice) in VCC. At this point I don't have a lot to go on so please, if you do get a crash under emulation, I'd be interested in a screenshot (if there's any corruption) at least. And if you happen to be running it under the debug build of MESS, a full dump (SAVE) of the memory space would be much appreciated!

Tuesday, 3 June 2014

Lode Runner Playable Demo Beta 1

The remaining 'collision-detection' bug turned out to be a typo and also missing code from the end of a routine! I normally add a place-marker for code that is yet to be ported, but I'd obviously neglected to do so in this case.

The missing code in question, which amounted to just a handful of lines, is particularly interesting because unlike the rest of the collision-detection code which uses the logical playfield, it actually inspects pixels rendered during the draw_player_sprite() routine. This will have ramifications for ports to sprite-only systems, like the Neo Geo, and will likely require that the port maintains the bitmap screens in system memory even though they aren't used for the actual display.

Here's a video of the demo mode running for the 1st level:



That aside, the end result is that Lode Runner is now complete in the sense that it is 100% playable on the Coco 3. There are a few bells and whistles that have yet to be ported, so whilst I work on those I thought I'd release a playable demo for beta testing.

Please read the included README.TXT file before submitting any comments, suggestions and/or bug reports, but feedback is most welcome.

Without further ado, here's a link for an archive with the DSK file.

EDIT: I should add that I'm yet to run this on a real Coco! I plan to do that sometime this week!

UPDATE: I've fixed the problem with not being able to exit the demo. Please re-download.

Still not quite there

Today I worked on implementing the game speed throttling accurately. The speed throttling is interleaved with the sound routines in order to maintain a constant speed; until I add the Coco 3 sound routines it's not going to be 100% accurate. But it's quite close anyway and certainly more than good enough for a beta release.

I also added a few of the easier-to-code missing features, such as high score table, update and (non-destructive) display. The only part missing is the initials entry - they stay blank for now - and of course load and save.

I also fixed the graphical glitch when digging is interrupted by a guard.

That just leaves one (that I'm aware of) niggly bug which I'll address next session; namely the 'collision detection' isn't consistent with the original. It's all done on the logical board, not the graphics screen, so it shouldn't be too difficult to track down.

Once I'm satisfied that there's no latent bugs, I'm intending on releasing a playable beta demo release that will feature the first 5 levels. The beta will otherwise be completely playable, albeit monochrome without the circular wipe and game over animations, sound and high score initials entry. The release will hopefully encourage people to help me play-test, and also whet people's appetite whilst I'm finishing up the port.

I've also tentatively added the scoring support for Championship Lode Runner which I believe is almost identical to the original, aside from the ability to enter messages on the high score list. I'll probably stay true to the original format and release the two variants separately.

I'm also seriously considering (again) releasing it in cartridge form. It would be nice to have something tangible for the Coco, but the cartridge case is the real stick-in-the-mud. Do I take the path that others have in the past for other platforms, and do a limited run using sacrificial carts?

Sunday, 1 June 2014

Getting there

Fixed another 3 bugs; 2 in the AI and another in the guard re-spawn routine. In one case I hadn't flipped a BCS/BCC when translating, the other two I didn't realise that SEC, SBC actually performed a subtraction without borrow on the 6502! Why did they invert the Carry flag???

The guard AI is so close now I can't even say for sure that it's not complete and accurate. The game is certainly playable and seemingly just as challenging as the Apple II version.

What is throwing things a little off atm is the speed of the guards. It's telling on the demo screen that the guards do choose the correct path, but lag behind the Apple II somewhat and as a result the demo doesn't play properly. I implemented the guard speed logic in haste the other night so I guess it's time to go back and verify that.

Back to the 4-colour mode; I think I've deduced that it won't be possible to emulate both mono and colour modes with the same tile data. I've not sat down and thought it through properly either way yet, but I'm pretty sure I've reached the right conclusion here. No matter...

Saturday, 31 May 2014

Friday night musings

I found a few spare minutes tonight to work on fixing the AI; managed to find the graphical glitch (took about 20s) and another 4 sections of code that had bugs. Much to my dismay, the guards still run in the wrong direction on the first demo level.

For those interested, the debugging process atm consists of opening both the Apple II and Coco 3 versions in the MESS emulator side-by-side, and running them (manually) in lock-step, comparing key results throughout the AI routines. Painful but a no-brainer! And it's actually fortunate in this instance that the very first guard starts off in the wrong direction - it should mean that the first pass through the AI logic will reveal most of the bugs! I mean, I've found 4 bugs already and I've only stepped through about a quarter of the AI logic!

It might seem to some that there are an awful lots of bugs in the AI code (I'm looking at you James) but you need to remember that I've added over 700 lines of 6809 without much visible feedback along the way. When porting the mechanics of movement, I was able to code small chunks of routines and - usually - immediately see whether or not it actually worked. And then fix the bugs before blogging about them!

I've also been thinking a bit about the colour version. I'm pretty sure that with clever use of the palette I'll be able to render both colour and monochrome versions of the Apple II display in the Coco3's 4-colour mode using the same graphics data. This of course means there's no reason to retain the 2-colour version of the game... though being the pack-rat that I am, it'll probably remain in the source only .ifdef'd out.

And that also goes for the Neo Geo version, of course. On that note, I've decided to tackle an automated static translation of the original 6502 code - it should be an interesting exercise in itself! I guess once I've got a 68K source base, I could also look at porting to other platforms such as Amiga, Atari ST and some other more obscure platforms.

But for now, back to debugging...

Friday, 30 May 2014

Mostly Playable

Tonight I finished porting the guard AI. I also did a quick audit of the ported code and discovered a few minor routines that I hadn't done and also a few lines here-and-there related to, amongst other things, the speed of the guards that I've subsequently completed.

However, there are clearly one or more bugs in the AI code (one of which causes a graphical glitch - they're generally easier to find) but nothing too major. The guards do wander around and occasionally act intelligently but more often than not get stuck or stand still. Regardless, it's a major milestone and within a session or two I'm hoping to have the demo screens running correctly and a 100% accurate and fully playable game!

It's also very good to note that without the delay loop (hack) in the main game loop it still runs too fast! Once I've ironed out the above-mentioned bugs in the AI code I'll port the original game speed throttling code, and then release a demo for beta testing whilst I attend to the rest of the missing features I detailed in my last post.

Lode Runner is approaching 4,200 lines of 6809 and it's interesting to note that my Neo Geo port of Donkey Kong is roughly the same size (68K code of course) but is only 50% complete!

I've been thinking a bit about a Neo Geo port of Lode Runner; hardware platform issues aside, it probably wouldn't be too difficult to write a 6502-68000 translator, especially given my now-intimate knowledge of the code base - even if it was in part Lode Runner-specific. That plus the fact that the rendering routines would be replaced with much, much simpler sprites, it may not be a lot of work to get something running! Food for thought...

Wednesday, 28 May 2014

More on the AI and overall progress

Last night I finished commenting the guard AI code. FTR there's approximately 700 lines of 6502 assembler to produce almost exactly 1KB of object code for the AI. It's straight-forward enough to decipher on a line-by-line basis; it's when I try to wrap my head around the algorithm as a whole that it takes a few more brain cells. I'm most of the way there I think.

It also doesn't help that one of the first sections of the algorithm that I tackled has a bug. I'm yet to confirm this, but I believe that this bug is (at least partly) responsible for the instances where the guards actually run away from the player. You may be tempted to suggest that it's a feature rather than a bug, but the very nature of it suggests to me that it is indeed a bug, even if the behaviour was an unintended side-effect that Doug Smith decided to retain.

Roughly speaking, as far as I've deduced the guards attempt to get themselves - first and foremost - onto the same level (row) as the player, and the search algorithm for a path is quite exhaustive, which means a lot of code gets executed. When scanning down to see if the guard can get to the same level, it (also) checks each side of that column to see if there is a route to the left or right. Checking the route to the left is OK, but when checking to the right, under some circumstances the aforementioned bug causes it to check the wrong row. So it sometimes sees an obstruction when there isn't one, and will run away when in fact the guard is only a few (empty) tiles away from the player. Other times the guard will get stuck trying to follow a non-existent route (e.g. when you see them looping on ladders).

Anyway, I'm yet to port the code and when I've done so, I'll experiment more to document the exact behaviour caused by the bug. I can also 'fix' it and see if the game is any harder.

I also did a quick 'audit' of the original code and I'm satisfied that I've identified most of the code and that those sections that I haven't commented can be attributed to the level editor or other sections that I know about but haven't ported yet. On this note, a list of what is yet to be ported includes:
  • Accurate game speed throttling
  • Circular wipe at the start and end of each level/life
  • Spinning 'GAME OVER' text animation
  • Restoration of game screen after High Score screen displayed mid-game
  • High score table (itself)
  • High score determination and name entry
  • Storage and loading of the entire 150 levels
  • And last but certainly not least - sound!
EDIT: updated list above

 Aside from the above, there's only the matter of saving/loading high scores (if I opt to implement that) and of course the level editor, which I have no plans to port at this stage.

And for the case of the Coco3, it'll be tight but I still believe it will be possible to have a 4-colour mode version of the game. The cartridge version is looking a little less likely at this stage, at least without some fancy bank-switching hardware on the cartridge itself.

I've also come across a few small sections of dead code. This includes a look-up table that determines the time that a guard will remain in a hole before attempting to escape, whose index is determined not only by the number of guards on the level, but also by an unknown variable whose value never appears to be set to anything other than zero - unless there is a problem loading/displaying the level!?! Weird...

Right now I need to finish porting the AI and then ensure that the demo levels run correctly. Once I'm satisfied that the game-play is intact and 100% faithful to the original, I'll release a playable demo of the first 5 (or so) levels whilst I finish off the bells and whistles.

Monday, 26 May 2014

The guards are getting smarter!

As I mentioned, the AI for when the guard is on the same row as the player is quite simple; if there's a direct path to the player, then move towards the player! Pretty intuitive stuff.

So this much I've implemented, and I can confirm that it's enough to get the guards escaping from the holes if the player remains on the same level. Yah! I did discover another minor glitch though - when the guard interrupts the digging it isn't cleaned up properly. I'll get to that in due course...

This morning I hit memory problems again (the code is about 3,500 lines and assembles to about 8KB now), so it was time to move the title screen data out of the source code and load it into high memory. Here's the breakdown of the Coco's 64KB memory space so far:
  • monochrome screen #1 $0000-$1DFF (8KB)
  • monochrome screen #2 $2000-$3DFF (8KB)
  • 6502 zero-page memory variables $3F00-$3FFF
  • program code & data $4000-$6DFF (assembler output)
  • monochrome tile data (4 sets) $8000-$A3C0 (pre-loaded from a disk file)
  • monochrome title data $A800-$B993 (pre-loaded from a disk file)
I need to keep in mind that the colour mode will require double the video memory (32KB) which will shift everything up by 16KB and basically then occupy every (8KB) page in the 64KB addressable memory space. Hence the level data will need to be stored in high memory and switched-in as required to generate each level. Or I could swap the DISK BASIC ROM back in and load the levels from disk (potentially messy since I'll need to be mindful of ROM buffer/memory requirements). Haven't decided which way to go on that just yet.

Each colour tile will require twice the data, but since I'll only need two (2) sets instead of four, it should occupy the same space. Likewise since the title screen data is stored in RLE format, I'm not expecting it to require too much more memory either.

Anyway, onwards with the AI for now...

Saturday, 24 May 2014

Monkey See, Monkey Do

I've finished - but not completely debugged - the mechanics of the guard movement.

There's no AI to speak of yet; I've implemented some test code whereby the guards simply mirror the player or, more correctly, the keys held down by the player. Here's a short video to show the guards all moving, falling into holes and re-spawning.



You'll notice they'll actually start to climb - and then subsequently fall - whenever the player tries to move up, regardless of whether there's a ladder there or not. I started to debug this behaviour and then discovered that there was nothing at all in the guard movement code preventing this from happening! Turns out that the code relies on the AI routines to not even attempt to move up without a ladder.

To this end I've started to comment the guard AI. I was pleasantly surprised to find that the logic for when the guard is on the same row as the player is quite straight-forward. That got my hopes up that the rest of the AI would be just as simple - alas that's not the case at all. It gets significantly more involved when the guards are on a different row...

I'm still not sure whether the guards escaping from the holes is driven by the movement mechanics or the AI - they don't yet do that correctly as you'll notice in the video. From here-on in it's a matter of reverse-engineering the AI, adding it in sections, and continuing to test the movement until I've ported every line and the demo plays correctly. On that note, the re-spawn points are deterministic, and I suspect there's no random element at all to the AI either - I can't see how the demo would work if there was.

Getting down to the business end of the port now!

EDIT: After implementing a small part of the AI, it seems that the guards' escaping from holes is actually driven by the AI, not the movement mechanics. It's possible then that the mechanics are complete and working. Onwards with the AI now...

Friday, 23 May 2014

Left, right and up!

Fixed a few more glitches - including the 1st frame glitch - and added right and up to the guard's repertoire. As for movement, only down to go, although there are still a few more minor issues with the guard movement as a whole. The guards also die and re-spawn.

I'll press on with adding down and then look at solving the remaining issues.

Aside from the AI, I really am starting to round out the code. I'm missing the high score entry routine, and the circular wipe, but there's not a lot else aside from the editor, which I'm not planning on porting. I'll need to write my own level data access routines, which will likely be bank-switched into memory to negate the need for any DOS (and also facilitate a cartridge version).

But, I'm getting ahead of myself here. The immediate task is to complete guard movement.

Thursday, 22 May 2014

Still cranking and squashing

Squashed another handful of bugs in the guard code, but still not done!

Discovered in the process that the player movement code also had a bug; the rendering looked fine on the screen but it didn't update one of the 'logical playfields' correctly - effectively leaving a clone of the player on top of every ladder they've climbed. Made it somewhat easier for the guards to kill the player!

I've deduced that the unknown guard state variable is, in a nutshell, the state of the guard. I'm yet to work out the meaning of all the different values, but 7-12 mean that the guard is wriggling to get out of a hole and - I think - negative means he's carrying gold!?! There's a bit more to it, too.

The guard state is also influenced by other variables, including an initialiser in the main game loop that takes into account the total number of guards on the level, amongst other things. A look-up table is then used to calculate the actual initial value. This is unexpectedly complicating matters somewhat, as the 'wrong' initialiser value causes guards to behave improperly.

Anyway, the guards all run left (and fall) properly now (except for a graphics glitch after the very first frame of gameplay), but are yet to be killed by the holes filling in. That I'll be implementing next session, and will hopefully shed further light on the guard status byte.

Still plenty to do, I'm afraid.


Wednesday, 21 May 2014

3,000 lines

Wasn't going to post but I had a little bit of a win tonight. And I should mention that the 6809 code has reached approximately 3,000 lines (sans data).

I've got the guards running/swinging left (and falling) with the player, albeit with a handful of glitches on the screen and in the logic (eg. they tend to leave 'holes' in the bricks occasionally). But after porting all the 'scaffolding' code for the guards (look-up tables, calculation routines, etc) the mechanics of moving are in place and after fixing the bugs - which I suspect won't be too difficult - I'll just need to fill out the routines for the other 3 directions. That'll be a case of simply cranking the handle for a few sessions.

After that there's a bit more logic to fill out to do with guard status, picking up and dropping gold etc but that's all fairly straightforward - although I must admit there's a couple of memory variables related to the guards whose function I'm not 100% clear on.

I also took a quick peek at the guard AI routine just to gauge how much code there was, but stopped looking after scrolling down a few screens... mine's a bit simpler:

guard_ai:    ; $70D8
; A=col, B=row
; ret: B=0..4 (direction)

        lda     *key_1
        ldb     #1
        cmpa    #0xca
        beq     9$
        ldb     #0
9$:     rts
               

It effectively says, "move left if the player tries to move left, else don't move".

Sunday, 18 May 2014

Guarded optimism

I've spent the last few sessions - several hours - reverse-engineering the code for the guards.

I've long suspected (and by long, I mean a good quarter of a century) that the design of the guards - in the player's image - was solely to enable the use of the same movement logic & code. As it turns out, I'm only half right; the code is very, very similar but it is duplicated in its entirety for the guards.

The good news is that it's very simple to reverse-engineer, for the most part, as a lot of it really is a carbon copy of the player movement code. The bad news is - there's an awful lot of it! More than the player movement code because it needs to handle 5 guards, and it needs to handle other logic like re-spawning.

There are three main areas of guard code that I need to implement; the death of the guards when they fall into a hole and get filled-in (fairly trivial), the movement (both AI and mechanics) of the guards, and the re-spawning of the guards when they are resurrected.

Of course the guard code only deals with the current guard; a table of state data gets copied to-and-fro for each of the guards during the main loop iteration. The guards also need a bit more state data than the player, such as dead/alive and whether or not they're carrying gold.

As it is, I've probably done enough to get a start on the porting, and the rest should come out in the wash while I'm doing so. I've located the AI routine but haven't yet peeked inside it - that will come last. I've already decided that for testing the guard mechanics, I'll simply have them mirror the player's movements, which will of course allow me to manoeuvre them manually. Furthermore, I've already worked out exactly how to do that!

Given the amount of code that needs to be ported, I'd expect it'll be a week or so before I have the mechanics in place, but I'm optimistic that it will be quite straightforward.

The AI is another issue altogether.

Friday, 16 May 2014

Freeing up memory

As I mentioned in my previous post, I've hit the (free) RAM limit on the Coco. With 16KB reserved for screen memory, and 32KB reversed for BASIC and DISK ROM, that only leaves 16KB for all the code and data for Lode Runner, before I need to start loading in sections.

I went back to my old Tutankham port to see how I handled loading of the numerous bank-switched ROM images, expecting to find a loader that I had written. What I (re)discovered was a much neater solution; a multi-segment .BIN file that updated the MMU registers directly during the load, and restored them on completion. So it was simply a matter of updating my tool to produce a .BIN file for the tile data (in addition to ASM .db statements) that would load itself into banked memory.

And to make my life a little easier, I wrote a small BASIC loader to streamline the now-multi file loading operation - something I've already done hundreds of times during the course of this port.

With the tile data loaded externally, I've been able to restore the title screen and a handful of levels, and I still have 4KB of code/data space remaining. Eventually I'll move the title and level data into external files as well, possibly loading the levels from disk, and implementing high score load/save.

And there's always the cartridge version...

So, now onto demo mode!

UPDATE: I've now implemented the demo mode - it was even easier than I dared hope! A simple table look-up that pokes keys into the key input registers, with a counter for each entry that determines how many game loop iterations the 'key' is held for.

BUT: it didn't take long to discover that the demo mode wasn't going to work properly without the guards - only a few seconds into the demo and the player digs a hole, the guard falls in, and the player runs over the guard. But without the guards implemented...


No worries, it's all implemented and now it's time to tackle the guards!!!

A 'hole' lot more...

In a nutshell, the player movement and interaction with the environment is complete. Running, climbing, swinging, falling, digging and collecting gold is all done, and the holes now fill themselves in, killing the player if they happen to be in the hole.

Here's an updated video,  showing the first 2 levels of the game. I've had to remove the title screen due to memory restrictions on the Coco3. I've also removed the guards from the game entirely because they affect the ability to dig. In the video I purposefully fall into a hole to show the player losing a life, and then use CTRL-R to end the game.


All that remains now, as far as I believe, is the demo mode logic (just a large look-up table) and the logic related to the guards. I'm sure there's also some housekeeping stuff I'm missing as well (like high score entry), but that will fall out in the wash.

The code, without the large data tables, is heading towards 2,500 lines now - roughly 4.5KB of 6809 object code. With the graphics data and a handful of levels the executable object is ~16KB.

To be honest, I've been quite pleasantly surprised by how smoothly the port has gone, and how easy the reverse-engineering has proven to be thus far - especially given my lack of experience with either the 6502 or the Apple II. It has certainly been easier than (arcade) Donkey Kong, for example! I can only hope that the remainder doesn't throw up too many challenges, though I suspect the guard AI will be the real thorn-in-the-side!

The next task is to get the demo mode running before I move onto the guard logic. I'm not expecting too many issues there, as it is little more than a large table look-up, and it should run correctly even in the absence of the enemy AI.

Thursday, 15 May 2014

Scaffolding

A surprisingly productive day today!

Managed to complete the left and right digging, though holes are yet to be filled-in.

The rest of the progress was scaffolding around the main loop and in-game keys. There's a proper distinction between attract mode and game play mode now, and you can exit from the former. The high score display screen (with dummy data) is also in the outer loop now, and it all transitions properly, and the correct game levels are displayed in both demo and play modes.

There's a bunch of in-game CTRL key functions including killing your player (for when you get stuck in holes that enemies can't get to), adding an extra life, skipping to the next level, freezing the game, terminating the game, and displaying the high scores. Most of these have been implemented now, as they are very handy for testing!

There are now 5 game levels - in addition to the 3 demo levels - and I'll probably leave it at that when I release a playable demo due to space restrictions. In fact, I'm almost at the limit for the Coco3 now (16KB program space from $4000-$7FFF) without having to resort to writing loaders to shift data into high memory.

The two functions I want to complete next are filling in the holes, and running the attract mode logic. (once these are complete, all that remains is the code for rendering and the enemy and the AI). I've identified both but am yet to decide which to implement first. The latter will be easier, but won't work properly until the former is complete. Decisions, decisions...

Wednesday, 14 May 2014

Diggin' it!

Some more good progress today!

When you collect all the gold, the end-of-screen ladder appears and climbing to the top awards the end-of-level bonus (1,500 pts), taking you to the next level. To this end I have included the three demo levels to complement the 1st in-game level.

I've also implemented digging (to the left); you can dig the hole but it will never fill in. The (same) digging routine is actually re-entered each iteration of the in-game loop to sequence through the digging animation. There are still some issues with it, but it's looking good... I'll do a video once digging is complete!

Whilst the porting continues, I'm also chipping away at the reverse-engineering as I work. The in-game loop is starting to take shape and I can see where the holes are filled in, and the enemies are re-spawned once they die - although I'm yet to comment these in any detail.

Once I've completed the digging routines, I'll do the fill-in and then I'll investigate what is required to implement the demo. I should then be able to round out the outer loop with title screen, attract-mode demo, and high score table.

A very quick scroll through the listing suggests that I have commented a good portion of the code thus far. Once I've done the above-mentioned, it really just comes down to the enemy rendering and AI. The remainder of the code must then be the level editor. Still a lot of work to do, but I am just beginning to see the light at the end of the tunnel!

Monday, 12 May 2014

A video is worth 1500 lines of assembler

Today at lunchtime, and earlier this evening, I managed to get the player movement done, including gravity, and even had time to add the collecting of the titular gold 'lode'.

So without further ado, here's a video from MESS of Lode Runner in action on the Coco3:



My dilemma now is whether to continue the momentum with the Coco port - and put the Z80 version on ice - or take a step back and bring the TRS-80 version up-to-date. I'm concerned that the bandwidth for the Grafyx Solution hires board is simply not up to the task, without some optimisations, and quite frankly the prospect of porting the indexed-indirect code to the Z80 isn't exactly appealing.

At this stage I'm leaning towards continuing the momentum with the 6809 port, and getting the end-of-screen ladders appearing, then moving on to the player moving around in the attract mode, adding high scores, and getting the main loop completed.

Late Sunday Night Update

I've been making very good progress over the last week. I've managed to find time for a few sessions of coding but I soon discovered that there was more code to write than I'd reckoned on.

I'd taken a few shortcuts previously on both the Z80 and 6809 ports. But now I'd reached the stage where I had to fill in the gaps.

First, I needed to implement the second hires page. I'd reserved the memory, but hadn't coded the routines to read the current page from the zero-page variable(s), so I implemented that. Relatively trivial, but I should note that the Coco now requires 2*8KB=16KB just for the mono screens (as does the Apple II, incidentally) . With the Coco ROM's that doesn't leave a lot of memory, and in fact for now I've removed the title page so I don't need to worry about loaders and switching out the ROM's just yet...

When the level data is first read from disk, a full sector (256 bytes) is read into a disk buffer in low memory. Since each level is 28*16=448 bytes, the level data is packed into nibbles. Thus the sector is subsequently unpacked - not into one but two (2) different buffers - static & live. I had only coded the one copy in order to display the level. Now it does both of course.

And when the level is rendered, it is actually rendered to the 2nd hires page, and then copied to the 1st during the famous circular wipe transition. The program then goes through and wipes the player and enemies from the 2nd page, which is used as the background tile-map during the game to make the sprite emulation more efficient.

So I had to render to the 2nd page, and then I do a straight copy to the 1st (as I'm not attempting the circular wipe at this point). I also added some debug code to toggle the displayed hires page with the <ENTER> key.

Then it was on to the player movement routines, which comprises reading the keyboard, checking the aforementioned level data to ascertain if the player can move, and then emulating sprites using the two hires pages. Here there was a reasonable amount of code to implement, including two basic rendering routines that weren't used for the level rendering, and a handful of support routines that calculate address offsets, pixel shifts, sprite-to-character mappings, etc. It was tedious and error-prone more than anything.

I've discovered that in some cases, the 6502 is actually more efficient than the 6809 - or at least my limited knowledge of the 6809 is preventing me from a line-by-line translation. On the 6502 it's possible to specify an offset (in a register) from a 16-bit address stored in zero-page memory; on the 6809 I can't see how to do this, so for now I've been using 2 instructions to compensate. Otherwise, the main source of confusion is mapping the A,X & Y registers to A,B & X/Y on the 6809. For the most part I've been able to get away with just A&B, since most routines only return one or two values (though sometimes in X and sometimes in Y) - but there's one routine that returns three values in the three 6502 registers, so it gets a little messy with the 6809's 16-bit X register.

As for actual progress, the player can now both run and swing left & right and climb up ladders. In truth, there's a few ladders on the 1st level that you can't (yet) climb, so I need to find that bug. But otherwise, it's working perfectly. Climbing down is just a matter of cranking the handle, and I've simply run out of time.

The good news is that most of the hard grind - the mechanics of rendering - has been done and the movement routines are relatively straight-forward. I also need to add gravity, but I recall seeing that in the Apple II disassembly so that shouldn't be too difficult either.

Once I've got the player moving around everywhere, and falling, I'll post a video of the Coco3 version on this blog. And then I guess I'll roll up my sleeves and bring the Z80 version up-to-date. To be honest, I'm not looking forward to that as there's a lot of index-indirect addressing mode code and the Z80 is going to be horrible (ADD HL,DE).

Tuesday, 6 May 2014

Brief update

I've identified the main game loop, the keyboard read routines, and commented most (95%) of the movement routines - definitely enough to start porting and see the results.

There's a decent amount of code that needs to be written before I'll see the player moving around on the screen. It's probably not something that can be written in a single session. I also need to properly implement the dual screen logic as it is used extensively in the movement code, for example.

For this reason, I've decided to update the Coco3 (6809) port first. It's a bit simpler than the TRS-80 port since for the latter I'll need a shadow copy in RAM of the port-mapped hires screen, and hence I'm unable to make use of dual-purpose routines. The latter is also slower and more painful than the 6809 port - so much so that I'm actually tempted to put it on ice for the moment.

Next time I sit down to work on this I'll be able to start on the Coco3 port!

Saturday, 3 May 2014

Spaghetti?

No more porting but I have spent some time on the reverse-engineering.

I've located the player movement (and dig) routines, which I eventually tracked down via the keyboard read call. I'm working through those now and have unearthed a few more crucial variables related to the player tracking throughout the play-field.

It's relatively early days yet, and I reserve the right to retract my statements, but I find some comfort in what I've found so far. Way back some 20+ years ago when I was attempting to write my TRS-80 version, I naively coded the player movement routines by handling each case explicitly in what equated to a rather lengthy case statement. It was classic spaghetti Z80 assembler, and whilst I knew it wasn't elegant, I was too eager to see results to attempt to formulate a more efficient algorithm.

On the surface, that appears to be pretty much how the original code was written. There's a ton of duplicated, cut 'n' paste code related to movement from what I've seen so far; perhaps not as bad as the code I first churned out but certainly nowhere near as elegant as the code that I finally crafted - albeit in its 3rd incarnation - on the PC. At least, it seems to be the case as far as I've gotten at this point.

It's also somewhat reassuring to note that the variables I've managed to identify thus far are heavily used throughout most of the codebase, in fact a surprisingly large percentage of the code seems to be concerned with manipulating these very variables, mostly related to movement (presumably of enemies and the player). If I'm right in assuming the same logic is used for both, then I guess there's little more to the actual game mechanics, other than digging (which should be relatively simple) and enemy AI.

What this suggest is, in stark contrast to a few other projects I've undertaken, that the actual reverse-engineering effort may be relatively straightforward, and somewhat devoid of instances of large sections of code whose functions defy explanation without some serious time & effort and even some guesswork and trial-and-error. That would be nice for a change!

I'll continue with the reverse-engineering for the time being as there are a few aspects of the movement that I'm yet to decipher that would prevent a functional port at this point. But I'm still on a roll and would expect that it won't be too much longer before I can draw a line in the sand and start the implementation of the movement routines.

I'm also sorely tempted to break with tradition and start with the 6809 this time 'round. We'll see...