Porting Meteor Mission II to Microbee

Part 3 - Development Environment and Title Screen

This article continues on from Part 2 - Basics and First Run.

Now that I'd got to the point of being able to build and run something I needed to setup a build/run environment to make debugging as painless as possible. There's going to be alot of build/run/debug cycles before this thing is finished so anything that streamlines that process can only help.

For this type of work, I find Sublime Text works really well - it's without doubt my favourite text editor and well worth the very reasonable purchase price (particularly when you consider it runs on Windows, Linux and OSX). Anyway, Sublime has the ability to invoke build tools including make files.

Here's the makefile I'm using:

all: meteor.tap

meteor.tap: meteor.bin
	bin2tap meteor.bin meteor.tap --loadaddr:0x900 --startaddr:0x900

meteor.bin: meteor.asm
	zz80asm --list meteor.lst -o meteor.bin meteor.asm 

It's very basic and simply invokes the same commands as those used in the previous part to build the .TAP file. By putting this in the project folder I can now simply hit Ctrl+B to get a new build. (be sure to turn on Tools -> Save all on build).

Taking this a step further, Sublime can also invoke different make targets. For this to work I edited Sublime's Make.sublime-build rule file (see Preferences -> Browse Packages and look in the Make subfolder):

{
	"cmd": ["make"],
	"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
	"working_dir": "${project_path:${folder:${file_path}}}",
	"selector": "source.makefile",

	"variants":
	[
		{
			"name": "Clean",
			"cmd": ["make", "clean"]
		},
		{	// ADDED THIS
			"name": "Run",
			"cmd": ["make", "run"]
		}
	]
}

Next I added a new build target in the makefile:

run: meteor.tap
	/cygdrive/z/retro/ubee512/ubee512.exe pc85b --tapfilei=./meteor.tap --conio --exit-check=off --debug=on

This is simply invoking ubee512 with all the options to have the tape ready to load, console window enabled, don't confirm on quitting and turn on debugging. Also, I can setup breakpoints by adding them to the end of this line eg:

run: meteor.tap
	/cygdrive/z/retro/ubee512/ubee512.exe pc85b --tapfilei=./meteor.tap --conio --exit-check=off --debug=on --bp=0x900

Now all I need to do for the build/run/debug cycle is hit Ctrl+Shift+B, then type "load" in the emulator and I'll land on my breakpoint. Nice!

Graphics Mode

So with that bit of project management out of the way, it was back to the task at hand and the obvious first thing to do was get the Microbee's PCG character set loaded up with the TRS80 style lores graphic characters. The Microbee's BASIC ROM has a function to do this at 0x8027. So right at the top, just after setting up the stack I added a call for that:

       ORG      900h

data:           equ     03800h
vram:           equ     0f000h
stacktop:       equ     08000h
basic_rom_lores: equ     08027h

       ; Entry Point
       ; Referenced from 4C04, 536A, 537A, 656C, 657D, 658E
       ; --- START PROC L4500 ---
L4500: DI
       XOR     A
       OUT     (02h),A
       LD      A,38h   ; '8'
       OUT     (0ECh),A
       LD      SP,stacktop

       ; Load lores PCG graphics
       CALL    basic_rom_lores

Ran it and things started looking a lot better (pretty close to the screen shots below). I did notice some quirks though:

  1. the explosion animation at the start seemed to run for too long with one "particle" arriving very late and running at a weird angle across the screen.
  2. the very top left character - the corner of the bordering box - went missing a few seconds after the complete title screen appeared.
  3. I noticed while running under the debugger with tracing enabled (ie: slowly) some extra block characters appearing at the very left of the scrolling message at the bottom.

Although these are appear as minor artifacts they're indicative of deeper problems so I try to sort out little issues like this as soon as I notice them.

Fixing Issue 1 - The Stray Particle

The first thing I tried was to relocate the data area back to its original position to see if that resolved the issue (ie: changed data: equ 0x3700 to 0x7300). And yes this stray particle disappeared. I then tried some other addresses and the problem didn't recur. Finally setting back to 0x3700 and the problem recurred. Double checking my maths revealed the problem - I was overlapping the last few bytes of the program. Changed it to 0x3800 - problem fixed.

Fixing Issue 2 - The Blank Character

This one was little harder to find. In this case I knew I was looking for an errant write to memory address 0xF000 (ie: the first character in video RAM). To track this down I used ubee512's debugger and tracing capabilities.

First I configured the Console window to show as many lines of history as possible (9999) and then restarted the program and let it run at full speed up until about 1 second before the problem occurred. I then hit EMUKEY+\ to turn on tracing which slows things down and then as soon as the character disappeared I hit EMUKEY+BS to stop the program and looked at the trace.

Backtracking through it wasn't hard to spot the HL register with value 0xF000 which I then cross referenced to the instruction writing to that location. Turned out to be this:

L4C41: LD      A,(HL)
       CP      80h
       JR      NC,L4C6E
       CP      60h     ; '`'
       JR      C,L4C6E
       PUSH    HL
       LD      HL,L4C70
       DEC     (HL)
       POP     HL
       JR      NZ,L4C6C
       PUSH    HL
       LD      HL,vram			; <-- there's the 0xF000
       LD      A,(HL)
       LD      (HL),0C0h
       LD      L,(HL)
       LD      (3C00h),A        ; <-- Oops
       LD      A,0C0h
       CP      L
       POP     HL
       JR      NZ,L4C66
       XOR     A
       JR      L4C68

Just a few lines down I spotted a missed reference to video ram. Searching for regex "3C..h" found two others as well. Problem fixed.

Fixing Issue 3 - Blocks in the scrolling message

The third issue was also a difficult one to track down, but in the end I noticed it by accident. Basically I tracked down the instruction writing the block character and then back tracked to where it got the address it was reading from. In that process I just so happened to notice the value 0x5068 in one of the registers. This seemed odd since I was also working around the label L5608 - which should have been relocated to a completely different address. More back tracking and I eventually stumbled across this:

L460F: 
       DB      67h     ; 'g'
       DB      50h     ; 'P'

Which is the equivalent of (0x5068-1) ie: a hard coded address reference in the program's data. Not surprising that I didn't notice it earlier (and I hope there aren't too many more of these). Once found the fix was simple:

L460F: 
       DW     L5068-1

Title Screen Finished

So now the title screen works... if you've seen Meteor Mission before these screens will look familiar.

meteor_port_2.png
meteor_port_3.png
meteor_port_4.png

Note that although all the animations were running (the explosion, the scrolling text at the bottom) the speed was wrong. The TRS80 runs at 2Mhz whereas the Microbee runs at 3.375Mhz.

Next up though is to look into keyboard handling.

Porting Meteor Mission II to Microbee continues with Part 4 - Keyboard and Flashing Text.