Close

Sprites and Game Loop

A project log for Dodo: 6502 Game System

Handheld Game System featuring the 6502

peter-noyesPeter Noyes 03/01/2016 at 22:210 Comments

The software is coming along. The screen is now rendering at a consistent FPS based on the timer interrupt. The timer counts 50,000 clock cycles at a time, which at a 1mhz CPU comes out to 20 fps. The LED flashing in the video is flashing once per frame. Instead of running all game code in the IRQ handler, I instead added a wait for irq call. The IRQ handler simply sets a flag when interrupted, and the wait call spins until that flag is set. This way a minimal amount of code runs in the interrupt handler. The main game loop just calls wait each cycle.

I also figure this is best because cc65 triggers BRK whenever the runtime encounters a fault, and BRK causes a software interrupt to fire. If the majority of my code was actually in the interrupt handler, then I would never be able to react to or even detect a BRK properly.

I also now have sprite drawing fully working. Previously my sprite drawing routine was only working if the y offset of the sprite was on a page boundary of 0, 8, 16, etc... The routine is a bit complicated because it is optimized to move as many bits at a time as possibly straight into video memory, rather than the naive approach of calling getpixel / setpixel. Here is the routine, with really ugly variable names:

void drawSprite(unsigned char* sprite, unsigned char x, unsigned char y, unsigned char w, unsigned char h) {
	unsigned char p = y/8;
	unsigned char yoff = y%8;
	unsigned char yoff_inv = 8-yoff;
	unsigned char i = 0;
	unsigned char il = 0;
	unsigned char yp = 0;
	unsigned char last = 0;

	unsigned char* vmem = VIDEO_MEM; // + _char_x + (p*128);
	for (i = 0; i < p; ++i) {
		vmem += 128;
	}
	vmem += x;
	
	i = 0;
	for (yp = 0; yp < h; yp += 8) {
		il += w;
		last = 0;
		for (; i < il; ++i) {
			if (yoff > 0 && yp > 0) {
				last = sprite[i - w] >> yoff_inv;
			}

			*vmem |= (sprite[i] << yoff) + last;
			vmem++;
		}

		vmem += (128 - w);
	}

	// Go through last set of sprite data becasue it spills over into next page of VMEM
	if (yoff > 0) {
		i -= w;
		for (; i < il; ++i) {
			*vmem |= (sprite[i] >> yoff_inv);
			++vmem;
		}
	}
}

Discussions