Thursday, 23 March 2017

NES Homebrew Part 3: On the move

So the next part to tackle is the moving eggs. Moving one isn't so bad, but there's the issue of what happens if they collide. the basic sequence of events is this:

  • Player pushes an egg
  • It continues moving until it hits another egg
  • The previously moving egg stops and the hit egg starts moving
  • This process continues until...
  • ...an egg hits a wall.
  • The egg then reverses direction until it ends up at its home position (which should be next to the previous egg).
  • The previous egg then begins to move....
  • ...until the first one arrives at its home position again.
So how do I manage all of this? Well I figured that a stack-based approach would be best. When a push starts the stack will be empty and a moving object is put into the stack and the background object is removed for the moment. As soon as it hits another egg then the process is reversed, and we remove the moving object and place a background object at that position. Another moving object is created in place of the next egg and it's placed at the next slot in the stack. when an egg hits it's home position again it is converted to a background item once and for all, and the stack unwinds one step. If the last stack item needs removing then the stacksize is set to 255(0xff) to signify that it's empty and no further processing is needed.

Simple enough? Well yeah aside from the usual 'It's all in 6502' type issues. I get around this by having a single-byte stack pointer in the zeropage and using the start of the hardware stack page for my egg movement stack. Each egg description in the stack is only 4 bytes, and with a maximum of 12 on a row or column (13 - where the player is standing) this means we have a worst-case scenario of 48 bytes, leaving 216 bytes for the stack. I can't see it ever going over 128 bytes to be honest so I can rob more of the page if needed.

All addressing is done by declaring the structure elements relative to the base of the stack, loading the stack pointer into the X register and referring to the elements with LDA/STA egg_element,x.

The egg_type element contains the current type in the lower nybble (same way the level data was defined to start with) with the movement direction encoded into 2 bits of the upper nybble, giving us a nice round stack element size that isn't too slow to manipulate.

I'm still a couple of functions short - the graphics update stuff isn't plugged into the right points yet, but stepping through the stack handling and movement code looks like it's working. I have the other code I need but I've written it in a way that makes it a ballsache to reuse, so it looks like some refactoring is needed...


Wednesday, 15 March 2017

NES homebrew part 2: On map formatting

There's always tradeoffs to be made


Generally speaking code can have a small footprint, or be fast. Sometimes (but not as often as you'd want) you can get lucky and have both.

The level data in this case is one of those things. There are currently less than 8 types of tile on a 13x13 grid. This means that in theory we only need 3 bytes per block, and with the map being 169 tiles this would be 507 bits (64 bytes, rounded up). So what options do we have?

  • 3 bits per tile - This would be the smallest representation, but as the start of each tile would start at an odd place in a byte and may even cross into the next byte along. This lands us straight into the roughest end of speed vs size territory as you'd need to find the start of the 3 bits, which may be one or 2 byte reads, shift them into the bottom 3 bits of a byte, maybe swapping and combining part-bytes. We also have the overhead of logic to figure out if these special cases happen, which takes time, and then we can use them. This is the worst case scenario.

So... we're pressed for both memory and time, but we're going to have to choose one. Let's look at the wastage options, shall we?

  • 4 bits per tile - Not quite as small in terms of representation at 676 bits (85 bytes), but we can look at it as expansion room for future tile types. Tiles still need expanding from their positions within the byte, but they alternate between the top and bottom half of each byte, with no crossings so it would be quicker and simpler at least.
  • 8 bits per tile - This brings us up to the full 169 bytes for a level description. As far as reading out the data is concerned we would be wasting half of each byte for storing the tile number, but no unpacking would be needed. We can even turn the negatives into a positive and use the top half of the byte to hold other information about the tile (such as collision information) so you get everything in a single read and you can just AND-mask off the bits you don't need for drawing. Even random access is easy - just look up MAP_START_ADDRESS+X+(Y*13) and you'll get the byte. We're sorted!

oh. wait... Not quite that simple.

Y*13 now becomes our enemy. In the relative comfort of C++ it's easily done. On a modern cpu, or even a 16-bit 68000 or 32-bit ARM you can just use a MUL instruction, but on a machine with no multiply how do you even do this?

You could just have a lookup table with 13*0,13*1...13*12 in it, but in 6502 we only have 3 registers, 2 can be used for indexing into lists like this but they're probably busy doing other things anyway. The other way is to use shifts. Even if you don't code you've probably done this subconsciously by multiplying by 10,100,1000 or so by just moving everything left and adding zeroes onto the end. Binary works the same only shifting left multiples by 2,4,8,16,32... depending how far you go.
What about values that aren't nice binary values, such as 13, though? Well - you just find the binary shift values that make up the add number and add the result of doing those individual shifts together:

13 = 8 (shift left 3) + 4 (shift left 2) + 1 (original value). So we can do those 2 shifts, add them together. Oh - and do a bunch of swapping and putting stuff in and out of memory because as I'm sure I mentioned before we only have 3 registers... my head aches just thinking about it. This brings us to one further option:

  • 8 bits per tile, but with each line padded out to 16 bytes. We're now up to 208 bytes per level map, but we can find any given tile with (Y shifted left 4) + X. Fairly quick and decent. Even better is that if we have a pixel position on screen each tile is 16 pixels high, so to turn that into a block position we'd have to divide the Y position by 16, then multiply it by 16 again. Those two cancel out and can be replaced by just clearing the bottom half of the Y position by ANDing it with 0x0F. Even quicker.

The two-way split

Generally as I think about game code, whether it's 64k of assembler running at 1Mhz or thousands of lines of C++ in xcode I mentally divide code into 2 camps: gametime and non-gametime.

  • Gametime is basically when you're playing, or an animation is running and you really need everything to by silky-smooth and as fast as it can go. If something happens in gametime it needs to favour speed. If it can not happen in gametime that would be even better,
  • Non-gametime. This covers loading time, static screens being shown, and basically any time where responsiveness is less of an issue. Anything that happens during this time can take a size-over-speed bias.
We also need to have the game data whilst playing in RAM, as the level might change as we're playing it due to things being destroyed or moved. So this means we can choose 2 of the above options - one for storing the levels that aren't being played (in the cartridge ROM in this case), and another for what is called the 'inplay buffer' in the code, which is a working copy of the level in the RAM.

Currently the inplay buffer uses the 16x13 layout, as it is almost exclusively used during gametime so speed is of the essence however I've yet to decide on the ROM layout format. I'm tending towards the 4 bits per tile layout. This would mean stripping the collision information out of each tile byte, but I can add that back in when I unpack the level to the RAM. It takes a little time, but this is non-gametime so I'm okay with that. It also assumes that each tile type would always have the same collision information but consistency is good in gameplay so I can live with that too.

This means in a single 16K cartridge bank I can hold 192 screen definitions, which is overkill and doesn't factor in other level definition info, such as enemy placements, timers or other per-level adjustments I might come up with as I go along.

Not so important on the NES, but if I backport to other machines later on then this might gain more importance.

Back to the NES

This weekend would've been great - things warmed up outside, the sun came out (and I had to look on Wikipedia to see what the glowing thing in the sky was, it's been so long), the beach bars were having their grand opening for the year 10 minutes walk away...

...and fate rewards me with a heavy cold that felt like the not-at-all fun bits of being drunk and a 3-day hangover combined into one handy package. Fantastic.

So like any normal geek who can count to 1023 on his fingers I grabbed a Lemsip, curled up on the sofa and started investigating Unreal Engine 4 and getting something out of it that didn't make my old backup PC and netbook scream in pain. The requisite hacks I found online required multiple recompilations which took a not insignificant amount of time.

So in the meantime I turned to WUDSN and the Nintendo NES toolchain. I also remembered discussing ideas way back with someone about an old arcade game where you pushed eggs around to free the birds trapped within whilst avoiding the enemies patrolling the screen. As a test of doing an old style single-screen game (Like the original NES classics, such as balloon flight) I started to implement the basis of something similar on the NES:


What I currently have is a hardcoded test level, which is somewhere close to the final (decompressed) format I want to use, a player sprite composed of 2 16x8 hardware sprites, all the hardware initialization and RAM clearup code and Shiru's Famitone sound player handling the sound. The collision detection is in, although my (deliberate) non-handling of diagonal joypad presses doesn't feel as fluid as I hoped when moving around, so I'm going to go back and redo that.

On the Actual hardware front the initialization, bankswitching (for the 64k cartridge image) and NMI-based Picture Processing Unit (PPU) update code means that the game works properly on hardware. It should also be able to determine if it's running on PAL/NTSC and adjust movement speeds and music pitch accordingly.

All the game logic is in 6502 assembly, however the collision routines and logic all happens in game-space (as opposed to screen coordinates) and only references the machine-agnostic game data with things being transferred across to the hardware as needed so hopefully if this thing gets finished I can port it across to any other 6502-based machines afterwards.

Seeing as I got this far in a lazy day I figure I might as well keep on with it and see how it goes. Hopefully documenting it as I go will motivate me.

Next task - handling the egg pushes. Pushing an egg is easy - it moves until it hits a wall, then bounces back to it's original position with 1 hit of damage taken. The harder part is if it hits another egg, in which case it causes a chain reaction until the last egg in the chain hits the wall and then everything bounces back into place in reverse order. This would be easy enough to do in C, but in 8-bit assembly with 3 registers and a clockspeed of under 2MHz this is going to take a bit of thinking about how to do it for the best.

Tuesday, 14 March 2017

Where was i...?

or 'yet another 'sorry for my absence' type of post'.

I know... Real life again. Things have been a bit thin on the 8/16-bit front for a while as I've been a wee bit busy working for those fine folks at Feral Interactive getting other peoples games up and running on MacOS. Then, just as I settled into that a job offer for my girlfriend came up in the Netherlands, so there was the small matter of hauling my Mac (and a cross-section of 80s and 90s machines) across to the Hague, settling in there, trying to learn the language. This brings me to my top tip for Dutch people - If you'd like us to actually do this (and some of us think that it'd be pretty gezellig thing to do) maybe you could stop being so helpful and speaking perfect English to us? :)

So I've finally gotten around to coding a mixture of new and old stuff again, depending on mood.

I've not done absolutely nothing though - there has been the odd bit of music here and there.


This raster split-tastic intro by Cosine has a Cover of 'Bliss' by Muse. I was suprised by how well this worked out actually.

Important note: I made a little typo on the copyright note, so if you take it literally then Muse covered me. I don't think I need to point out that that's not the case.

I liked this one...


...In fact I liked it so much I ported it over to the Atari 8-bit and we used it again :)

What can I say? What you lose in instrument quality you gain with that 4th channel I really could've done with on the SID.

Back again on the subject of covers of stuff I like I did a cover of 'Here comes your man' by the Pixies, which got the usual splendid DYCP scroll, logos and raster split treatment.

And 'In the interest of balance' as the BBC like to say yet another cover done for this years AtariAge new years disk. This was a reworking of a tune I remembered hearing back in the 90s bundled with various DOS Adlib music editors, forgot about and then it turned up in my youtube playlist. So I had to do something to get the damn thing out of my head again.


Then there's the matter of work stuff, Which is more numerous but it gets messy in terms of attribution. Not only because it's porting work (So more like translation than writing, and not my original work to start with), but also because there's games I've done 'myself', games I've helped with, common company code that I've written that's in every game since, and the odd fact that my favorite game I can (vaguely) lay claim to is the one where I wasn't officially working on it, but someone found code I'd written helped, cut+paste it in, and left me a thank you in the bugtracker. Life is strange sometimes...

Even in the '100% me' games there's the aforementioned huge chunk of shared code without which I'd get nowhere, so I can't rightfully claim 100% of anything. But hey! that's modern development for you.


Wednesday, 15 January 2014

New Work-In-Progress: Moonshot

I've been a bit busy of late trying to get a new job (I succeeded - I'm off to do games coding in a couple of weeks), but in the meantime a big chunk of retro time came and went, so sadly I missed the RGCD competition. I've checked my code into bitbucket and I'll resurrect it for either RGCD or ABBUC so it's not abandoned, just waiting for a chance to finish it up for a time when more people will be watching.

In the meantime I've been reading the excellent Racing the beam over christmas, which inspired me to have a try at Atari VCS coding.

For my first attempt I've been looking back at various Spectrum and C64 games and remembered playing Bounces, which looks to me like it is a great fit for the Atari hardware - 2 player objects and a ball with some scope for variations and some 2 player action.

I've had to make some changes - in my attempts to make the players look like Knights (I originally wanted to call the game 'Fight Knight' I ended up with something that looked like a robot waring a condom on it's head and I figured I needed a chunky back for each sprite to mask the playfield-drawn bungee chord due to the low resolution, so generic Spacemen/jetmen seemed the way forward.


This is the first test of my display kernel - I haven't added the colouring to the sprites yet (which makes them look a lot more defined), but the main parts of the display kernel are there. I've also got a good chunk of ROM left (for 4K) and RAM isn't an issue just yet so it looks like it's progressing well.



In case you are wondering - I've moved the blanking logic processing down to underneath the play area and put a colour switch in before calling it so I can gauge how much time is being used, so the occasional flicker you see there is the minimal amount of game logic kicking in.

Wednesday, 18 September 2013

It's been quite a while.

Sorry... I got distracted. Real life and all that.

I have started coding a small C64 game, which I'm not making any promises about at the moment (seeing how I've been AWOL for so long since my last update here). I would ideally like to have it up and running for the RGCD 16k cartridge development competition, however as I've only just started the thing I'm not far enough along to confidently throw my hat into the ring just yet.

Before the Atari folks start booing me off for neglecting their beloved machine I would like to say that it does look like it would be viable on the 8-bit Atari too. It won't be a compromise - it just coincidentally worked out this way when I was laying all the data out and planning how it works. If anything it may be a bit easier with the extra CPU grunt and the more flexible screen display layout.

But Alas - the C64 competition is up first, so that makes it the lead machine. Had I had time and thought of it a couple of months back the Atari would've been getting it first via the ABBUC competition, but what can you do?


Wednesday, 1 August 2012

Happy birthday my old friend

Yup - it seems that the Commodore 64 is now 30. Thanks for all the fun.

Now let's remind ourselves what it's capable of and why we love the damn thing so much :)






Tuesday, 15 May 2012

so why even bother doing this kind of stuff?

I think a poster nailed that one right here

'It's also like asking musician's why they still create new music on acoustic instruments invented hundreds of years ago, and why people still listen to such music. Part of the reason is because acoustic instruments have a particular character and a simplicity.'

Amen to that. With the technologies and limitations comes a style. And some of us just like that and want to make more stuff  in the same or similar style.

Thursday, 12 April 2012

Cheers Jack

It looks like the founder of Commodore, Jack Tramiel is no more.

It's pretty safe to say that without the C64 I wouldn't have had so much fun with games, learned to code because 'the game I wanted wasn't exactly what was there' and then kind of accidentally fell into coding as a career. Likewise my family were definitely one of the masses, not the classes, so love or hate his 'get it out the door cheap' attitude I wouldn't be where I am without it.

so cheers for everything...

Thursday, 15 March 2012

Those iOS trailer videos that everyone hates doing.

There's always a question on the touch arcade developers forum from someone trying to grab gameplay video for a trailer but they don't want the frame rate fluctuations of the simulator being picked up by screen camera software, or to spend a ton of cash on a hardware solution to capture from the device.

I do most of my coding within a windows framework, and switch to OS X to do a phone build periodically to check my code work, and that helps in this case.

KKapture by Farbrausch is a great capture tool - everything looks silky smooth every time, but this comes at a price. Basically the capture software lies to your software, telling it that it is running at a rock-solid 60FPS and grabs every frame it produces to stitch together a video. Your code is only producing 20FPS? No worries - it'll run slowly but it'll get there in the end and you'll still end up with a full-framerate video. The downside to this is that playing the game at that speed is either impossible or at least looks very unnatural.

To get around this I added 2 commandlines to my Windows framework - Record and playback. In record mode vsync is enabled, locking the gamecode to a constant 60hz framestep, and all touch events are logged to a file, along with the number of the frame they occured in. The random number used to seed the random number generator is also stashed away.
In playback mode the events contained in the file are passed into the application through the framework instead of the real input, so the game can be run through exactly as you played it.

Capture this noninteractive version with kkapture et voila! Nice smooth gameplay videos.

Of course, it assumes that the game will run at 60fps solid when recording input, but on an average PC if the game starts dropping frames this is probably the least of your worries. If your game isn't too heavy and your PC is fast enough you can probably kkapture it at 60FPS whilst playing it. In fact, in the case of Reaxion it runs above 60FPS whilst being captured.

Thursday, 2 February 2012

Zynga and originality.

Isn't this bloke just a class act?




Moral of the story is this: If you see a Zynga game you would like to play don't bother - just Google it, find whatever they cloned to build it and go play that instead, thereby supporting the actual creative people who did the work.

Thursday, 19 January 2012

Spending a little time on modern platforms - Reaxion lives on iOS

I haven't forgotten about Reaxion for the Spectrum - but time hasn't been on my side of late, but it's worked out easier to grab the odd moment here and there to put together a bit of C++ in windows. Problem is what I actually want to do is a smartphone game.

What I now have is a small lightweight openGL-based framework running that massages windows events into a format similar to those that come from iOS, and provides just enough primitive functions to allow image loading, screen drawing and timing to be handled in a way that is abstracted from the bulk of my game code. Once I had this running under windows it was a small matter of porting this little chunk of code to IOS, merging the 2 projects into a common folder structure and this was the result:



Now I have the advantage of being able to grab the odd minute that I find in front of a PC with visual studio installed to write and debug the game code, and then I can throw it all back onto my main machine and build for iOS. There are a few sacrifices in the way I've done this - multitouch isn't supported, I need to stub out gamecentre functions in the windows build and my current code is less than optimal, but it means I can hopefully get proof of concept games stuff done much quicker.

I'm currently using 'Reaxion' as a testbed for this, but I'm still undecided about releasing it...

Thursday, 15 December 2011

Testing out Amiga algorithms the cheating way

Despite working for a 3D graphics IP company I've never actually tried coding any 3D stuff from the ground-up on an 8/16-bit machine and I figure I might want to give that a try someday.

The problem is that there's all sorts of places an algorithm can go wrong. Is my maths shoddy to start with? Have a made a mistake converting it to fixed-point? Or have I just misunderstood some instruction?

Although I grew up prodding around with an action replay (and to be fair using windbg on kernal mode drivers for windows isn't that much better) it's a bugger of a way of working, especially when the error might involving trashing memory so you've not got any way to investigate.

To help me solve the problem of at least getting the algorithm right I've knocked up a framework. All it does is allow you to set up a palette (using Amiga colour values), give you 1-5 bitplanes (plane 0 providing the LSB) and allow you to read and write from them with bounds checking. Once your function (which should draw a single frame) returns it dumps the plane contents to binary files and spits out a .bmp with the output.

So what does this mean? It means you can breakpoint, single-step and printf the smeg out of your code when you are developing it and write it all as C with floating point maths, just like a PC routine but with a wierd graphics configuration. Once I'm happy with that I can convert the algorithm to use fixed-point 16-bit maths and keep an eye on it as I go. When that's working fine I can subdivide the steps taken until it becomes pseudo-68k and all with pretty much the same level of comfort as debugging a windows application.

By that point the remaining thing to do would be to convert it to 68k assembler (which should be a line-by-line translation if I've kept to the plan) and hope I don't introduce any bugs along the way.

Wednesday, 30 November 2011

For those with dead A600 or A1200 internal floppy drives.

This bloke does a decent job at going through the process:




There is a bit of the video missing though, but for that part:

towards the front of the drive there are a couple of tabs which can gently be pushed outwards, allowing you to lift the second layer of the top of the casing. Once you've lifted the top part take care to lift the top read/write head clear before sliding the casing clear of the drive.

And don't worry about the spring that infuriated the bloke in the video - you don't actually need to remove that at all.

About 5 minutes with cotton wool buds and some cheap alcohol-based makeup remover and it was booting right up again.

Monday, 28 November 2011

Hola Amiga. Cuanto tiempo!

It seems I'm now in possession of a stock A1200 with a second diskdrive (and the obligatory knackered mouse).

Now to give it a compact flash card, some means of transferring stuff and ideally a little extra RAM...

Thursday, 20 October 2011

It's been a long time coming...

But I've nearly done it...






Hopefully my next game won't get delayed by half a decade of life happening.

Monday, 26 September 2011

You have to love how accurate Spectrum emulators are

When you can just pipe the tape noise out of an emulator into a real machine and it loads perfectly every time (so long as you remember to emulate a machine with no YM soundchip, otherwise it gets confused)

Sunday, 25 September 2011

Back on with the 68K/Amiga

Seeing as I've passed my driving test I should now be able to nip off and pick up my* trusty Amiga 1200 and see if my code is as hardware-friendly as I hope it is. It's a stock 1200, but I'm hoping whatever I turn out will run on a stock Amiga 500 with 1Mb of RAM (I'm assuming 512k chip, 512k unknown).

In the meantime I've gone back to my scrollcode and it worked okay, but it made no use of the Blitter. I've corrected that now, although it took a couple of attempts to decipher the documentation for the minterm stuff.

The minterm docs run to a couple of pages and goes through boolean algebra and venn-diagrams, but it's really not as complicated as that. I reckon it should be explained like this:

You have a truth table for the 3 possible inputs. Just write in the fourth column where you want a 1 or 0 to be generated, and put those into the bottom byte of bltcon0 with the first row as the lowest bit. So a direct copy from A to D would be:

ABCD
0000
0010
0100
0110
1001
1011
1101
1111

so reading bottom-to-top the bottom byte of bltcon0 would be 11110000. Also, the 4 bits before that are the flags to use each channel, so those would be 1001 to use only channels A and D.

All the other registers do exactly what they say on the tin and don't seem to hold any nasty surprises.

problem is the scroller has a buffer that is just over 2 screens wide and draws each character twice, so once the buffer has hardware scrolled to the second half the first half should be visually identical, so I can snap back to the first half with no visible effects whatsoever. It uses a little extra memory and 2 blits, but it should perform better than shifting the entire buffer in one blit and then drawing a character in a second blit.

My next Problem is that the code busy-waits on the first blit, and then carries on to do other things on the second blit, so it's wasting time it could potentially be using for other tasks and not making good use of the machine. My next task is to get the code to build a blit list and then have an interrupt handler to dispatch the jobs to the blitter when it's no longer busy. Definitely overkill for this little framework, but when I generalise it for a game engine I can run game logic and blitting in parallel and scrape more power out of the thing.



*Actually it belongs to my brother, but he's not using it...