Sprite tile fetch/fill issue

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
fergus_maximus
Posts: 38
Joined: Sun Jul 29, 2012 10:13 am
Location: Chicago, IL
Contact:

Sprite tile fetch/fill issue

Post by fergus_maximus »

So I'm in the midst of refactoring my emulator to not be so naive about copying memory while doing a bank switch, and I'm running into some trouble with a limited number of mappers (haven't reworked MMC2/3/5 yet) in certain cases. For MMC1, any game that does 4k CHR swaps runs totally fine but if the game uses 8k CHR swaps you get the effects seen below in Zelda and Bionic Commando. Duck Tales (and other UNROM games) also show the behavior.

ImageImageImage

Digging in it looks like Zelda doesn't even trigger a bank switch for a while when it starts up (or at least not that I can see), so that says to me that the startup bank is wrong but I'm pointing the lower CHR bank (where it has sprites stored) to 0 which worked fine before I refactored. What I'm thinking is that I broke something in how the the sprite pattern tables are filled, but I'm lost at what these games do differently from others that might make those patterns fill incorrectly.

A little abstract, but any thoughts? I can provide relevant code if necessary.
3gengames
Formerly 65024U
Posts: 2284
Joined: Sat Mar 27, 2010 12:57 pm

Re: Sprite tile fetch/fill issue

Post by 3gengames »

Post some code to get more replies. But on 8KB switching, are you ignoring the lowest bit?
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Sprite tile fetch/fill issue

Post by lidnariq »

Looks like you're fetching some things from the wrong pattern table.
e.g. with Duck Tales, Scrooge McDuck should be from the left pattern table (PPU $0xxx), but you're drawing him from the right pattern table (PPU $1xxx)
User avatar
fergus_maximus
Posts: 38
Joined: Sun Jul 29, 2012 10:13 am
Location: Chicago, IL
Contact:

Re: Sprite tile fetch/fill issue

Post by fergus_maximus »

lidnariq wrote:Looks like you're fetching some things from the wrong pattern table.
e.g. with Duck Tales, Scrooge McDuck should be from the left pattern table (PPU $0xxx), but you're drawing him from the right pattern table (PPU $1xxx)
Exactly what I thought but I verified the address coming in is certainly the appropriate one.

CHR banks are stored in 4k arrays, here's the relevant code to read from that address space and to fetch a tile:

Code: Select all

func (m *Mmc1) ReadVram(a int) Word {
	if a >= 0x1000 {
		return m.VromBanks[m.ChrUpperBank][a&0xFFF]
	}

	return m.VromBanks[m.ChrLowerBank][a&0xFFF]
}

func (m *Mmc1) ReadTile(a int) []Word {
	if a >= 0x1000 {
		return m.VromBanks[m.ChrUpperBank][a&0xFFF : a&0xFFF+16]
	}

	return m.VromBanks[m.ChrLowerBank][a&0xFFF : a&0xFFF+16]
}
3gengames wrote:Post some code to get more replies. But on 8KB switching, are you ignoring the lowest bit?
Shifting it out, yeah:

Code: Select all

		switch m.ChrBankSize {
		case Size8k:
			// Swap 8k VROM (in 8k mode, ignore first bit D0)
			bank := v & 0xF
			bank %= len(m.VromBanks)

			if v&0x10 == 0x10 {
				bank = (len(m.VromBanks) / 2) + (v & 0xF)
			} else {
				bank = v & 0xF
			}

			m.ChrUpperBank = (bank >> 1) + 1
			m.ChrLowerBank = (bank >> 1)
		case Size4k:
			// Swap 4k VROM
			var bank int

			if v&0x10 == 0x10 {
				bank = (len(m.VromBanks) / 2) + (v & 0xF)
			} else {
				bank = v & 0xF
			}
			m.ChrLowerBank = bank
		}
3gengames
Formerly 65024U
Posts: 2284
Joined: Sat Mar 27, 2010 12:57 pm

Re: Sprite tile fetch/fill issue

Post by 3gengames »

Why not just do an & 0xFE? Shifting it makes it "wrong" because 8KB banks are the same as 4K except the bank value swapped is +1'd for the 2nd bank.5
User avatar
fergus_maximus
Posts: 38
Joined: Sun Jul 29, 2012 10:13 am
Location: Chicago, IL
Contact:

Re: Sprite tile fetch/fill issue

Post by fergus_maximus »

3gengames wrote:Why not just do an & 0xFE? Shifting it makes it "wrong" because 8KB banks are the same as 4K except the bank value swapped is +1'd for the 2nd bank.5
Good point, made the change. Problem I'm seeing though is that the bank swap never occurs before the Zelda title screen appears. I see the lower bank get filled but it's clearly the wrong data (or I'm reading it wrong in the mapper).
3gengames
Formerly 65024U
Posts: 2284
Joined: Sat Mar 27, 2010 12:57 pm

Re: Sprite tile fetch/fill issue

Post by 3gengames »

Is the reset bit written to? I'm going to assume reset sets CHR to 0, but that's just guessing. Anyone know for sure? If I had a working compiler on Linux that wasn't 10 years to set up, I'd write a test ROM and run it on hardware, but don't have one.
User avatar
fergus_maximus
Posts: 38
Joined: Sun Jul 29, 2012 10:13 am
Location: Chicago, IL
Contact:

Re: Sprite tile fetch/fill issue

Post by fergus_maximus »

3gengames wrote:Is the reset bit written to? I'm going to assume reset sets CHR to 0, but that's just guessing. Anyone know for sure? If I had a working compiler on Linux that wasn't 10 years to set up, I'd write a test ROM and run it on hardware, but don't have one.
Been a while since I wrote this mapper, but I only have the PRG banks as being reset when the reset bit gets set (and the mapper received a write):

Code: Select all

        // If reset bit is set
	if v&0x80 != 0 {
		m.BufferCounter = 0
		m.Buffer = 0x0

		m.PrgSwapBank = BankLower
		m.PrgBankSize = Size16k
	}
User avatar
fergus_maximus
Posts: 38
Joined: Sun Jul 29, 2012 10:13 am
Location: Chicago, IL
Contact:

Re: Sprite tile fetch/fill issue

Post by fergus_maximus »

Ha, I found it. Silly lack of a return after writing the to the high banks so it would write to both banks.

Thanks for the quick responses guys.
Post Reply