It works!
Thursday, 22nd September 2005
Based on this information alone, you can deduce that FTGG will be vastly superior.

I just gave FT2 a try in VTI (I don't have any batteries in my calculator) and good grief it's slow. FTGG is much much faster... (though you should see it go when I set the enemy speed to two... I need more accurate control of speed, 1 being medium-ish easy, 2 being nightmarishly impossible!)
This makes me happy.
Things to notice about the above screenshot:
- Near pixel-perfect parallax star background (you can see some through the bullet holes!)
- Not one single poorly timed VDP write.
This has required an enormous amount of code rewriting!
First to be fixed was the VDP timing. With a few .ifdefs, restructuring of the main loop and addition of an extra function call, all sprite data is now written to a shadow in RAM and then all sent to the VDP at once. This means that in sprite-intensive frames the framerate drops (it is unnoticable!) instead of the VDP going bonkers.
Next up, the pixel-perfection. I do not know if you know how difficult this is to do on this hardware (or, at least to a hack coder like myself), so I'll do my best to explain.
On a purely software-driven system, you can create a bitmask of your tiles so that when you manually blend your layers together you can cut out the stars you don't need. Or, you just draw them first then draw the tiles on top.
On more advanced hardware you can Z-order your polygons, so that's all done for you.
On the Game Gear, I have two layers - sprites and background. I can set individual background tiles to be on top of sprites - but this would dump a solid 8x8 square on top of everything. In other words, ALL the sprites are drawn under the background tiles marked as being on top. I had toyed with the idea of bizarre palette tricks and messing around with the tiles themselves, thinking sprites would be too slow (I asked about this on the SMS Power! boards - apparantly some games do the sprite trick, so I gained confidence in it).
What I need to do is this:
- Take the (x,y) of my star and convert this into an offset into the VRAM name table.
- Look up the value of the tile at this value. If it is 0 (blank tile), draw the star. (Special case to skip expensive stage below)
- Look up the tile in a table of sprites marked as transparent. If it isn't listed, don't draw it.
- Take the offset into our table of transparent tiles, multiply it by 64, use that as an offset into another table. Find how far into the nearest tile as an (x,y) coordinate we are - that is, x is in the range 0-7 and y is also in the range 0-7 inside the current tile.
- Use this coordinate to look up inside our mask whether to draw the sprite or not.
There was an awful lot to go wrong and it did, often. It works pretty well now, so I'm happy with where it is.
The function to calculate the VRAM name table offset based on an X,Y on screen was broken. It needs to take into account the current vertical scroll, you see, to calculate the offset, so was essentially doing this to calculate which 8-pixel-tall row a pixel was in:
row_offset = (y/8) + (scroll_y/8)
(where y is the coordinate we pass to the function) - which leads to all sorts of rounding errors! The correct function is, of course:
row_offset = (y+scroll_y) / 8
Which, oddly enough, didn't seem to work at all well - at certain times, the values returned were completely off. The reason is simple enough - our scroll_y is a value between 0 and 223, and out y coordinate is anything between 16 and 160. 160+223=383 - you try storing that in an 8-bit register! So I updated the entire function to 16-bit code where needed.
Z80 ASM gurus - my old code to divide A by 8 was the simple:
srl a
srl a
srl a
For my divide-hl-by-8 function (srl [reg] is a sort of [reg]>>=1 function) I use this:
srl h
rr l
srl h
rr l
srl h
rr l
-- is this the fastest I could use? Is there a nice 16-bit shift operation available to me?
Next I had to generate the transparency data. I edited my tile editor - solid green &00FF00 is taken to mean "transparent!" It dumps a list of any tile with transparency, then an expanded 64-byte table of the mask (1 byte per pixel - horribly big, but much faster than packing it into a 1bpp mask).
When I say "near pixel-perfect", I have a problem - my stars are 2x2 pixels, and so if they can overlap the borders by a pixel or two from time to time. It doesn't look too bad, and in my defense the original Fire Track displayed stars over ANY black areas on the background at some points...
Parallax
Wednesday, 21st September 2005
Here's a nice little graphical enhancement...
...and here's the video for it! (I disabled collision detection for that video, so no silly comments, alright? )
Now, there's a little problem with this system - well, a number of problems. The worst is this:
Oh dear. I'm now writing to the sprite table when the display is active, which (understandably) it does not like. On the Game Gear hardware, you can see this in the vertical bar of flickering stars towards the left hand side of the screen. I am not sure how I shall fix this, but I'm hoping that altering the sprite drawing routines to write to a RAM shadow then dumping the entire RAM shadow in the frame is faster than my current method which is to manually draw the sprites in a number of different routines.
The next problem is the detection of when to show/hide stars. Currently, it only does this based on tile index - so only tiles marked as being 0 are "transparent" and enable the stars (they're being drawn as sprites). This leads to them vanishing a good distance away from the edge of land.
Finally, there's the even weirder issue where the stars move at almost the same rate as the landscape but are shifted in alternate frames. If a star is on the boundary between tiles, one frame it is over tile 0 so is shown, next it is over tile X so is hidden, and this oscillates. Hopefully by fixing up a pixel-perfect "show/hide" function, I can fix up this problem as showing and hiding would be about 4 pixels away from the boundaries.
I have also started work on "Segue", a simple music system for Game Gear games. I'll support instruments (they just modulate the amplitude of notes when they are played) that can be bound to the different channels. The song itself will be a list of instructions - "play this tone X on channel Y" (where X is the period of the tone), "delay for X frames", "assign instrument X to channel Y" - that sort of thing.
EDIT: This journal is now low-res non-horizontal-scrolling friendly.
Title screen goodness
Tuesday, 20th September 2005
I spent some time yesterday doing some 'fun' work on Fire Track - that's not to say that the other stuff is not fun, but I find the graphics work less head-hurting than the programming work.
Hence the spiffy title screen above! It was fun trying to fit that into 16 colours and able to be broken down into 256 tiles, but with a bit of shuffling around it's a mere 254 tiles and the GIF exporter in Photoshop has done a great job dropping down the colours.
The display on the Game Gear blends adjacent pixels together very nicely - on hardware, the title looks pretty flash. (It's difficult to get a good picture of Game Gear - you try taking a photo of a TV set and you'll see what I mean! As clear and sharp as your TV looks out the photo will usually look washed out or fuzzy). See, here is a screenshot of the game running in an emulator:
Not quite so smooth, is it? (Not to mention it's a different aspect ratio!) Still, it's a little more colourful than the original:
(Mine is a cleaned up version of the box cover with the text redrawn.)
As you can imagine, a title screen such as the above takes up a lot of space. 254 8x8 tiles means 254*8=2032 rows of pixels, each row is made up of 4 bytes (four colour bitplanes) giving us 8128 bytes or 7.94KB. Seeing as the ROM I'm using is only 32KB, things are going to get tight - not to mention that even without the title picture I get the following:
Building... (Sega Game Gear)
Setting base location 'D:\My Documents\Game Gear\Dev\Fire Track\'
Running batch job '"D:\My Documents\Visual Studio Projects\Latenite\bin\compile\Sega Game Gear.bat" ftrack.z80 ftrack "D:\My Documents\Visual Studio Projects\Latenite\bin\compile"'
Build process complete!
Bank 00 has 03729 bytes (11.38%) free.
Free space at $0029-$0065.
Free space at $7191-$7fdf.
Free space at $7ff8-$7ff9.
Free space at $7ffc-$7ffe.
3729 unused bytes of total 32768.
Erk! That's not much room at all, and I still need more space for the music. I need to jump to using 2 ROM banks - that'd give me a healthier 64KB to work in, and 48KB of that is set up to be directly accessible without any paging as default. Or so it goes in theory, but WLA-DX's syntax for defining memory locations/ROM bank setup has me totally stumped. Looks like I'll need to pester the SMS Power! chaps again.
Anyway, what is going on in Fire Track itself? I did do some coding last night as well as slacking off with some image editing, and these features are now implemented:
- Final attack pattern is in place - small ships appear then attack you by setting a direction when at a certain Y coordinate and just heading into you in a straight line. This is slightly buggy, some ships appear to have drunk pilots and veer off in completely the wrong location. Not sure why that is, but most seem to hit the target (read as: ME).
- Bugfixes/tweaks on a couple of the enemies. The ones that randomly drift towards you (the dumbell-shaped blockers and another formation) now only start drifting in X once they are on-screen, else they all appear on screen in a vertical column and it looks really silly.
- If you complete a level it doesn't just automatically jump to the next level, you lose control of your ship and it flies up and off the top of the screen. I shall probably also stop the end face from looping so that when you finish and have flown the background doesn't just disappear, it's as if you accelerate and it moves downwards off screen to the blackness of empty space.
- The sound! How could I forget that? It now works on volume rather than the hard-coded priority, and thus sounds very much better. (The loudest sound is the one that is played, as I can only set one period/amplitude as a sound effect at any one time).
- Fixed a bug on the title screen where sound channel #2 was not being set (channel #1 was set twice by accident).
Rather than just see a list of what's done, have a list of what is left to do as I am feeling generous.
- Get ROM paging correctly up and running so I can dump more data onto a second 32KB ROM chip.
- Add sounds for me exploding (uses the noise channel so isn't just a case of adding a new sound effect).
- Adding the "mine" enemy. This is a small spiky blobby thingummy (technical term) that drifts in a straight line until it hits the edge of the screen, at which point it reappears at a random location and drifts in a new, random direction. If it hits you, of course, you lose. You can see it in this screenshot of the BBC Micro version:
It's the thing above the two lower explosions. - Music. I need music. I also need a music system, so defining instruments (attack fade, play effect (vibrato?), release fade) and notes, as well as all sorts of other nasty music things.
- Scoring.
- Parallax stars? (Maybe, hopefully!)
- Lots of other things I must have forgotten.
Until next time! Incidentally, my journal is now listed as the News section on my website.
Minor progress
Monday, 19th September 2005
I've spent the last few days up North for a cousin's wedding, so not much has gone on regarding Fire Track.
A few things have been added, though!
The sound is now "mixed" (for want of a better word) much better. It's still not perfect, and I'd like to see how it sounds when favouring amplitude over priority. That'll be my next tweak!
I have added the cheat screen (also useful for testing sound!) which will appear if you hold down certain keys as the game starts. There are a new set of enemies...
They just drift towards you - and you can't shoot them (they block bullets, though).
Also, the "final platform" for a few levels has been implemented. This is for the levels where you don't finish up with a face to shoot the eyes on, just a platform:
You need to drift past it to beat the level.
When you have finished the last level, the epilogue now plays too.
Through extensive testing (playing?) the original, I have worked out the purpose of the question mark blocks:
Shoot out a certain number and you get a funny noise and are awarded an extra life!
Motion blur filters are so cool.
Bloop-bleep, it's the 80s!
Wednesday, 14th September 2005
Sound! I am still musicless, but never fear, for sound effects will fill the gap. Screenshots are pretty poor for sound , so here's the MP3.
Simple as it sounds, that takes a mere 163 lines of ASM code to work, and even then it's a fairly crap effect!
Each sound is stored as a series of "fades". Each fade contains the following data:
- Starting period of the wave.
- Starting amplitude of the wave.
- Length of the wave in frames.
- Amount to add to volume each frame.
- Amount to add to period each frame.
Using these simple fades and joining them together you can very easily produce a fairly complex sound. There are currently only two sound effects, and both are a single "fade" long - one for firing, the other for when a tile on the ground has been hit.
Each sound effect is issued with a priority, in a little table, so that the most important sound is played over the top of the least important one. In this case, if you play a more important one over a less important one (higher pitched bleeps) it cuts the less important one out for good - which is rubbish, really. What I will have to do is to extend the system to act over a list of current sound effects that can be added to at any time. That way, which tone is sent to the PSG (the sound chip) can be decided at that point, based on priority (and maybe volume, I'll have to see how it sounds).
I fixed Latenite's ugly XP icon issue, and here are the results:
The one on the left is the Debug build. The one on the right is the Release build. I have no idea why it is doing that on the right, or how I can fix it.
It gets better.
This is what it looks like in Release mode when running in the VS.NET IDE.
I shall now resist the urge to make an massive journal post this time. Honest. Just watch me.