It is currently Mon Oct 16, 2017 9:11 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Mon Jun 27, 2016 1:25 pm 
Offline
User avatar

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
NOTE: I fixed the problem - thanks to everyone's help on this thread!
Solution may be found towards the end of the thread

I have done quite a few strides with my MMC5 mapper implementation, and in the process rewrote the mirroring mode to allow the generality required by MMC5, and also a mechanism for reading nametables 2 and 3 externally from the PPU (that is the MMC5 mapper in this case). The $5120-$5512B CHR bank switching range seems to be working well both for 8x8 and 8x16 sprite modes. Fill mode also seems to be working well, although the only test in this regard (Castlevania III), fill mode is only used as a temporary blank screen transition, from what I gather. The Intro of the game is also working well (the moving reel bit), except for a tiny glitch at the top 8 pixels, which I suspect could be due to a problem with the scanline irq counter.

Now I am struggling with trying to get the first floor of the castle within Castlevania III to look right. The game's code up to this point seems to only set Extanded Ram mode zero, and to be honest, I'm not quite sure how to apply the Expanded Ram mode rules, for instance if at the point of reading/writing to the range $5C00-$5FFF, or when the PPU reads nametable C, or for both cases. I'm referring to the following:

Code:
Extended RAM mode ($5104)
7  bit  0
---- ----
xxxx xxXX
       ||
       ++- Specify extended RAM usage
0 - Use as extra nametable (possibly for split mode)
1 - Use as extended attribute data (can also be used as extended nametable)
2 - Use as ordinary RAM
3 - Use as ordinary RAM, write protected


From what I understand Mode zero simply allows a name table C to be read from Extended Ram (both tiles and attributes). From what I gather, Castlevania is trying to build the castle's first floor from this. Am I correct?

I'm attaching a screenshot for reference in the hope that it might help lead to the cause of the problem:

Castle First Floor:
Image

The garbled screen is directly above the castle ground floor:
Image

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/


Last edited by colinvella on Tue Jun 28, 2016 1:53 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Mon Jun 27, 2016 2:24 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3192
Location: Mountain View, CA, USA
Not sure if this will help you or not, but: the screenshot depicting "garbled graphics" appears to have nametable/screen layout that matches the very end of the first section when you start the game, before you enter the door (i.e. start the game, go all the way to the right, but don't open the door -- that screen), just with wrong CHR data. Attached is a screenshot as evidence.

A lot of early emulators got MMC5 wrong (some may still!), so the mess-ups in your screenshots look very familiar. I just don't know what the root cause is in every case (varies per emulator).

My impression is that when $5104 is %00, the MMC5's expansion RAM is used as an additional nametable that can be mapped at $2000/2400/2800/2C00 in PPU space (controlled with $5105). You might try reading Disch's mapper doc (005.txt) to get a different (rephrased) view of how it works.


Attachments:
cv3-nestopia.png
cv3-nestopia.png [ 20.91 KiB | Viewed 1534 times ]


Last edited by koitsu on Mon Jun 27, 2016 2:32 pm, edited 2 times in total.
Top
 Profile  
 
PostPosted: Mon Jun 27, 2016 2:30 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3064
Location: Brazil
In short words: IRQ timing problem, not nametable-based.


Top
 Profile  
 
PostPosted: Mon Jun 27, 2016 2:41 pm 
Offline
User avatar

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
koitsu wrote:
Not sure if this will help you or not, but: the screenshot depicting "garbled graphics" appears to have nametable/screen layout that matches the very end of the first section


Well spotted! I do see it now. Cheers :)

Still not sure what's happening though.

Edit: If I go down the stairs to ground floor and then back up. The nametable from the ground floor seems to be used:
Image

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/


Last edited by colinvella on Mon Jun 27, 2016 3:04 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Mon Jun 27, 2016 2:43 pm 
Offline
User avatar

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
Zepper wrote:
In short words: IRQ timing problem, not nametable-based.


Could you explain in more detail please? Why is it so?

Thanks

This is my IRQ counter code BTW. It may well have some incorrect boundary condition handling:
Code:
        public override void StepVideo(int scanLine, int cycle, bool showBackground, bool showSprites)
        {
            ppuRendering = scanLine >= 0 && scanLine < 240 && (showBackground || showSprites);

            if (!ppuRendering)
                irqCounter = 0;

            if (cycle != 0)
                return;

            if (scanLine == 0)
            {
                irqPending = false;
                irqCounter = 0;
            }
            else if (scanLine > 0)
                ++irqCounter;

            if (irqCounter == irqScanline)
            {
                irqPending = true;
                if (irqEnabled)
                    TriggerInterruptRequest?.Invoke();
            }

            if (scanLine > 239)
            {
                irqPending = false;
            }
        }

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/


Top
 Profile  
 
PostPosted: Mon Jun 27, 2016 3:25 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3192
Location: Mountain View, CA, USA
I'd suggest logging writes to $5104 and $5105 to see what may be going on. I get the impression those might be tweaked within the IRQ handler as well, but I'm not sure. I haven't spent much time analysing this game (last time was a few years ago where we began discussing the exact same registers in question; fellow in question posted his MMC5 emulation code as well, including IRQ).

Possibly you have an uninitialised variable somewhere, re: going down the stairs to the ground floor and back up? Grasping at straws here; there isn't a lot of data to go on. :\


Top
 Profile  
 
PostPosted: Mon Jun 27, 2016 5:34 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3064
Location: Brazil
Code:
MMC5 IRQ timing
---------------

READS
   $5204:  [PI.. ....]
     P = IRQ currently pending
     I = "In Frame" signal
   Reading $5204 will clear the pending flag (acknowledging the IRQ).

WRITES
   $5203:  [vvvv vvvv]
     v = IRQ latch
   $5204:  [E... ....]
     E = IRQ enable (1=enabled)

=============
Operation

-At any time when the MMC5 detects that the PPU is inactive*,
the In Frame signal is automatically cleared.

*inactive if out of visible field, or background and sprites are disabled.
(return).

-If the scanline number has changed...

  - If In Frame Signal is clear...
    a) Set In Frame signal
    b) Reset IRQ counter to 0
    c) Clear IRQ pending flag (automatically acknowledging IRQ)
   - otherwise...
    a) Increment IRQ counter
    b) If IRQ counter now equals the trigger value, raise IRQ pending flag


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 3:40 am 
Offline
User avatar

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
koitsu wrote:
I'd suggest logging writes to $5104 and $5105 to see what may be going on. I get the impression those might be tweaked within the IRQ handler as well, but I'm not sure. I haven't spent much time analysing this game (last time was a few years ago where we began discussing the exact same registers in question; fellow in question posted his MMC5 emulation code as well, including IRQ).

Possibly you have an uninitialised variable somewhere, re: going down the stairs to the ground floor and back up? Grasping at straws here; there isn't a lot of data to go on. :\


I added some tracing - here's what I found.
ExRamMode is set only once at the beginning with value $00

The mirror mode is changed a few times for the intro and start screens, alternating between the Pseudo 4 screen mode (11 10 01 00) , Single Page 1 (01 01 01 01) and Vertical (01 00 01 00).
After a brief use of fill mode (11 11 11 11), presumably for a quick transition to black, the game rapidly alternates between Pseudo 4 Screen and Vertical during gameplay (the ruins/garden outside the castle). I'm wondering.. are these rapid mirroring changes to be expected?

Code:
ExRamMode ($5104) = $00 (00000000)        <----- Extended Ram Mode set to 0
Mirror Mode ($5105) = Vertical($44) (01000100)    <----- game intro (movie reel thingy + name select etc.)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Single1($55) (01010101)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Single1($55) (01010101)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = SingleFillMode($FF) (11111111) <----- black screen before playing
Mirror Mode ($5105) = Pseudo4($E4) (11100100)          <----- gameplay starts here
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Vertical($44) (01000100)
Mirror Mode ($5105) = Pseudo4($E4) (11100100)
Mirror Mode ($5105) = Vertical($44) (01000100)

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 3:59 am 
Offline
User avatar

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
I did a minor change to my IRQ counter code (reset IRQ counter when the IRQ latch is written in $5203) and I can already see a difference, parts of the screen seem to have updated correctly as I can see some stained glass windows. I probably have to overhaul the IRQ counter logic as per the algorithm you suggested.

Image

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 4:45 am 
Offline
User avatar

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
I have a question concerning when an IRQ is raised by the counter. The specs say that when the IRQ counter matches the IRQ latch specified by a write to $5203, the "Irq Pending Flag should be raised". Does this mean that the CPU should trigger the IRQ (as in jump to the IRQ vector) as soon as the mapper processing step is over, or should there be some kind of delay? If this is the case, does this allow for the IRQ counter to "cancel" an IRQ request?

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 5:32 am 
Offline
User avatar

Joined: Sat Jan 22, 2005 8:51 am
Posts: 427
Location: Chicago, IL
I had the same problem and it turned out to be a CPU issue. I don't recall the exact details, but I think it had to do with handling the case where the interrupt disable flag was cleared while the irq line was being asserted.

_________________
get nemulator
http://nemulator.com


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 8:11 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3064
Location: Brazil
colinvella wrote:
I have a question concerning when an IRQ is raised by the counter. The specs say that when the IRQ counter matches the IRQ latch specified by a write to $5203, the "Irq Pending Flag should be raised". Does this mean that the CPU should trigger the IRQ (as in jump to the IRQ vector) as soon as the mapper processing step is over, or should there be some kind of delay? If this is the case, does this allow for the IRQ counter to "cancel" an IRQ request?


No delay.
Just note that you must add the InFrame bits for reads.


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 8:42 am 
Offline
User avatar

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
I added more logs for writing to $5203 (IRQ counter) and $5204 (IRQ enable/disable) and from what I gather the game is doing the following:

During the first horizontal walk outside the castle, it sets the IRQ counter to 46, presumably to render the game's HUD in the top 4 rows from one nametable, before splitting to the level nametable (vertical mirrored to allow horizontal scrolling)

Once the player gets inside the castle and walks up to the upper part, the game starts setting the IRQ counter successively to 41, 42, 52 and 53, interspersed with toggles to the IRQ enable flag. I don't know why it is doing this, but it seems to result in too much of the HUD being shown, and not enough of the background. It's as if the horizontal split required between HUD and background is happening much further down the screen and the resulting garbage is simply unused tiles in the nametable used for the HUD.

An excerpt from my debug log:
Code:
MMC5 IRQ ($5204) = Enabled
MMC5 IRQ Counter($5203) = 41
MMC5 IRQ Counter($5203) = 42
MMC5 IRQ Counter($5203) = 52
MMC5 Mirror Mode ($5105) = Single1 ($55) (%01010101)
MMC5 IRQ Counter($5203) = 53
MMC5 IRQ ($5204) = Disabled
MMC5 Mirror Mode ($5105) = 216 ($D8) (%11011000)
MMC5 IRQ ($5204) = Enabled
MMC5 IRQ Counter($5203) = 41
MMC5 IRQ Counter($5203) = 42
MMC5 IRQ Counter($5203) = 52
MMC5 Mirror Mode ($5105) = Single1 ($55) (%01010101)
MMC5 IRQ Counter($5203) = 53
MMC5 IRQ ($5204) = Disabled
MMC5 Mirror Mode ($5105) = 216 ($D8) (%11011000)
MMC5 IRQ ($5204) = Enabled
MMC5 IRQ Counter($5203) = 41
MMC5 IRQ Counter($5203) = 42
MMC5 IRQ Counter($5203) = 52
MMC5 Mirror Mode ($5105) = Single1 ($55) (%01010101)
MMC5 IRQ Counter($5203) = 53
MMC5 IRQ ($5204) = Disabled
MMC5 Mirror Mode ($5105) = 216 ($D8) (%11011000)
MMC5 IRQ ($5204) = Enabled
MMC5 IRQ Counter($5203) = 41
MMC5 IRQ Counter($5203) = 42
MMC5 IRQ Counter($5203) = 52
MMC5 Mirror Mode ($5105) = Single1 ($55) (%01010101)
MMC5 IRQ Counter($5203) = 53
MMC5 IRQ ($5204) = Disabled
MMC5 Mirror Mode ($5105) = 216 ($D8) (%11011000)
MMC5 IRQ ($5204) = Enabled
MMC5 IRQ Counter($5203) = 41
MMC5 IRQ Counter($5203) = 42
MMC5 IRQ Counter($5203) = 52
MMC5 Mirror Mode ($5105) = Single1 ($55) (%01010101)
MMC5 IRQ Counter($5203) = 53
MMC5 IRQ ($5204) = Disabled
MMC5 Mirror Mode ($5105) = 216 ($D8) (%11011000)
MMC5 IRQ ($5204) = Enabled
MMC5 IRQ Counter($5203) = 41
MMC5 IRQ Counter($5203) = 42
MMC5 IRQ Counter($5203) = 52
MMC5 Mirror Mode ($5105) = Single1 ($55) (%01010101)
MMC5 IRQ Counter($5203) = 53
MMC5 IRQ ($5204) = Disabled
MMC5 Mirror Mode ($5105) = 216 ($D8) (%11011000)
MMC5 IRQ ($5204) = Enabled
MMC5 IRQ Counter($5203) = 41
MMC5 IRQ Counter($5203) = 42
MMC5 IRQ Counter($5203) = 52
MMC5 Mirror Mode ($5105) = Single1 ($55) (%01010101)
MMC5 IRQ Counter($5203) = 53
MMC5 IRQ ($5204) = Disabled
MMC5 Mirror Mode ($5105) = 216 ($D8) (%11011000)
MMC5 IRQ ($5204) = Enabled
MMC5 IRQ Counter($5203) = 41
MMC5 IRQ Counter($5203) = 42

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/


Last edited by colinvella on Tue Jun 28, 2016 4:36 pm, edited 2 times in total.

Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 9:02 am 
Offline
User avatar

Joined: Sat Jan 22, 2005 8:51 am
Posts: 427
Location: Chicago, IL
Are you properly handling this scenario?

- CPU I flag set
...
- MMC5 asserts IRQ (CPU should ignore)
...
- CPU I flag cleared (e.g., CLI or PLP) <-- IRQ should be handled here (after the next instruction)

_________________
get nemulator
http://nemulator.com


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 1:11 pm 
Offline
User avatar

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
James wrote:
Are you properly handling this scenario?

- CPU I flag set
...
- MMC5 asserts IRQ (CPU should ignore)
...
- CPU I flag cleared (e.g., CLI or PLP) <-- IRQ should be handled here (after the next instruction)


I actually had my CPU coding wrong there. My I flag was effectively suppressing pending IRQs and hence doing CLI would not have triggered the IRQ afterwards. I'm changing this but I think I have a problem elsewhere. Still.. thanks for the tip.. one step closer to emulating the real thing! :)

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Bing [Bot] and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group