My First Plot Routine

ST Software Begins

In 1983, Steve Turner started to write Spectrum games for a living. He took the courageous step to give up his IT job and start working from home. We played in a band together, and used to tour the local ale houses on a Friday evening together in search of good beer and arcade machines. Thus I knew how he was getting along, and that he had successfully written a game: "3D Space Wars", and found a publisher. Shortly afterwards he started receiving royalty cheques and was writing his second game, provisionally called "War of the Worlds". We got a letter from Jeff Wayne's people later on, so it was changed to "Seiddab Attack".
 
 

The Interview

Things were going well and one August Friday evening Steve came round and, knowing that I wasn't happy in my job, he asked me if I'd like to work for him. That was the easiest question I ever had to answer, and the shortest interview I never prepared for. I handed in my notice the next week, and during my month's notice period I thought I'd better get acquainted with 6809 assembler.
 
 

Tandy Co-Co

I bought a book on 6809 assembler programming, quite a sensible sized paperback, and I must have bought a book on the Dragon 32, or maybe actually the Tandy Co-Co, on which the Dragon 32 was based. We used to have a Tandy shop in nearby Colchester, which was useful for accessories and games. 
  

Lunar Lander

I didn't have too much idea about how fast home computers ran, or know anything about how graphics got onto the screen on a Dragon. I had written a Lunar Lander type game that only really needed to plot one small object on the screen, and it appeared to run at a reasonable pace in BASIC. The object plotting was done by a BASIC function, so I wasn't doing that part of the task. I at least learned that since we weren't clearing the screen and starting from scratch every frame, you had to un-plot your object from its old position and plot it in its new position. We also weren't using back buffers nor frame-syncing in those days. Actually, to clear an entire bitmap of 8K might take you a tenth of a second or more without doing anything else.
 

No Assembler

I also didn't have an assembler at the time. What we did have though was a plethora of magazines which published listings that you typed in yourself. All were written in BASIC, but some used to POKE machine code into higher areas of memory, then pass control to it. That technique was what I was interested in. Little did I know that Steve had written an entire game using that technique. You might think that's not particularly important, but I was going to be converting that game to the Dragon 32, without any assembler source code for reference.
 

Always Save Your Program Before Running It

So, my evening job for the next few nights was to try to write an assembler plot routine on paper. I would then look up the machine code for my instructions, which were in hex, then convert them to decimal, work out the arguments, such as variables in hex, and convert to decimal, and work out the relative branch distances. Having worked out all of the values in decimal, I would type them into a BASIC loader program, SAVE IT, TWICE, and then see if it runs. Naturally it doesn't work properly for quite a while. Depending on how badly it doesn't work, you may be re-booting and hoping your program reloads from tape.
 

Pixel by Pixel

In my naivety, I decided to try and plot a space ship pixel by pixel. I know, totally impractical, but I was optimistic. Since the screen started out blank and black, I provided just a list of the white pixels` positions relative to the centre of the spaceship. So for each pixel I had to calculate the screen position and which bit to set. I actually included a multiplier factor, or at least an addition factor,  so I could make the ship explode by moving the pixels further from the centre point. I believe I did include clipping, which by pixel isn't so tough.  Pixels didn't come back until Morpheus, unless we count the Uridium background stars, and they didn't move, which is actually the clever bit!
 

Relative Code

6809 assembler code supported relative code, which means that provided you avoid any absolute jumps, the code can be loaded at any location and all the branches still work. 6502 and Z80 code weren't usually written relative. The advantages of relative code weren't really relevant until the Amiga, which allowed the operating system to load your code in anywhere that fits and run side-by-side with other programs. I had seen that on our mainframe, which was slightly different as it segregated programs by making them think they were the only program loaded, and faking the addresses so they always looked the same (whether the COBOL code was compiled as relative code, I don't know, they didn't let me see my COBOL programs in machine code, but whether relative or absolute, the faked addresses would still work.
 

Add Some NOPs

The problem with writing relative code the way I was doing it is that if you want to add an instruction in the middle, you have to "stretch" all the branches that might cross over that point. There are no labels or function names as I wasn't using assembler, I was writing in raw machine code. I quickly adopted the strategy of throwing in a few NOPs (or No OPeration, null instructions) to pad out the routines so that if I needed to add an instruction I could remove the corresponding number of NOPs and all the branches stay the same. Similarly if you want to remove an instruction you can replace it with one or more NOPs, and just tidy it up at the end once you've debugged it since NOPs still take a little time to run.
 
 

No Debugger

Naturally I didn't have a debugger, and I was starting with a whole plot routine. Fortunately the list of points helped. You can just give it one point to start with and see if that works before you add more. Computers can always think of new ways to not work, so it's a mental exercise of relating what you see on screen to how your code might be wrong. There's always a way! With one small routine you get to know it well. I was used to debugging code by staring at it and willing the bugs to show themselves. Dry-running, we called it. We are as clever as computers, just not as quick at finding the mistakes!
 

My First Space-Ship 

I can't remember exactly how long it took me to get this working, probably a week or so of evenings. Like any number of tutorials I have seen recently that are not running frame-sync'ed you have little idea how quickly or slowly the screen is being updated if there is no movement. I expect my next step was to add a small BASIC loop to just move the X position of my space-ship and call the plot routine again. At this point the reality of how long this routine was taking to plot my space-ship set in. It was maybe updating 2 or 3 times a second, and I was somewhat disappointed.
 
  There was also another limitation that I wasn't plotting black pixels, my graphic relied on being plotted onto an empty black screen, and my un-plot routine was removing pixels one by one rather than clearing (or restoring) a rectangle. With the explode option, that rectangle would get bigger and at some point clearing the rectangle would be slower. 

Hardware Sprites - Now That's Magic

All this seemed so laborious compared to what I was already seeing in Commodore 64 demos: you just put your graphic data into a particular location in video RAM, POKE a few ports on the graphics chip and the hardware plots a sprite on the screen for you, pretty much for free (data fetches aside). No un-plotting, different colours than the background, very straightforward, and you can slide the background around underneath it and it stays where you put it. It would be about 6 more months before I got a chance to try them out for real.


Next time...A Proper Plot Routine.

0 nhận xét:

Đăng nhận xét