Skip to content →

bug hunting – get more games going

Tennis

Missing STAT interrupt

The window layer in the PPU is mostly used for menus, or overlays. It can be offset on the X- and the Y-Axis, but only to positive numbers. This is what caused this bug in Tennis for me. The scoreboard in the upper right corner is the window layer, that is offset to the right of the screen. But since we can’t offset it “up”, it shows the scoreboard and blocks the actual court with white color.

Tennis – Window layer blocking – missing STAT interrupt

To fix this, I had to implement / fix the STAT interrupt. The STAT-interrupt can be caused on the LYC=LY coincidence. This way, a programmer can set LYC to the line he wants the window layer to stop drawing. The interrupt will fire once the current line drawn (LY) is equal to LYC, and we can just disable window drawing completely (until the next frame). With this implementation, we can achieve the result we hoped for.

Tennis – fixed STAT interrupt, fix Win drawing

Not handling panning on sound channels

Since I did not plan on implementing the panning of sound channels, I completely ignored the registers responsible for panning. A mistake that cause me multiple days of frustration and debugging, until I finally discovered the relevance of these registers. Tennis makes use of the panning registers, to disable channels. This is a very weird technology, as there is e.g. the length counter that is designed to do something like that. Without handling these panning registers though, some sounds won’t stop, or won’t stop sweeping, like you can hear on the ball bounce.

Note: In the following video the sound bug on the ball bounce is already greatly reduced by other factors. Sadly I don't have any video left of the initially longer sound problem, where the sound wouldn't stop until another sound appeared on the channel.
Tennis – Ball bounce sound bug (already reduced in intensity)

Also, the racket swing sounds too long, and off, also caused by the same behavior.

Tennis – Racket swing sound bug

After implementing a check for the panning registers, if there is any sound at all for the channel, before pushing to the channels buffer, all sound bugs were fixed.

//	enabled channel
if (SC4enabled && ((readFromMem(0xff26) >> 3) & 1) && (readFromMem(0xff21) & 0xf8) && (readFromMem(0xff25) & 0x88)) {
	//	push data to buffer
	SC4buf.push_back((SC4lfsr & 0x1) ? 0 : (float) SC4amp / 100);
	SC4buf.push_back((SC4lfsr & 0x1) ? 0 : (float) SC4amp / 100);
...
Tennis – sound bugs fixed

Super Mario Land

This game was a good baseline for me, since it has scrolling, complex sprites etc. I fixed minor scrolling bugs (due to wrapping on the VRAM), sprite flipping and timings later on. But what boggled my mind was this problem. If you are familiar with the automatic demos on this game, you will see that the demo end way too early.

Super Mario Land – demo too short

After a lot of debugging and testing, my mistake was pretty clear. My V-Blank interrupt was firing on every cycle inside V-Blank, so way too often! After I fixed this, to only fire once V-Blank entered, the demos ran the normal length.

// if vblank, draw once (drawFlag)
if (!frameDrawnFlag && readFromMem(0xff44) == 144) {

	//	V-Blank interrupt IF
	writeToMem(0xff0f, readFromMem(0xff0f) | 1);

	drawFrame();
	frameDrawnFlag = 1;

}

Mario & Yoshi / Super Mario Land 2

These two games gave me headaches again. After other games started to run perfectly smooth and normal, Mario & Yoshi did not boot at all, and only showed a blank screen, while Super Mario Land 2 – 6 Golden Coins would show the title screen, but when pressed START would only fade out, to return back to the title screen (instead of the save game selection screen)

Super Mario Land 2 – The game would not go past this screen

I finally got this fixed, after I let the PPU only fire V-Blank interrupts if the Display is not off. So, I modified the code from above slightly.

// if vblank, draw once (drawFlag)
if (!frameDrawnFlag && readFromMem(0xff44) == 144) {
	
	//	only draw if display is enabled
	if (readFromMem(0xff40) >> 7) {
		//	V-Blank interrupt IF
		writeToMem(0xff0f, readFromMem(0xff0f) | 1);

		drawFrame();
		frameDrawnFlag = 1;

	}
}

With this minimal fix, I was able to get past Super Mario Land 2’s title screen, and also boot into Mario & Yoshi.

Super Mario Land 2 – Fixed title screen bug
Mario & Yoshi – Boot bug fixed

Despite the missing sprite ordering (as you can see as Mario goes down the pipe in the SM2 gif), these were all the bugs I encountered for now. So it was time, to add some features to the emulator, to make it neat.

Comments

Leave a Reply