MMC5 problems...
Moderator: Moderators
Re: MMC5 problems...
The left and right thirds of the screen are 4 tiles or so too high, but the center portion is much worse. Almost seems like a PPUADDR problem?
In any case, exattr mode seems to be applying consistently. If you can walk around in the opening town of Just Breed without anything looking wrong, exattr mode is probably working right.
In any case, exattr mode seems to be applying consistently. If you can walk around in the opening town of Just Breed without anything looking wrong, exattr mode is probably working right.
Re: MMC5 problems...
IRQ timing?
Re: MMC5 problems...
The title screen in question doesn't have any splitscreening going on (exattr lets it show all of those tiles without needing a midframe bankswitch).
Re: MMC5 problems...
I wonder if you are somehow using the X part of the scroll as the Y part? That'd be weird because nothing on the MMC5 has any impact on the scroll (except for the splitscreen mode stuff... but you're not doing that yet I assume).
Re: MMC5 problems...
Mmm... i don't get it. I mean my fetchTile() routine is not changing scroll at all.Disch wrote:I wonder if you are somehow using the X part of the scroll as the Y part? That'd be weird because nothing on the MMC5 has any impact on the scroll (except for the splitscreen mode stuff... but you're not doing that yet I assume).
Anyway here is my poor code thats fetch a mmc5 tile:
Code: Select all
void FetchTileMmc5(int cc)
{
extern MMC5 Mmc5;
extern pu8 g_pChrRom;
switch (cc & 0x07)
{
case 0:
Ppu.pt_addr = 0x2000 | (Ppu.addr & 0x03FF);
break;
case 1:
Ppu.NTIndex = ReadPpuMem(Ppu.pt_addr);
Ppu.NTIndex <<= 4;
break;
case 3:
Mmc5.ex1 = ReadMmc5ExtraRam(Ppu.pt_addr);
Ppu.AT = Mmc5.ex1;
Ppu.AT >>= 6;
break;
case 4:
Ppu.pt_addr = Ppu.NTIndex | ((PPPUADDR)(&Ppu.addr ))->FineY;
break;
case 5:
Mmc5.addr = Mmc5.upper_chr << 18;
Mmc5.addr |= (Mmc5.ex1 & 0x3F) << 12;
Ppu.lPT0 = g_pChrRom[((Ppu.pt_addr /*& 0xFFF*/) | Mmc5.addr) & (Mmc5.chr_size - 1)];
break;
case 6:
Ppu.pt_addr |= 0x08;
break;
case 7:
Ppu.lPT1 = g_pChrRom[((Ppu.pt_addr /*& 0xFFF*/) | Mmc5.addr) & (Mmc5.chr_size - 1)];
Ppu.PT0 |= Ppu.lPT0;
Ppu.PT1 |= Ppu.lPT1;
Ppu.lAT0 = Ppu.AT & 0x01;
Ppu.lAT1 = (Ppu.AT & 0x02) >> 1;
break;
}
}
The only thing to say here is that ((PPPUADDR)(&Ppu.addr ))->FineY is a pointer to a bit structure that represents the PPU ADDR.
ANes
Re: MMC5 problems...
Since your code does not check for Ex1 mode, I assume it is only called in Ex1 mode.
You're losing the nametable bits. You probably meant & 0x0FFF
I don't see anything wrong apart from that.
Code: Select all
Ppu.pt_addr = 0x2000 | (Ppu.addr & 0x03FF);I don't see anything wrong apart from that.
Re: MMC5 problems...
No, it still has problems... f**n bakground.... i have to check in other places of my code.Disch wrote:Since your code does not check for Ex1 mode, I assume it is only called in Ex1 mode.
You're losing the nametable bits. You probably meant & 0x0FFFCode: Select all
Ppu.pt_addr = 0x2000 | (Ppu.addr & 0x03FF);
I don't see anything wrong apart from that.
Thanks.
ANes
Re: MMC5 problems...
Thank to Disch that reviewed my code UW now runs.
I still have two problems:
1) UW gets hang when it enters the first level:

Basically the game is making a JMP Absolute to the same addr. This makes a loop forever.
I have checked for MMC5 interrupts and the game disables it and at the same time is Executing a SEI, so IRQ never executes.
Another thing to mention is that is disabling NMI trough a write to $2000.
So how can it get out of that infinite loop?
Any clue??
2) BK of Ancient China:

Disch's and the Wiki says:
I still have two problems:
1) UW gets hang when it enters the first level:

Basically the game is making a JMP Absolute to the same addr. This makes a loop forever.
I have checked for MMC5 interrupts and the game disables it and at the same time is Executing a SEI, so IRQ never executes.
Another thing to mention is that is disabling NMI trough a write to $2000.
So how can it get out of that infinite loop?
Any clue??
2) BK of Ancient China:

Disch's and the Wiki says:
I think that is happening. I really dont understand the "$8000 + ROM area".Test ROM Notes:
---------------------------
- Bandit Kings of Ancient China writes PRG-RAM through the $8000+ ROM area. Failure to emulate this causes
corruption when the background is restored on the world map.
ANes
Re: MMC5 problems...
Bandit Kings is probably swapping RAM into the $8000-BFFF area... rather than swapping ROM. See the high bit of the PRG swap regs. It's possible you are always swapping in ROM, which would explain this bug.
This might also be the cause of your UW bug, but I don't know for sure.
This might also be the cause of your UW bug, but I don't know for sure.
Re: MMC5 problems...
$5115 swaps $8000 - $BFFF can only be swapped in program mode "1" or "2" and UW nevers change it. It sticks to "3"!!
Does program mode affect prg-ram swapping? I tested my emu not affecting it and have the same results.
I will keep checking...
Does program mode affect prg-ram swapping? I tested my emu not affecting it and have the same results.
I will keep checking...
ANes
Re: MMC5 problems...
$5115 is somewhat irrelevent. In any mode, you're able to swap out PRG, right? So any time you swap PRG, the high bit determines whether to select RAM or ROM.$5115 swaps $8000 - $BFFF can only be swapped in program mode "1" or "2" and UW nevers change it. It sticks to "3"!!
The only exception is $5117 .. which will always select ROM (note this also means PRG mode 0 will only select ROM, since $5117 is the only swap reg used in that mode).
ROM/RAM can be selected in any other mode (modes 1-3)
It affects which registers are used and how. If any of the $5114-5116 registers are being used... they can select ROM or RAM. Whether or not those registers are used depends on the mode.Does program mode affect prg-ram swapping? I tested my emu not affecting it and have the same results.
Re: MMC5 problems...
My code looks like this:
I can't find any error, and there are.
MapMemory(from, to, pFunRead, pFunWrite): as it names implies map the memory into an array of function pointers.
SwapPrg4K(addr, bank, size): It does the ROM swap.
SwapMmc5Ram(page, wherein, size):Takes the caluclated page and directly memcpy to "wherein" into a plain 64K of "size".
You said i can avoid prg-mode when i swap prg-ram. I have tried commenting:
"ifs" and "switchs" and no result.
Code: Select all
case 0x5113:
Mmc5.r5113 = (data & 0x07);
page_kb32 = Mmc5.r5113 * KB_8;
SwapMmc5Ram(page_kb32, 0x6000, 0x2000);
MapMemory(0x6000, 0x7FFF, ReadMmc5Extra64, WriteMmc5Extra64);
break;
case 0x5114:
if ((data & 0x80))
{
if (Mmc5.prg_mode == 3)
{
MapMemory(0x8000, 0x9FFF, ReadMapperPrgMem, WriteMapperPrgMem);
SwapPrg4K(0x8000, (data & 0x7F) & (((Mapper.last_prg)* 4)-1), 0x2000);
}
}
else
{
if (Mmc5.prg_mode == 3)
{
page_kb32 = (data & 0x07) * KB_8;
SwapMmc5Ram(page_kb32, 0x8000, 0x2000);
MapMemory(0x8000, 0x9FFF, ReadMmc5Extra64, WriteMmc5Extra64);
}
}
break;
case 0x5115:
if ((data & 0x80))
{
if (Mmc5.prg_mode == 1 || Mmc5.prg_mode == 2)
{
MapMemory(0x8000, 0xBFFF, ReadMapperPrgMem, WriteMapperPrgMem);
SwapPrg4K(0x8000, ((data & 0x7F) >> 1) & (((Mapper.last_prg)* 2)-1), 0x4000);
}
else
if (Mmc5.prg_mode == 3)
{
MapMemory(0xA000, 0xBFFF, ReadMapperPrgMem, WriteMapperPrgMem);
SwapPrg4K(0xA000, (data & 0x7F) & (((Mapper.last_prg)* 4)-1), 0x2000);
}
}
else
{
if (Mmc5.prg_mode == 1 || Mmc5.prg_mode == 2)
{
page_kb32 = (data & 0x07) * KB_8;
SwapMmc5Ram(page_kb32, 0x8000, 0x4000);
MapMemory(0x8000, 0xBFFF, ReadMmc5Extra64, WriteMmc5Extra64);
}
else
if (Mmc5.prg_mode == 3)
{
page_kb32 = (data & 0x07) * KB_8;
SwapMmc5Ram(page_kb32, 0xA000, 0x2000);
MapMemory(0xA000, 0xBFFF, ReadMmc5Extra64, WriteMmc5Extra64);
}
}
break;
case 0x5116:
if ((data & 0x80))
{
switch (Mmc5.prg_mode)
{
case 2:
MapMemory(0xC000, 0xDFFF, ReadMapperPrgMem, WriteMapperPrgMem);
SwapPrg4K(0xC000, (data & 0x7F) & (((Mapper.last_prg)* 4)-1), 0x2000);
case 3:
MapMemory(0xC000, 0xDFFF, ReadMapperPrgMem, WriteMapperPrgMem);
SwapPrg4K(0xC000, (data & 0x7F) & (((Mapper.last_prg)* 4)-1), 0x2000);
break;
}
}
else
{
switch (Mmc5.prg_mode)
{
case 2:
case 3:
page_kb32 = (data & 0x07) * KB_8;
SwapMmc5Ram(page_kb32, 0xC000, 0x2000);
MapMemory(0xC000, 0xDFFF, ReadMmc5Extra64, WriteMmc5Extra64);
break;
}
}
break;
case 0x5117:
switch (Mmc5.prg_mode)
{
case 0:
MapMemory(0x8000, 0xFFFF, ReadMapperPrgMem, WriteMapperPrgMem);
SwapPrg4K(0x8000, ((data & 0x7F) >> 2) & (Mapper.last_prg - 1), 0x8000);
break;
case 1:
MapMemory(0xC000, 0xFFFF, ReadMapperPrgMem, WriteMapperPrgMem);
SwapPrg4K(0xC000, ((data & 0x7F) >> 1) & (((Mapper.last_prg)* 2)-1), 0x4000);
break;
case 2:
case 3:
MapMemory(0xE000, 0xFFFF, ReadMapperPrgMem, WriteMapperPrgMem);
SwapPrg4K(0xE000, (data & 0x7F) & (((Mapper.last_prg)* 4)-1), 0x2000);
break;
}
break;
MapMemory(from, to, pFunRead, pFunWrite): as it names implies map the memory into an array of function pointers.
SwapPrg4K(addr, bank, size): It does the ROM swap.
SwapMmc5Ram(page, wherein, size):Takes the caluclated page and directly memcpy to "wherein" into a plain 64K of "size".
You said i can avoid prg-mode when i swap prg-ram. I have tried commenting:
Code: Select all
if (Mmc5.prg_mode == 3) ANes
Re: MMC5 problems...
I didn't look over the code too closely (kind of at work, so I can only take quick breaks). However, you are showing me 2 things that are kind of alarming.
#1:
The same memory could be swapped into 2 different places. For example.. if it swaps RAM page 1 into both $8000 and $6000... then those two areas would effectively be "mirrored". Writes to $6000 would be visible at $8000 and vice versa.
#2:
You are doing complex logic in your register writes, rather than a "sync" style function. This will work as long as the game does not switch modes... but as soon as it does, you'll either have to duplicate all that logic, or you will have the wrong stuff swapped in.
When the game changes modes, it's as if it "reswaps" all pages. This is often implemented as a "sync" function. IE when the game writes to the mode, you change the mode var, then 'sync'. And when it writes to a PRG swap reg, you just modify a variable and then 'sync' again. The 'sync' function is the one that would be examining the mode and swapping out all the pages.
Also note that this is not MMC5 specific, but applies to all mappers.
#1:
memcpy is a bad sign. There is no copying going on when you swap. What's happening is the chip is modifying the address lines on access.SwapMmc5Ram(page, wherein, size):Takes the caluclated page and directly memcpy to "wherein" into a plain 64K of "size".
The same memory could be swapped into 2 different places. For example.. if it swaps RAM page 1 into both $8000 and $6000... then those two areas would effectively be "mirrored". Writes to $6000 would be visible at $8000 and vice versa.
#2:
You are doing complex logic in your register writes, rather than a "sync" style function. This will work as long as the game does not switch modes... but as soon as it does, you'll either have to duplicate all that logic, or you will have the wrong stuff swapped in.
When the game changes modes, it's as if it "reswaps" all pages. This is often implemented as a "sync" function. IE when the game writes to the mode, you change the mode var, then 'sync'. And when it writes to a PRG swap reg, you just modify a variable and then 'sync' again. The 'sync' function is the one that would be examining the mode and swapping out all the pages.
Also note that this is not MMC5 specific, but applies to all mappers.
Re: MMC5 problems...
I did one thing: i "marged" with my mapping engine.... i mean i used SwapPrg4K() to swap prg-ram.
UW Works (with some graphics glitches):

and BK of Ancient China now looks good.
The thing is i have a 64kb that's in the mapper... if i knew the prg-ram size would be prominent, but the wiki says that byte "8" should indicate that and roms out there have only "0". But, but it says that emulators even don't use this byte.
What do i do?
UW Works (with some graphics glitches):

and BK of Ancient China now looks good.
The thing is i have a 64kb that's in the mapper... if i knew the prg-ram size would be prominent, but the wiki says that byte "8" should indicate that and roms out there have only "0". But, but it says that emulators even don't use this byte.
What do i do?
ANes