Who needs asm? cc65 C compiler

Who needs asm? cc65 C compiler

Commodore Computer
Image by OpenClipart-Vectors from Pixabay

Back in the day 1984-1989, I wrote games in Z80 and 6502 assembly. It would be another 10 years before I learnt C++ and ten years after that for C. But I would have killed to have had a C compiler that generated 6502 code back then. Writing assembly language code is slow and painstaking. You have to remember whats in each register (A,X and Y) and what you are using page 0 locations for.

It takes the same length of time to write and debug 10 lines of 6502 assembler as it does to write 10 lines of C.  But those ten lines of C can do way more than 10 lines of 6502 assembly.

On a 6502 which is an 8 bit CPU with 16-bit addressing, memory goes from 0-65535. It takes two bytes for an address unless it is in the first 256 bytes (0-255) which only needs 1 byte. You can optimise your code by using page 0 for many variables. It only takes 2-byte instructions to fetch them from memory and write them back. The first byte is the instruction, the 2nd the address. Compare that with the rest of memory where instructions are three bytes long with 2-bytes for the address.

CC65 is a C compiler that generates 6502 code. It’s mostly written in C. I’ve added a permanent link to it on the C Codes link page. Pictured is a CBM-64 like the one I used to own.

Deciding what level features to be used in the Match Three game

Deciding what level features to be used in the Match Three game

Match Three gameI’m at the point of deciding what features will be included in the game and then determining what % of features are used on each level. how to make the game harder etc. As with asteroids I’ll use Excel.

These are features to enhance the game and maybe increase difficulty.

  • Wanted animals. Most levels have a target of a number of pieces of one type. The level is completed when all of that piece have been removed. These ‘wanted’ animals are shown onscreen with a count of how many remain.
  • Locked pieces. On some levels, pieces are randomly locked. The lock is removed only when the piece is in a matched line or in the area affected (from bonus pieces). Locked pieces do not move even if there is a space beneath them. For really hard levels, two locks can be used on a piece. Each lock has to be removed.
  • Skulls. Some levels have a number of skull pieces to be removed. This can only be done by removing pieces below so the skull drops and eventually reaches the bottom row where it is automatically removed.
  • Timed levels. Some levels will have a count down timer; so many animal pieces have to be removed before the timer runs out.
  • Bonus Pieces. These appear when a 4-match, a 5-match or a 6-match occurs and show special pieces- a 4-piece, 5-piece etc. Two 4-pieces dragged together clear a 5 x5 area of all pieces (remove locks on locked pieces). Two 5-pieces dragged together wipe out all pieces in both the row and column. A 4 and a 5-piece together wipe out all animal pieces of the animal piece (picked randomly) next to the 5-piece. Two 6-pieces together wipe out all pieces on the board (locked pieces aren’t wiped, just unlocked). A 6-piece dragged on a 4-piece or 5-piece wipes out all pieces in 3 rows wide and 3 columns deeps.
  • Board Rotation. The board can be rotated clockwise or anti-clockwise. This allows spaces created under locked pieces to be possibly filled. It also helps get rid of skulls that are now on the bottom row. But some levels start with a number of board rotations. Once used up, the only way to earn them is to do something like drag two four-match pieces together.

So now I have to decide how these fit together on the different levels, what weighting each has and calculate a difficulty score that should increase as you progress through levels. Oh the joys of game design!

Back writing book two

Back writing book two

Hexagons
Image by Clker-Free-Vector-Images from Pixabay

This time it’s about Learning to program games in C on the Raspberry Pi. Most of the books I’ve seen are about programming in Python, but C combined with SDL2 gives you an edge. I already know that I can get 150 frames per second in Asteroids on a Raspberry Pi 4B.

The three games for the book are

  1. Asteroids. Fully developed
  2. MatchThree. About 1/2 developed.
  3. Empire type game. Map generator plus large scrolling hexagon map with fog-of-war shrouding and computer AI opponents. This will be based on the existing Empire code.

The third game is one I originally wrote thirty-three years ago (Dark Empire) in Z80 assembler for the Zx Spectrum. I then converted all 5000 lines of code into CBM-64 6502 assembly in one month working seven all-nighters, with the last three on three successive days. That one wasn’t in hexagons but squares and of course there was no mouse.

On the morning after the last all-nighter I drove across Manchester to deliver the tape master copy to a railway station to be sent to the publisher in London and when I got home, I slept for 24 hours solid. I doubt I could do an all-nighter now, but 33 years ago …

 

How to run C snippets quickly

How to run C snippets quickly

lacy utility to run C snippetsI saw this the other day. A GitHub project for Linux that installs a quick way to run snippets. You download the zip file from GitHub let the archiver handle it then right-click extract the folder to somewhere, typically in your home folder.

Then you cd into the extracted folder and from the terminal run

./install.sh

To install it. After that open a new terminal to pick up the changed paths. You can type in

lacy -h

to view the commands. You can see in the screenshot above where I tried it in Ubuntu.

How to stop access to Global variables in C

How to stop access to Global variables in C

Links
Image by PIRO4D from Pixabay

If you have an application made up of multiple source and header files, it’s possible that you use global variables in those source files. Remember, these are variables declared outside of any function.

Now you may not know it, but by default, those variables are visible to other files through what is known as external linkage.

Slap extern on the definition and the compiler and linker will happily use it. For instance in the Asteroids game, there is an extern int variable used in the file asteroids.c.

// external variables
extern int errorCount;

This is declared in the source file lib.c and when all the modules are linked together the linker sees all the compiled symbols and figures out which refers to which.

Making your program robust

If you don’t want global variables in one file to be accessed from another, just add the keyword static in front of the declaration like this.

static int errorCount = 0;
Now then, even though you’ve got the extern, when you compile it you’ll get an error. This is what Visual C++ says.

Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol _errorCount asteroids D:\writing\Amazon EBooks\GamesProgrammer\publishing\Learn C Games Programming\Windows\Code\asteroids_ch48\asteroids\asteroids.obj 1 
Error LNK1120 1 unresolved externals asteroids D:\writing\Amazon EBooks\GamesProgrammer\publishing\Learn C Games Programming\Windows\Code\asteroids_ch48\asteroids\Debug\asteroids.exe 1

So obviously only do this with global variables that are not going top be referred to. In this case we do refer to errorCount in Asteroids.c so adding the static would make no sense.

Working with Mice in SDL

Working with Mice in SDL

Computer mouse
Image by OpenClipart-Vectors from Pixabay

On the Match three game, I’m at the point where I need to be able to click on a piece and drag it to the next piece (horizontal or vertical) and then start the two animating to swap positions.

In SDL, I’ve got a simple mouseclick function that is called from ProcessEvents (my function for handling all input) with the x,y coordinates on the screen where clicked. These have to be  converted from screen coordinates to board coordinates (or ignored if not on the board) to identify the piece clicked. However the mouse now needs to drag this piece to an adjacent piece.

As usual I’m not the first person to ask this and there’s a StackOverflow Question with an answer. So I’ll be following this answer and hopefully get it working. This is possibly the key mechanic in a MatchThree game so it’s important to get it right. After that I’ll get teh touchscreen working again which should in theory use the same code apart from reading the game controller..

Do you declare variables at the top of functions

Do you declare variables at the top of functions

Matrix code
Image by Pete Linforth from Pixabay

This is for C99 and later. Prior to this, in function you had to declare all the variables that would be used in that function before any code. Since C99, you can declare them nearer to where they are used.

This function is from the Asteroids game. The declaration of the two variables hx,hy could have been moved to just before the do-loop. They can’t be declared inside the do-loop because they are used after it.

// doHyperJump() find empty space on screen fo PlayerShip
void CheckJump() {
	int hx, hy;

	if (jumpFlag && SDL_GetTicks() - jumpTimer > 3000) { 
		jumpTimer = SDL_GetTicks();
		jumpFlag = 0;
		do {
			hx = 65 + Random(SCREENWIDTH - 130);
			hy = 65 + Random(SCREENHEIGHT - 130);
			if (IsEmptySpace(hx, hy)) break;
		} while (1);
		Player.x = (float)hx;
		Player.y = (float)hy;
		Player.vx = 0;
		Player.vy = 0;
	}
}

This is one of those cases where it doesn’t really matter. But generally I will declare them close to where they are first used and I almost always declare the for-loop variable in the for-loop. Only if it’s needed afterwards do I declare it after, but that is a slightly iffy use unless you want to check the value it had when it exited the loop.

Remember the scope of the variable i.e. the part of the function in which the variable can be accessed starts just after it is declared. By keeping declarations near the code, you reduce the scope and this can help robustness.

More open source games on Sourceforge.net

More open source games on Sourceforge.net

Sourceforge games filterA couple of weeks ago I looked at GitHub. Now it’s time for Sourceforge. Like GitHub, it’s an open source repository and has been around for well over 15 years. Instead of using search parameter there are filters that let you specify games, types of games, programming language and project maturity.

The screenshot shows the games part of the filter, what you can’t see is further down in the Programming languages where I’ve ticked C and Status where I’ve ticked Production/Stable. So SourceForge contains 67 production ready Role-playing games in C.

You have to us the status or else you’ll get 100s of projects that have been started then abandoned, often without any code.  One or two projects have migrated to GitHub, so their code here is old.

I have some ideas for big multi-player games myself but I’d like to try a novel approach. The game clients run on your computer and communicate with a server. However it’s not real-time but sends commands to the game server via a web interface and can check for results the same way. If you like, it’s a modern take on postal gaming except that used printers and the postal service to send printouts. Of course with WebAssembly, it could run in your browser.

Slight change of pace

Slight change of pace

Networking
Image by Gordon Johnson from Pixabay

I’ve managed one blog entry per day for the last 134 days but a change in side project (I was writing a book to be published, not an Ebook)  but that has to be delayed by at least a year because of an issue at the publisher. In fact I may just publish what I’ve done as my 2nd Ebook.

I’m currently working on networking on a Raspberry Pi. Unfortunately it has to be in C# not C. Networking is a lot easier in C#- you have OOP, task parallel library (far easier than threads), thread pools,. concurrency with async/await and a lot more.  And I can use C# with .NET core or Mono on the Pi.

That said, I will still continue on with game development on the PI. I’ve got my Match Three game half done; I’m quite proud of it and want to get it finished. But I may switch to a slightly less frequent blog posting schedule…

 

Using heap memory with malloc

Using heap memory with malloc

For some reason malloc seems to confuse new programmers but it’s very straightforward.  I didn’t use it or even talk about it in the ebook. Memory allocation is not something you want to be doing in a game loop, running 60 times a second. All the memory that was ever used in the asteroids game was for text strings, variables and arrays and you don’t have to explicitly allocate any memory for those.

When you have a program that needs to allocate and free memory, like say a compiler or text editor then you grab a block of RAM using malloc.  You have to specify how much RAM you need and you must type cast it, because malloc return a void *.

Here’s an example. The image shows the output in the Visual Studio debugger.


#include <stdio.h>
#include <stdlib.h>

char* ptr[10];
int main() {
	for (int i = 0; i < 10; i++) {
		ptr[i] = (char *)malloc(1000);			
		char* aptr = ptr[i];
		for (int j = 0; j < 1000; j++) {
			aptr[j] = i + 64;
		}
        }
	for (int i = 0; i < 10; i++) {
		free(ptr[i]);
	}
}

DEbugger showing array valuesThis is what the Visual Studio debugger shows just before the final loop that calls free.

It has allocated 1000 bytes of memory for each of the ten char * in ptr[] and then fills it with 1000 each of the ASCII values 64..73 @

Finally, it frees up the memory using free. For every malloc, there should be a corresponding free or else your program will develop a memory leak.