Saturday, October 14, 2006

XeO3: The Big Sqeeze!

Well, there comes a time in every project where all you seem to do is try and get a few bytes of memory back. It's usually a slow, grueling process where you look through virtually every line of code for the odd byte that you can save, and hope its enough. XeO3 has hit this point. Since I started doing the loading, I thought it was about time I did a front end, but before I did that, I needed memory - a lot more memory. My current code budget had around 300 bytes left which isn't enough to make toast, never mind a front end. The data block still has around 1k left so the first thing to do is try and merge them. This means rearanging the whole of memory to try and pack free areas together. Never fun.

Certain areas must still sit on certain boundarys (character sets, screens etc.) but the rest is free game. I've managed to move the data down by moving the sprites and character sets up, and the character animation down. So the current memory map looks like this:-

$0800-$17ff 2 Screens
$1800-$27ff Music (4K)
$2800-$65ff Game Code and DATA (15872 bytes)
$6600-$67ff Character bitmap animations
$6800-$77ff Game charactermap (double buffered) (4K)
$7800-$97ff Sprite graphics (167 16x16's) (8K)
$9800-$9fff Barrel shifter for sprite caching system (MCM version)
$a000-$a2ff Panel Character Set (95 chars + space)
$a300-$aea7 Level Data-13 screens (7*13 - 3x3=91*13=$49F, 200 3x3 blocks=$708) ($ba7)
$aea8-$aeff Spare (88 bytes)
$af00-$bfff PATH data... (4k+256 bytes)
$c000-$efeb 141 pre-rotations... ($2feb - 141*87)
$f000-$f578 ScrollBuffer
$f5a2-$f5ef Sprite address table (built at runtime)
$f6f0-$fd00 Spare.... (1.5k)
$fd00-$ffff IO/Hardware/Vectors

I moved the fixed table of sprite addresses out of the data area and into a bit of free space right at the top of memory, but instead of a table, I build it with a little code at runtime. This keeps the EXE down and saves loading diddy little tables. I also stripped out the last bits of the save/replace sprite system (it's still there, just commented out) which freed up a little more space.

So all in all I now have 2,721 bytes left. Still not a lot... Now it gets tricky....


Anonymous said...

I think you should have an intro sequence after which the actual game is loaded. Then nobody is disappointed if there's only a small frontend inside the game.

Have you considered packing (NOT realtime packing/unpacking)? Of course you need to store packed data then... for the frontend and maybe for some parts of the game/data to gain enough space. Even if that's adding an overhead for the unpacker you might gain more than you lose. Have a look at exomizer. Maybe a simple byte packer will do, too. And that should be definitely fast enough.
If unpacking causes a noticeable delay, it's annoying. As you mentioned before, when the player just died, he probably wants to restart right away. So check how much packed data you can get into those free bytes minus the unpacker. For some extra bytes you can use $ff40 and above... not much but sometimes every byte matters.

About the turbos... there's none "ready made" for the 1551 that'll suit you. Well, I'd exomize the whole thing and then load it with a speeder (Csory's one) and unpack the game, start it and if level data has to be loaded, then it's loaded without a speeder. That's not too bad, I think.


Mike said...

Not sure about an intro... Everyone will watch it once then just skip it, which makes it a bit of a waste of effort.

The problem with packers is that you need a reasonable amount of code to depack it, and then I'd have to find space for this code as well.

If I was short on data space, then this would be the ideal solution, but being short on code space means that its hard to even fit in a depacker.

I dont want to pack stuff that may disable a turbo that someone else has installed. On the C64, Blood Money was crunched, and it decrunches over the top of the vectors - which means it now can't load from the MMC64 - which is a damn shame! I'll now have to go and make one that doesn't have this problem. I dont want to do anything that might cripple it later on - I'd rather leave it slow and let people choose how they want to play it.

Anonymous said...

Even though people skip the intros, it sure makes your game stand out as a solid, polished product. :-)


Mike said...

Perhaps... but after 6 years I'd rather have it finshed than a polished unfinished thing with only me playing it. :)

Chicken said...

Never underestimate intro watchers ;) I know lots of ppl who like to watch good intros... more than once! It doesn't have to be anything big but I'm sure Luca would like to draw a nice title pic.

About crunchers... It's not that hard to make sure the decruncher doesn't mess with any vectors. I mean, you are coding an entire game :)

I think the bigger problem is, that almost all turbo loaders use memory ranges that you need for something else.

Therefore, I still think it's good to crunch the game so that it can be loaded with a turbo. After loading the game, just re-initialize the vectors so that any further loading uses the standard ROM routines.
Thus you can offer (optional) fast loading for the big chunk and compatible loading for the small parts like next level's data without worrying about any future devices that might not load the game.

Btw, do you have a 1551 drive?

Mike said...

well, intro's are right at the bottom of my list. Theres no point in a pic since the turbo loader switches the screen off, and when you don't use that in an emulator its loaded too quickly anyway. However, Im sure I can add a couple of pictures if I need to. :)

No, dont have a 1551 - I use my 1581 usually, and have a 1541 II and 1541. It would be nice to make my own ROM though, and tie some developement keys to it, rather than load (say) my downloader off disk all the time.

Chicken said...

Well, then just wait for "space" or "fire" when showing the title pic.
So you are using that 1541 speeder of obscure quality? ;) I remember that one of my 1541-IIs hated it. Luca pointed in the same direction.

And get a 1551 drive (if you have enough space). Despite some dissing in the press and on some C64owned web sites (clichees like it's not much faster than a 1541, mechanics suck) it's in fact a fine piece of hardware. I haven't seen any CBM drive as reliable as my 1551 and I have used it a lot. Sure, they break sometimes but so did 1541s.

I like the 1581... Though, mine is at DAN's place since 1993 :( But there's not even a speeder for it on the plus/4 so I used it only for back ups and "mass storage" (funny to consider <1MB as mass storage ;) )