Hi everyone! I'm having some problems while implementing scrolling. Look at this cap:
I guess the problem might be in the way I'm handling the Name Tables. I'm using two variables to hold the directions for VRAM access: one for the "general" VRAM access (wich I'll call VRAMAddress from now on) and other for rendering (wich I'll call LoopyV from now on). Both are setted in the second write to $2006 register. LoopyV is modified in rendering while VRAMAddress doesn't, so if a value is written to a Name Table via $2007 register during HBlank, this will be written in the address pointed by VRAMAddress (and not in the address pointed by LoopyV). Is this correct? I'm asking just to be sure, because I can't figure out why the graphics are shown like this (i mean like the graphics in the imagen previously shown). Just in case, this is the way I'm handling mirroring and $2005/6 registers write:
Sprite #0 hit flag is implemented correctly, or that's what I think since Mario starts running all across the screen a few seconds after the main screen have been shown.
At this point, I don't know if this is a mirroring issue or a scrolling issue.
Any hint will be gratefully thanked. Thank you all in advance.
I guess the problem might be in the way I'm handling the Name Tables. I'm using two variables to hold the directions for VRAM access: one for the "general" VRAM access (wich I'll call VRAMAddress from now on) and other for rendering (wich I'll call LoopyV from now on). Both are setted in the second write to $2006 register. LoopyV is modified in rendering while VRAMAddress doesn't, so if a value is written to a Name Table via $2007 register during HBlank, this will be written in the address pointed by VRAMAddress (and not in the address pointed by LoopyV). Is this correct? I'm asking just to be sure, because I can't figure out why the graphics are shown like this (i mean like the graphics in the imagen previously shown). Just in case, this is the way I'm handling mirroring and $2005/6 registers write:
Code:
void WriteRegister2005(byte Value)
{
if(!VRAMLatchHigh)
{
LoopyT &= (~0x001F);
LoopyT |= (Value >> 3);
}
else
{
LoopyT &= (~0x73E0);
LoopyT |= ((Value & 0xF8) << 2);
LoopyT |= ((Value & 0x7) << 12);
}
VRAMLatchHigh = (!VRAMLatchHigh);
}
{
if(!VRAMLatchHigh)
{
LoopyT &= (~0x001F);
LoopyT |= (Value >> 3);
}
else
{
LoopyT &= (~0x73E0);
LoopyT |= ((Value & 0xF8) << 2);
LoopyT |= ((Value & 0x7) << 12);
}
VRAMLatchHigh = (!VRAMLatchHigh);
}
Code:
void WriteRegister2006(byte Value)
{
if(!VRAMLatchHigh)
{
LoopyT &= (~0xFF00);
LoopyT |= ((Value & 0x3F) << 8);
}
else
{
LoopyT &= (~0x00FF);
LoopyT |= Value;
VRAMAddress = LoopyT;
LoopyV = LoopyT;
}
VRAMLatchHigh = (!VRAMLatchHigh);
}
{
if(!VRAMLatchHigh)
{
LoopyT &= (~0xFF00);
LoopyT |= ((Value & 0x3F) << 8);
}
else
{
LoopyT &= (~0x00FF);
LoopyT |= Value;
VRAMAddress = LoopyT;
LoopyV = LoopyT;
}
VRAMLatchHigh = (!VRAMLatchHigh);
}
Code:
void WriteRegister2007(byte Value)
{
// Mappers
if(VRAMAddress < 0x2000)
{
// Nothing yet. To be writen while implementing mappers
}
// Name tables
else if((VRAMAddress >= 0x2000) && (VRAMAddress < 0x3F00))
{
if(Mirroring == MIRRORING_HORIZONTAL)
{
switch(VRAMAddress & 0x2C00)
{
case 0x2000: VRAM[VRAMAddress] = VRAM[VRAMAddress + 0x400] = Value; break;
case 0x2400: VRAM[VRAMAddress] = VRAM[VRAMAddress - 0x400] = Value; break;
case 0x2800: VRAM[VRAMAddress] = VRAM[VRAMAddress + 0x400] = Value; break;
case 0x2C00: VRAM[VRAMAddress] = VRAM[VRAMAddress - 0x400] = Value; break;
}
}
else if(Mirroring == MIRRORING_VERTICAL)
{
switch(VRAMAddress & 0x2C00)
{
case 0x2000: VRAM[VRAMAddress] = VRAM[VRAMAddress + 0x800] = Value; break;
case 0x2400: VRAM[VRAMAddress] = VRAM[VRAMAddress + 0x800] = Value; break;
case 0x2800: VRAM[VRAMAddress] = VRAM[VRAMAddress - 0x800] = Value; break;
case 0x2C00: VRAM[VRAMAddress] = VRAM[VRAMAddress - 0x800] = Value; break;
}
}
}
// Palette
else if((VRAMAddress >= 0x3F00) && (VRAMAddress < 0x3F20))
{
VRAM[VRAMAddress] = Value & 0x3F;
if((VRAMAddress == 0x3F00) || (VRAMAddress == 0x3F10)) VRAM[0x3F00] = VRAM[0x3F10] = Value & 0x3F;
if((VRAMAddress == 0x3F04) || (VRAMAddress == 0x3F14)) VRAM[0x3F04] = VRAM[0x3F14] = Value & 0x3F;
if((VRAMAddress == 0x3F08) || (VRAMAddress == 0x3F18)) VRAM[0x3F08] = VRAM[0x3F18] = Value & 0x3F;
if((VRAMAddress == 0x3F0C) || (VRAMAddress == 0x3F1C)) VRAM[0x3F0C] = VRAM[0x3F1C] = Value & 0x3F;
}
}
{
// Mappers
if(VRAMAddress < 0x2000)
{
// Nothing yet. To be writen while implementing mappers
}
// Name tables
else if((VRAMAddress >= 0x2000) && (VRAMAddress < 0x3F00))
{
if(Mirroring == MIRRORING_HORIZONTAL)
{
switch(VRAMAddress & 0x2C00)
{
case 0x2000: VRAM[VRAMAddress] = VRAM[VRAMAddress + 0x400] = Value; break;
case 0x2400: VRAM[VRAMAddress] = VRAM[VRAMAddress - 0x400] = Value; break;
case 0x2800: VRAM[VRAMAddress] = VRAM[VRAMAddress + 0x400] = Value; break;
case 0x2C00: VRAM[VRAMAddress] = VRAM[VRAMAddress - 0x400] = Value; break;
}
}
else if(Mirroring == MIRRORING_VERTICAL)
{
switch(VRAMAddress & 0x2C00)
{
case 0x2000: VRAM[VRAMAddress] = VRAM[VRAMAddress + 0x800] = Value; break;
case 0x2400: VRAM[VRAMAddress] = VRAM[VRAMAddress + 0x800] = Value; break;
case 0x2800: VRAM[VRAMAddress] = VRAM[VRAMAddress - 0x800] = Value; break;
case 0x2C00: VRAM[VRAMAddress] = VRAM[VRAMAddress - 0x800] = Value; break;
}
}
}
// Palette
else if((VRAMAddress >= 0x3F00) && (VRAMAddress < 0x3F20))
{
VRAM[VRAMAddress] = Value & 0x3F;
if((VRAMAddress == 0x3F00) || (VRAMAddress == 0x3F10)) VRAM[0x3F00] = VRAM[0x3F10] = Value & 0x3F;
if((VRAMAddress == 0x3F04) || (VRAMAddress == 0x3F14)) VRAM[0x3F04] = VRAM[0x3F14] = Value & 0x3F;
if((VRAMAddress == 0x3F08) || (VRAMAddress == 0x3F18)) VRAM[0x3F08] = VRAM[0x3F18] = Value & 0x3F;
if((VRAMAddress == 0x3F0C) || (VRAMAddress == 0x3F1C)) VRAM[0x3F0C] = VRAM[0x3F1C] = Value & 0x3F;
}
}
Code:
byte ReadRegister2007(word Address)
{
byte Value = 0;
// Address out of palette range -> Delayed read
if (Address < 0x3F00)
{
Value = VRAMBuffer;
// Mappers
if (VRAMAddress < 0x2000)
{
// Nothing yet. To be writen while implementing mappers
}
// Name tables
else if (VRAMAddress >= 0x2000) VRAMBuffer = VRAM[VRAMAddress];
}
// Address in palette range -> No delayed read
else Value = VRAM[Address];
return Value;
}
{
byte Value = 0;
// Address out of palette range -> Delayed read
if (Address < 0x3F00)
{
Value = VRAMBuffer;
// Mappers
if (VRAMAddress < 0x2000)
{
// Nothing yet. To be writen while implementing mappers
}
// Name tables
else if (VRAMAddress >= 0x2000) VRAMBuffer = VRAM[VRAMAddress];
}
// Address in palette range -> No delayed read
else Value = VRAM[Address];
return Value;
}
Sprite #0 hit flag is implemented correctly, or that's what I think since Mario starts running all across the screen a few seconds after the main screen have been shown.
At this point, I don't know if this is a mirroring issue or a scrolling issue.
Any hint will be gratefully thanked. Thank you all in advance.