• Create Account

Like
17Likes
Dislike

A Full C64 Game - In 2013

By Georg Rottensteiner | Published Jul 29 2013 08:54 AM in Game Programming

c64 asm assembly

Back when I was a wee lad we had a wondrous machine at home, a computer. You could hook it up to your TV and make it do what you wanted. It had color, sound and lots of games. This particular incarnation was called Commodore 64, or C64 for short.

Very fast I turned to writing programs and games, albeit in BASIC. It was cumbersome, and slow, and you could get nowhere near commercial quality. For a short period I tried to get into Assembly, failed at a (in hindsight) little problem and gave up.

Years went by... In the meantime I meandered to the PC (DOS, then Windows) where I started a programmer's career.

Fast forward to today. Today's development is heaps and bounds beyond imagination from 30 years ago but I've always had a soft spot for the C64 after all this years. Emulators appeared and became better and better, so I sat down and tried to start assembly programming on a C64 (via emulator). Having learned a lot in the meantime it just felt easy. One game grew under my fingers, supposed to be a kind of farewell to a good old friend, and it became Joe Gunn. And behold, making it was tremendous fun!

So finally this Tutorial series was born, to show a younger audience how a C64 game would be written from the ground up. The subtle and not so subtle pitfalls of the architecture and the developing approach will be shown, and maybe lure one or the other veteran back in ;)

Note:  This article is both introduction and partial post mortem on a series of journal posts that detail the development of a Commodore 64 game over the period of two years, including required assets and code source. To directly jump to the tutorial entries go here. Read on for further details of the C64 system and how the game turned out.

A C64 Game in Several Steps

Memory

The C64 is a rather simple machine for today's conditions. It has 64 kB of RAM, with ROM overlayed, like shown below. One of its main advantages are specialised chips for sound and graphics. They are controlled by "registers", which are blended in at a specific RAM location and can be written to/read from (I/O in the graph below). For example: write a value to $d020 (53280) to change the color of the displayed screen border. The memory layout looks like this (nicked from www.c64-wiki.de): Conveniently the ROM can be selectively turned off to have code running and accessing otherwise hidden RAM, which was used for most games excessively. Specialised chips Graphic display is handled by the VIC II. Display comes in several classes: For one there's the mostly used text mode. Characters are made up of 8 by 8 pixels and can be redefined. A screen is then worth 40x25 bytes for characters plus 40x25 bytes for the colors. Then there's bitmap mode which allows a higher diversity in display and colors, but then weighs in at 8000 + 1000 + 1000 bytes (quite a lot for only 64 kB total). And last but not least, the sprites. Sprites are little (24 by 21 pixel) objects than can be put anywhere freely. Most common was the text mode, as it allows quite nice graphics without too much memory used. Sound is handled by the famous SID chip. It allows 3 voices with separate envelopes in parallel. In the right hands some awesome music was and is composed. Emulators There are a handful of decent emulators out there, which are also available for most systems. Currently I prefer VICE for the great development support. A monitor with a full fledged (albeit a bit unwieldy) debugger is built in. Today you wouldn't use a code editor on the C64 itself anymore. There is a nice batch of different cross assemblers and even IDEs. I started out with ACME and TextPad for a code editor, but later wrote my own, Visual Studio inspired IDE. Connecting to VICE it allows for convenient debugging through your code, which helped me tremendously for those nasty bugs. With a key press code is assembled and started in the emulator. 6510 Assembly The 6510 comes with a simple and rather rudimentary set of opcodes. If you ever touched assembly on a x86/64 you will miss a lot of nice mnemonics and most of all, all the registers. The 6510 has one accumulator and two registers. Everything else must be stored in RAM. It has a few convenience functions (indexed addressing) that allowed for easy, indirect lookups (think pointer tables). Due to being 8 bit any math opcodes only operate on 8 bit values. The CPU does not come with things like multiplication and division. One of the things that stumped me was displaying a decimal number. You just have to manually calculate the division by 10. Not really hard to do but the absence of such a common functionality today feels weird. Where things get funny There are two hardware types, PAL and NTSC. Both run at different frequencies (60 Hz NTSC, 50 Hz PAL), but at the same speed. NTSC however has less time per frame. A lot of games simply run 20% faster on NTSC. Display is tightly coupled to CPU cycles. One cycle equals eight pixels. The more complex your game becomes the more you may need to fiddle to time a graphic setting at the right moment to avoid flicker. Generic code is nigh impossible. The machine is not too fast, and especially for writing games you mostly need to tailor the code to the situation at hand. There is no safety net. Code is data, and vice versa. Write a byte at the wrong location and your code crashes in unpredictable ways. On the other hand this allows you to copy code all over the place, and create self modifying code (actually useful). Emulation is very good - you can write whole games without ever having a real machine. However still, the more in-depth you go, the better it is to actually have someone test your game on the real thing. It's a good thing there is still quite an active community out there, so you're likely to find someone willing to help you out. Gameplay For the game in this series I had a rough idea in my head. It should have Bubble Bobble style gameplay, but with a touch of survival. During the first third of the project the game engine was built up and a lot of detail was used on the code part. Design came during the latter two thirds. Once the player could run around among enemies the gameplay would be tackled. Since at the time I was watching Supernatural that's the direction the game took. One of the first things to make the gameplay more survival-like was the need to actually stand still to reload your gun. I think that worked out pretty nice actually. It gets quite frantic when you're in the middle of a bunch of spiders and you just fired your last bullet. As a nice fit for a second game where Sam had to make an appearance. To make the gameplay differ the second player got a magic force that worked quite different from the shotgun. Reload was not required, but standing still while the force hurt the trapped enemy worked quite similar. At a later time I wanted to present a choice for the player types, but in the retail version I ran into all kinds of problems. Quite a few code parts were specialised to the shotgun player being player number 1 and the force player being number 2. Getting those ironed out took a lot of testing. Actual coding Especially in the beginning there was no new ground to cover and everything was simply writing out required base code. Sprite display, controlling, enemy behaviour, level structure, nothing ground breaking. Music and sound effects again do not need much work for the actual game coder. Richard Bayliss provided the music and sound effects as a runnable binary. Include the data, jump at a routine at regular intervals, done. Things got interesting with the screen buildup. Every screen is compiled by several primitive types, simple character lines, single elements, lines of elements or areas of elements (an element being a rectangular block of characters and colors). This was a nice exercise as this part can and has been reused for other games. During the last 20 steps memory got full. The C64 doesn't allow you to load a file into the full 64 kB RAM, only from 2049 up to 49152. The memory above can be used but data has to be copied there manually. That's when Exomizer came in. Exomizer is an awesome cross packer specialised in older machines. Exomizer would pack a file usually to about 60% to 70% of the original size. Remember, free memory is precious. For the retail release disk and tape versions were to be made. That was quite easy, as the game was designed as a single load and could be directly put on those media. However there should also be a cartridge version. The C64 allows for a cartridge via the cartridge port. Two in lines would determine how the memory of the cart would be shown to the CPU. The cart in question had a 64 kB ROM. The C64 however only allows 8192 bytes of cart memory be accessible at once (actually that's two times 4196 bytes). To access the other parts the shown "banks" could be controlled by writing specific values to a memory location. The memory at the cart location would just behave like the normal ROM, read from ROM, write to RAM below. This was tackled with the simple approach: Blend in cart banks, copy data into RAM, blend out the cart and work like before. For the full tutorial series you start here Conclusion It is awesome to see how far you can go all on your own (well, mostly). Still, having others, professionals, help out with graphics and music is still very much required. And what else I learned: Back then people didn't have all these convenient tools at their hands. Or an internet to look things up. My hat off to you gals and guys of the old times. Included Media The C64 photograph has been taken from Wikimedia Article Update Log 27th July 2013: Initial release License GDOL (Gamedev.net Open License) Comments This is awesome. I've been working on a similar project for the Apple IIgs, which uses a 65816. I think that having this kind of documentation for all of the systems that use this processor would help spurn more development. I believe there are a lot of proficient 6502 family programmers, but that they are largely focused on on machine, or family of machines... like myself. But we can bootstrap one another's education and really kickstart a rebirth of retro coding. Here's a link to the course I'm working on for the Apple IIgs: https://github.com/digarok/gslib Also, here's a retro programmer reference I'm working on for the 6502 family of processors that runs on iOS (iPhone/iPad): https://itunes.apple.com/us/app/recre8/id674806938?ls=1&mt=8 Thanks again for all the effort you've put into this. Hopefully I, and others, can finish similar guides for the other 6502 brethren. Cheers! Wow. I've been making my own 2d game engine in C#, which is hard enough - and you've nailed it in what appears to be C64 assembly language. Massive kudos to you. Well impressed! @digarok: Nice work! I guess there is a similar scene for Apple than for Commodore? There's lots of helpful people out there if you know where to look There's a nice wiki (http://www.c64-wiki.de and also http://www.c64-wiki.com) which list all the opcodes. @CdsTomalak: Thanks! This is awesome. I've been working on a similar project for the Apple IIgs, which uses a 65816. Looks good, I always wanted to complete a game for the Apple IIgs, but never did anything more than setting up the screen and showing an image. Have you investigated any cross platform development options? I used the WLA-DX assembler to create a simple ProDOS8 executable. I can't remember the exact details, it's been a 'few' years. The major issue I ran into was finding a command line tool to inject files into an disk image. It would be interesting to adapt the snes-sdk (https://code.google.com/p/snes-sdk/ ) to produce files for the Apple IIgs. Another option would be Western Digital C compiler, which were recently updated and the price was reduced to$40:

http://65xx.com/65xx-store-2/65xxtools/

This is awesome!! Thanks Georg

Note: Please offer only positive, constructive comments - we are looking to promote a positive atmosphere where collaboration is valued above all else.

PARTNERS