Jet Set Willy C64 WTF?

jet-set-willy-c64-remake.jpg

Yesterday while looking for the PSU for my Parker MidiFly MIDI box (unsuccessful, so if you have any pointers, I’m all ears), I found my original, sealed copy of Jet Set Willy C64. Are you tired of me telling you I wrote that in 1984? Well I showed this gem to my colleagues at work today.

This evening I was trying to remember whether I’d switched to a more reliable assembler after starting the project in the buggy Macrofire assembler. I’m sure I did, I just can’t remember whether it was the Commodore Macro Assembler or not. So what do you do when you can’t remember bits of your own life? Well you google it of course, and in doing so, I found that somebody had actually remade the C64 version. Frankly, that’s just beyond my understanding, but good on Captain Death, that’s all I can say.

I haven’t checked it out, I’m still on a high from working out a decent mechanic for Chimera’s energy/material phasing system and getting a fair bit of code done. Feel free to download it and let me know what you think. (Oh and this guy has done a good job of giving a breakdown of how the data is stored in the game)

Crazy, Crazy World

The world seems to have gone to hell. Countries are on the verge of collapsing, economies held together with sticky tape and Pritt stick, kids getting beaten up by police on the streets of London and Liberals turning out to be utter sell-outs.

Yet for some reason that I can’t quite fathom, when I should be at my most radical, with all of my activist engines on full boost, I am excited about my trade. My trade? Video games. That’s right. I’m so very excited about games, about making them, playing them, learning about them.

I’ve talked about making games with a message, subversive games, but that’s not why I’m loving them at the moment. My guess is that coding is a problem I enjoy solving and something over which I have some control. It is an area in which I can experiment, ask questions and get answers.

I’m still kind of dumbfounded that I have anything at all on the screen and despite my tardiness in recent times, I have made great strides and the results of that will be visible soon.

I managed to get boost::signals (or is it the single ‘s’? I can never remember) working. I had to drag the source for the signals library into my Xcode project, but that worked just fine. I also updated to the latest version of Xcode 4 and I’m particularly enjoying the Assistant mode, but I can’t really talk about that I don’t think, so let’s stop right there.

I am really surprised at just how powerful boost::signals and boost::bind are, and I will be using them a fair bit now.

I’ve also been thinking about the design and have some more ideas on that. Happy to share too.

Remember I talked about two phases to the game? Material and Energy? Well now I know how to switch phases. I want to do a twist on “game over” – it’s called “it’s never over” – when your energy drops to a critical level in the Material phase, the game switches to Energy mode. Everything becomes brighter, ethereal, vector-like and yes, glowing and sparkly. I like the sound of that. And to get back to material mode (reincarnate?) you need to accumulate sufficient energy. Or rather, “recycle” it. Everything will get smoother, more dream-like. So that’ll be a particle system then.

[Update: 21:44 – I’ve just got the threshold value-checking in and I was just thinking aloud – how about if the switch from material phase to energy phase was under player control? And the phasing is quite fast and frantic. Other games have jump and shoot as “panic mechanics” – I could have “the switch” – I’m usually good with names so I’ll have to come up with something suitably pretentious to describe it. For now, it’s just “the switch”.

[Update 22:09 Eureka! Energy gradually goes down in material phase, culminating in death with zero energy unless you switch to energy mode, in which case energy starts increasing gradually. In material phase, you use large amounts of energy for more energy-expensive moves. In energy phase, you gain large amounts of energy, but you lose material (i.e. room structure, perhaps the floor or the hull of the spacecraft) – I like this – and it could be fun if the rate at which you need to switch phase varies according to environmental factors]

 

 

What is Chimera?

I’m really understanding what this game is about now.

  • Energy
  • Environment
  • Reframing the past
  • Redemption

In order for the game to be about the above list, these all have to be factored into gameplay. And that’s my challenge.

The energy bit is really easy and most games do a simple variation of this. The obvious example is an FPS game, where you have a certain amount of health, as do the bad guys, and shooting them, or being shot, affects your energy.

I’m taking that a bit further and turning it into more of a real-time-resource-management issue. Energy is a resource, the Environment is a “trust”. In order to fulfill your stewardship of the latter, you need to be clever about the former.

Energy is expended in varying amounts depending on your activity and on the prevailing environment.

Reframing the past is about being able to over-write your previous actions, committed at every stage, and thereby “un-commit” them. And redemption means going back in the game and fixing mistakes that would have been harder to fix at the time.

 

The Boost Library

chimera-and-boost-library.jpg

I’ve been struggling for a while with indecision. At first I wanted to write an event system from scratch. Then I got sidetracked somewhat by McShaffry’s Game Coding Complete (bought in Kindle format and read on iPad). I’ve been doing an awful lot of C++ reading and I’m not ashamed to admit that much of it (certainly at first) seemed beyond me. Some of the things people get templates to do are just dizzying.

The upshot is that after much vacillation, I decided to use boost::signal. That’s when the real problems began. I tried search after search and found that I couldn’t get the basics done no matter what.  I read all kinds of distracting advice on what the problems might be, but ultimately realised that the issue I was facing was somewhat more fundamental. The scripts that build boost weren’t finding G++. It finally dawned on me that the build tools weren’t set up properly. So I installed the latest release of Xcode 4 and this time, told it to include the Unix tools. Now bjam was finding G++, but still not working.

It was just as well that I’d already given up last night and decided to simply drag the files from the signal source directory directly into my Xcode project. Everything worked fine after that. It’s worth mentioning that much of boost doesn’t require libraries, as everything you need is in the header files. There are some boost classes that do require building into a library, and boost::signal is one of those classes.

There really should be a binary distribution of a library as important as boost for Mac OS X and I’m surprised at how poor the state of support is.

Still, back to Chimera now – and how energy conservation can be turned into a game mechanic. I’m also thinking about the revision of history as a game concept and the notion of redemption as a gameplay mechanic. Yeah, I’m serious. This is a game after all.

(By the way, I particularly enjoyed reading this perspective on Chimera).

 

Nothing

All I’ve done this weekend is rest. I’ve not written a single line of C++. I feel this gnawing dread that I won’t have a demo this year at this rate.

I’ve been thinking of how to implement an event model and reading up on all manner of signal and slot systems, observer patterns and boost::signal libraries. My head tells me I should just write a straightforward system in C instead of worrying about the right way of creating a fast delegate system to cope with C++’s class methods. And if that sounds like Greek to you, I can assure you that when I first approached this subject, it was Double-Bloody-Dutch to me.

Sometimes I do wish that I was writing this in Assembler or plain C. I do get the basics of C++, but it really is a language that lends itself to using it fully – and that requires a level of abstract thinking that I’m finding it hard to come to terms with. 20 years ago, I would have coped without a second thought. Now, I’m more of a Biz Dev person.

Today I also feel a little depressed about some other work-related matters, existential matters, ones which I’m not really at liberty to discuss on this blog.

So apart from tweeting like mad for a couple of evenings, having a Hoyo de Monterey Epicure #2 cabinet edition whilst watching an excellent episode of The Professionals with my wife and going out with her for breakfast yesterday, the weekend has been a wash-out.

I am not giving up and I’m not prepared to spend the next few weeks beating myself up about not doing anything either, that seems completely absurd. The only cure for inaction is action. I have to make a decision about how I’m going to handle events and then just bloody well do it.

Illusions

Chimera Glow Dots

 

 

Have a look at Rob Fearon’s piece, “We Love Glow” when you get the chance. A man after my own heart, playing with the kind of looks afforded by modern software and hardware. That’s what I call “retro reframed” and it’s how I roll. What we’re working on appears retro, but actually wouldn’t be possible on older hardware (at least not at a reasonable frame rate).

Alpha-blending? Forget it. The best we got was transparency and masking, on, or off.

Additive blending? Don’t be silly. Overlays, sure. That’s your lot.

I’ve spent all day working on this. I’ve learned that I’m not as fast as I used to be. I’ve learned that music doesn’t help me relax as much as it used to. And I’ve learned that somewhere along the way, life hit me so many times, so hard, that I plain and simple forgot how to just let go and flow. I’m not saying I’ve got it back, but I recognise it. And yes, I’d like some more of that please.

I’ve coded quite a lot, learned some more C++ techniques, got half a graphic editor going, got some glowing graphics going and reverted to Spectrum graphics as opposed to the 3-colour (+black) C64 sprite. The proportions are wrong, the blocks are pink, the glow is Ready-Brek, but I’m happy for today.

What do you think of that big pixel look on the left by the way? That with some glow maybe? (Don’t worry about the white pixels, they’re just masking)

So what does the title of the piece refer to? Well, the illusion that more is being done than it actually is. I don’t need to do anythign fancy in real-time, other than let the hardware take care of alpha-blending. Everything can and should be faked.

The effect was achieved by adding an external glow filter and a gradient overlay from top left to bottom right at about 50%. The graphics have been scaled up from the Spectrum original enormously.

Now for some animation.

 

Big Pixels – You Like?

That code I showed you the other day – that was like showing a doctor a boil on your backside that you’d unsuccessfully treated with a home remedy of a pin sterilised in a match flame. Don’t worry, the code dramatically improved, that is, I fixed the bugs and cleaned it up and stopped pretending I understood anything about the bloody vector class and I finally managed to extract some sprites and display them on my demo in chunky pixel form. Here they are.

Bulky Chimera Pixels

What I’m doing here is loading a Spectrum image of my original game, kindly preserved by Internet people, then scanning through it for graphics. the black cut-outs are masks used as cookie cutters – the black pixels got cut out of the background, then the image got blended in. Did you see how I used the word “blended” there? Stop sniggering at the back.

I’ve done the whole faux-retro-pixel thing. I like it.

So I grabbed one of these images and started playing about with it in a graphics package. Here’s my first experiment. It’s a bit weird I know, but I like it.

 

chimeraman3dexperiment.png

Gory Detail

Here then, in all its gory detail, is the the file I’ve been working on this evening. Most of my time was wasted in trying to work out how the vector class worked and getting to the bottom of arcane compiler errors. Stuff like having to include std:: to qualify the vectors I was using, and getting the template for my really bare bones simple Colour class right. Sheesh, if I was doing this game in assembler or C, I would have finished it by now, but I know I’ll reap the benefits of proper C++ if I stick with it and let it do some of the heavy lifting for me.

And yes, I know the tabs have been stripped, just be grateful there are colours here.

/*what does this class do?

 

given a character pointer, it constructs a 2D array of RGBA from bitmap data of varying bit depths

 

what are the parameters?

 

width, height of source

bpp of source

palette to use when mapping to RGBA

stride per byte

stride per line

endianness

width of pixel group (in bits)

 

What’s the real world use of this class?

This class is used to decode old school bit streams of graphics data and

turn them into displayable blocks for capture and re-use in modern environments.

*/

 

#include “common.h”

#include <vector>

 

 

class StreamToImage {

public:

StreamToImage();

virtual ~StreamToImage ();

void setParams(int, int, int, int); // width, height, stride per byte, stride per line

void setWidth(int);

void setHeight(int);

void setStrideByte(int);

void setStrideLine(int);

bool setPalette(std::vector<Colour<BYTE> > *, int); // palette pointer and size of palette

bool extract(BYTE *); // extract to internal buffer given pointer to raw byte stream

void copyPixelBuffer(std::vector< Colour<BYTE> > *);

 

protected:

int width;

int height;

int strideByte;

int strideLine;

int bitsPerPixel;

std::vector<Colour<BYTE> > palette;

 

protected:

bool extract1BitPerPixel(BYTE *rawDataStream);

bool extract2BitsPerPixel(BYTE *rawDataStream);

 

private:

std::vector< Colour<BYTE> > pixels;

bool goodToGo;

};

 

 

StreamToImage::StreamToImage()

{

// Make the entire palette black, but set alpha to max

for (int i = 0; i < palette.size(); i++)

{

palette[i].r = palette[i].g = palette[i].b = 0;

palette[i].a = 0xFF;

}

palette[1].r = palette[1].g = palette[1].b = 0xff; // Make 1st palette colour white

bitsPerPixel = 1;

goodToGo = FALSE;

}

 

 

void copyPixelBuffer(std::vector< Colour<BYTE> > *pDest)

{

*pDest = pixels;

}

 

 

void StreamToImage::setParams(int w, int h, int sB, int sL)

{

width = w;

height = h;

strideByte = sB;

strideLine = sL;

goodToGo = TRUE;

}

 

 

StreamToImage::~StreamToImage()

{

 

}

 

 

inline void StreamToImage::setWidth(int w)

{

width = w;

}

 

 

inline void StreamToImage::setHeight(int h)

{

height = h;

}

 

 

inline void StreamToImage::setStrideByte(int s)

{

strideByte = s;

}

 

 

inline void StreamToImage::setStrideLine(int s)

{

strideLine = s;

}

 

 

bool StreamToImage::setPalette(std::vector<Colour<BYTE> > *p, int numPaletteEntries)

{

if (numPaletteEntries > kMaxPaletteEntries)

return FALSE;

 

palette = *p;

return TRUE;

}

 

 

bool StreamToImage::extract(BYTE *rawDataStream)

{

if (!goodToGo)

return FALSE;

// We have a palette and all the vars are set up, time to extract to our internal buffer

switch (bitsPerPixel)

{

case 1: // Monochromatic spectrum

return extract1BitPerPixel(rawDataStream);

 

case 2: // Commodore 64 or Amstrad

return extract2BitsPerPixel(rawDataStream);

 

default:

return FALSE;

}

}

 

 

bool StreamToImage::extract1BitPerPixel(BYTE *rawDataStream)

{

BYTE *pb;

BYTE bit;

for (int y = 0; y < height; y++)

{

BYTE mask = 0x80;

BYTE shift = 7;

for (int x = 0; x < width; x++)

{

byte = pb[y * strideLine + (x >> 3)];

bit = (byte & mask) >> shift;

// Now we have a value for the bit, use the palette index 1 to set it in our pixel buffer

pixels[x + y * width] = palette[1];

mask >>= 1 ? mask : 0x80;

–shift ? shift : 7;

}

}

return TRUE;

}

 

 

bool StreamToImage::extract2BitsPerPixel(BYTE *rawDataStream)

{

return FALSE;

}

 


I accept that constructs like the bool “goodToGo” have no place in polite society. I felt a little dirty doing that. I also think the ternary operators resetting the mask and shift values are a cop-out. I ain’t fooling anyone with that pitiful attempt to hide two branches in the middle of a byte loop, but the engines can take it captain. At least, they can nowadays.

Ugly, isn’t it? Go on, give me tips. I can and will improve this, but you can see what I’m trying to do here.