Monday, 30th January 2006
As (yet another) side project to all this Z80 work, I've also decided to have a stab at the Japanese Master System's FM chip. It's a YM2413, and the documentation on it is fairly tricky to get to grips with - not only thanks to it being in typical Japanese-manual English.
So far, I have this - the VGM player is a bit buggy and extremely primitive (unfinished), but should be enough to demonstrate the current state of the OPLL. You'll need an FM VGM to try it with - the Space Harrier demo from the BIOS sounds pretty good.
If anybody has had any experience with the YM2413, I'd be interested to hear if you had any helpful tips...
In other news, I've been adding multipage program support to Brass, and Latenite has had a lot of debugger integration work done on it. It's still a long slog before it's in a presentable state, sadly.
Thursday, 12th January 2006
CoBB has added an non-interactive mode to his emulator. I'd never thought about using stdin/stdout to pass information between executables; but it works well (once I've ironed out the bugs at my end, that is!) All I need to do is pass it instructions via stdin then read back the results (such as a screen dump) through stdout. This can then be, hopefully, used to pass instructions back to Latenite ("Highlight line 43 on file source.asm", for example, to show where the PC is).
Tuesday, 10th January 2006
This excites me greatly - integrating a debugging emulator into Latenite is very, very awesome. CoBB's emulator is incredibly good as a standalone, being able to step through your code instruction-by-instruction with breakpoints and a watch window or two is just amazing!
I spent most of the last few days working on Brass - adding for loops to assemble blocks of code multiple times and a few file operations for people not happy with the behaviour of .incbin. I also remembered to release an XML help file for Latenite.
The Marble Madness engine project has been plodding along in the background - I've written a fast masked, clipped, 16x16 sprite routine and have started tackling the big problem of mapping the ball's 3D coordinates to the screen (easy) and then to a heightmap (hard) for Physics.
Have a marble rolling off a ledge then bouncing off the right screen boundary.
Friday, 6th January 2006
Prompted by a PM from evolutional, I rebuilt a working-ish version of Fire Track.
Keys should be fairly self-explanatory; hold down button 1 and 2 as the ROM loads to get access to a cheat screen. Of course, you'll need an emulator; Emukon is a highly advanced, but suprisingly fast emulator (fast in that it lets me run GG ROMs at full speed on an old Pentium PC).
I will be uploading all the source and tools in a zip at some point so you can experiment with some of the other features if need be.
I started work on a 4-way smooth scrolling tilemapper last night for use with the Marble Madness project (for the main view) and have come up with a fairly simple, but sufficiently fast mapper.
The GIF is a little wasted as the level is only 128 pixels wide, and on a 96 pixel wide display this doesn't give much room for showing off the smooth x-scrolling. Having never written a mapper like this (only basic, slow horizontal scrolling and vertical scrolling, never together) it was quite an experience, but not as hard as I'd thought.
I have cobbled together a basic editor that allows me to edit the map, and that takes a folderfull of GIF files and exports a binary sprite resource file. Hooray RAD with C#!
It looks like I'm going to need a lot of sprites...
As for this crashing and burning - Fire Track failed because of my absolute lack of music skill; also, the game was too hard to be any fun.
Marble Madness is just a set of ideas; I'm not comitted to it (hence no "official" announcement to any TI people, kv83!)
Thursday, 5th January 2006
First up, happy Christmas (or "Seasons Greetings" to the politically-correct amongst you - I've never heard this supposed "Happy Holidays" said in this part of the world, and in any case the word Holiday seems to indicate religious goings-on in any case, so we'll be having none of that PC rubbish ).
Back to the Z80
Having spent a week away in Normandy, marooned from the world of the Intarwebs and PC, I have come up with a potential new Z80 project. I had my Game Gear with me (naturally) and one of my games was the most excellent Game Gear port of Marble Madness:
The game is simple if you do not know it; you must guide a marble through an obstacle course to the finish in under a certain time. Various tricky level design elements and enemies make this a hard task. The world is presented in an scrolling isometric 3D view.
The Game Gear is not an especially powerful platform; the Z80 runs at ~3MHz. The TI-83 Plus runs at 6MHz (an underclocked 8MHz Z80). Of course, the Game Gear has the bonus of hardware-accelerated smooth-scrolling (which is how we get super-fast games like Sonic on it) but Marble Madness has fairly simple basic scrolling; vertical smooth scrolling on a TI is cheap, and horizontal smooth scrolling only needs to go one pixel at a time for Marble Madness - we can't do much about that apart from bitshifts, but a pixel/frame isn't asking for too much.
In a bizarrely well-organised move I ended up taking along a pen and paper, and ended up making a bunch of notes on how to construct a Marble Madness engine.
For this game, it all boils down to the way the graphics are presented to make or break the gameplay. They need to accurately convey the illusion of a 3D world, whilst at the same time being handled internally as very primitive - we can't do CPU/memory expensive things like treat the world as a true 3D model and have a 3D isometric engine.
Also, the limitations of the display and LCD driver of the TI-83 Plus need to be taken into consideration. The TI-83 Plus is equipped with a 96x64 pixel monochrome LCD. It is accessed through the use of a driver chip on ports $10 and $11. As it is monochromatic, a single byte represents 8 entire pixels. The physical display is 12 bytes wide and (there are 64 rows); in reality it is 16 bytes wide, but normally the 4 bytes are off the edge of the display. It can be set into a special 6-bit mode where each byte only covers 6 pixels; the 6 pixel columns are squashed up to give us a 16-column display, but this is only really useful if you are, say, using it for a 6x8 font (the TI-OS uses this mode for the text-mode screens).
For this reason, horizontal scrolling is cheap; you can just change the byte offset as you copy to the buffer to scroll up and down. However, horizontal scrolling requires (expensive) bit-shifting. Not only that, but the display operations have to be timed using inefficient loops (push af \ inc hl \ dec hl \ pop af is common - there is no accurate timing hardware) else it decides to do useful things such as jump into 6-bit mode. The whole TI graphics system is very sluggish.
The low resolution needs consideration; the Game Gear Game relies on clean, large, colourful graphics. I will have to drop the resolution down so that you can see a decent region around your marble; and can't afford to use effects such as dithering which make the display unclear (the display is quite blurry).
Here is a sample course (thanks to Maxim for producing the map):
To fit it on the TI, I have decided to halve the resolution. If I kept the squares as tightly packed as in the Game Gear version, this would result in 4x4-ish tiles - mucky, cluttered and ugly. To remedy, I shall have to expand the tiles to double their visible width/height; so a single tile in my version would cover 4 tiles on the Game Gear version. The levels would have to be adjusted (in the image above, the tile blocks at the top are arranged in 3x3 grids; I shall probably go for 2x2 grids of my larger tiles, or just go straight to 1x1...
The way I intend to handle the levels would be to split them up into their individual parts;
- Background - this would be a simple 2D tilemap, made up of 8x8 tiles with a fast smooth-scrolling engine. This is rendered, then the marble/enemies are copied on top of it.
- Heightmap - this is a sort of 2D map of the 3D world, where each point has two values - a type (flat, steep slope, empty space, goal...) and a relative height. This would be used by the physics engine to handle the movement of the marble around the level.
- Depth map - this is a sort of copy of the 2D tilemap, but only contains special masked copies of the tiles on the tilemap, together with a depth (z-index). This way, when the ball is drawn the tiles that it is convering can be checked. If the corresponding tile in the depth map is closer to the user, it is redrawn, concealing part of the ball. For example, see the railings in the picture of the level above, or any of the large holes. As most of this layer will be empty, it could be RLE compressed fairly succesfully.
Other things, such as animated sprites or dynamic parts of the level, would be handled separately. For example, level 2 has this tilty thing:
It tilts up and down. For this, a special large sprite could be rendered, and the 3D heightmap in memory adjusted as required.
I'd be interested to hear any thoughts/ideas/pointers on my methods...