Sprite tile fetch/fill issue
Moderator: Moderators
- fergus_maximus
- Posts: 38
- Joined: Sun Jul 29, 2012 10:13 am
- Location: Chicago, IL
- Contact:
Sprite tile fetch/fill issue
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.
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.
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.
Re: Sprite tile fetch/fill issue
Post some code to get more replies. But on 8KB switching, are you ignoring the lowest bit?
Re: Sprite tile fetch/fill issue
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)
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)
- fergus_maximus
- Posts: 38
- Joined: Sun Jul 29, 2012 10:13 am
- Location: Chicago, IL
- Contact:
Re: Sprite tile fetch/fill issue
Exactly what I thought but I verified the address coming in is certainly the appropriate one.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)
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]
}
Shifting it out, yeah:3gengames wrote:Post some code to get more replies. But on 8KB switching, are you ignoring the lowest bit?
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
}
Re: Sprite tile fetch/fill issue
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
- fergus_maximus
- Posts: 38
- Joined: Sun Jul 29, 2012 10:13 am
- Location: Chicago, IL
- Contact:
Re: Sprite tile fetch/fill issue
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 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
Re: Sprite tile fetch/fill issue
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.
- fergus_maximus
- Posts: 38
- Joined: Sun Jul 29, 2012 10:13 am
- Location: Chicago, IL
- Contact:
Re: Sprite tile fetch/fill issue
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):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.
Code: Select all
// If reset bit is set
if v&0x80 != 0 {
m.BufferCounter = 0
m.Buffer = 0x0
m.PrgSwapBank = BankLower
m.PrgBankSize = Size16k
}
- fergus_maximus
- Posts: 38
- Joined: Sun Jul 29, 2012 10:13 am
- Location: Chicago, IL
- Contact:
Re: Sprite tile fetch/fill issue
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.
Thanks for the quick responses guys.