CNROM software (bus conflicts)

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

CNROM software (bus conflicts)

Post by Bregalad »

I'm unable to found a doccumentation explaining how works bus conflicts on a CNROM (and UNROM) cartidge.
The data written to the mapper (into $8000-$ffff) shall be the same than the value stored at the same adress in the ROM, right ?
So for a fixed swapping value would be :

Code: Select all

lda #$01
sta *-1 ;I'm swapping bank 1 and the target stored data is #$01 (the above instruction)
And the only way to do variable swapping is :

Code: Select all

jsr GetSwapByte ;A=bank to swap
tax
sta SwapTable,X
rts
SwapTable:
db $0, $1, $2, $3 ;Data to swap is the same than the target's value stored here
Is that all right ?
I also founded this information in MegaMan's rom tech doccument :
There is one more thing to note about this mapper: although any address
in the $8000-$FFFF range can be used to access the mapper, most games
prefer to use the address with the last digit equal to the value they
write out. Thus, $07 can be written to $9FF7, $05 to $9FF5, and so forth.
The reason for this is unknown.
This would mean, for me, that the value written shall be the same than the least significant nybble, and may not be the same as the stored value in ROM.
Thanks in advance.
Useless, lumbering half-wits don't scare us.
_jsr

Post by _jsr »

When you want to change a bank you'll have to write to the same space as the rom, which will cause the ROM to also output a value.
Bus conflicts appears if the CPU and ROM outputs are different, like if the CPU writes 1 and the ROM 0. That will cause an unknown result.

The simple way to fix that is to have the same numbers stored on the ROM where you write, just like you explain.
J2

Post by J2 »

http://nesdev.com/wiki/?page=bus+conflicts

That should explain to you what a bus conflict is. Many discrete logic mappers suffer from them (the ANROM at least protects against this using a 7402).

Basically, the PRG-ROM chip is connected to CPU /CE (A15 (to enable the chip only the $8000-$FFFF) AND M2 (so that it's only enabled at the right times). Well, when a STx $8000-$FFFF activate A15 and thus it enables the chip. So the chip outputs it's data based upon the address lines and such although the CPU is actually writing, the 2 outputs then collide and one them will overpower the other producing "corrupt" data. But if the data on both ends is exactly the same then theres no problem (and that's why you *must* have them be the same).
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

Thanks, it's okay now.
The only way to have a constant mid-frame PPU write with a single mapper like CNROM or UNROM is to have a sprite-0 trigger, right ?
Does it works if the BG is turned off via $2001 ?
I'll explain what I want to do :
I'll have a multidirectionnal scrooling routine, but it will be able to run on a single system and be portable and very simple, so witout calculating half attributes, etc...
So the good way is to use vertical mirroring so horizontal scrooling is no problem (no gliches). The vertical one will work also witout gliches, but a part of the screen (at the top or at the bottom) is going to have the BG redering off to hide gliches (this part should be at least 4 rows heignt, to hide one whole attribute). This part would be used to have a sprite-only status bar.
So 1-The scrooling is portable and simple; 2-There is no gliches; 3-There is a status bar. The only crap thing is the 8-sprites per line limitation for the status bar.
If the status bar is at the bottom of the screen, the PPU will spend 80% of the frame for waiting and 20% only will remain to do calculations, etc...
So have the status bar at the top like most old nes games (Mario Bross, CastleVania, etc...) will be usefull for waiting only 20% of the frame.
But, this means that the BG is off, and is turned on after the sprite-0 hit. So is that possible ?
If it's not, I've the idea to put 9 sprites at the last status bar's row, and using $2002.5 trigger as explained in the parallel topic. Would it works with most emulators ?
Useless, lumbering half-wits don't scare us.
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

Bregalad wrote:mapper like CNROM or UNROM is to have a sprite-0 trigger, right ?
Does it works if the BG is turned off via $2001 ?
I can't say with absolute certainty, but I'd be willing to bet a thousand bucks that it won't. The Sprite 0 hit flag is raised when a nontransparent BG pixel collides with a nontransparent Sprite 0 pixel. If BG rendering is off... there won't be any non-transparent BG pixels being rendered, so the flag won't be raised.
J2

Post by J2 »

The only way to have a constant mid-frame PPU write with a single mapper like CNROM or UNROM is to have a sprite-0 trigger, right ?
Not the only way, but prolly the best/easiest. You can also used timed code or something of the like though.
Does it works if the BG is turned off via $2001 ?
You mean does the sprite 0 hit occur with BG rendering off? Of course not. The nontransparent sprite 0 pixel has nothing to "hit."
I'll have a multidirectionnal scrooling routine, but it will be able to run on a single system and be portable and very simple, so witout calculating half attributes, etc...
So the good way is to use vertical mirroring so horizontal scrooling is no problem (no gliches). The vertical one will work also witout gliches, but a part of the screen (at the top or at the bottom) is going to have the BG redering off to hide gliches (this part should be at least 4 rows heignt, to hide one whole attribute). This part would be used to have a sprite-only status bar.
So 1-The scrooling is portable and simple; 2-There is no gliches; 3-There is a status bar. The only crap thing is the 8-sprites per line limitation for the status bar.
So then you want a scrolling routine that can be easily used with any mapper (portable)? A sprite-only status bar guess you could do if you wanted, but why?
If the status bar is at the bottom of the screen, the PPU will spend 80% of the frame for waiting and 20% only will remain to do calculations, etc...
So have the status bar at the top like most old nes games (Mario Bross, CastleVania, etc...) will be usefull for waiting only 20% of the frame.
Yep, without an Scanline IRQ you have to constantly wait, that is unless you have some interesting timed code.
But, this means that the BG is off, and is turned on after the sprite-0 hit. So is that possible ?
If it's not, I've the idea to put 9 sprites at the last status bar's row, and using $2002.5 trigger as explained in the parallel topic. Would it works with most emulators ?
Sprite 0 hit will not occur. Why does rendering need to be turned off during the top portion of the screen and have a sprite-based status bar instead? Since Sprite rendering is turned on I assume the sprite overflow bit will still work so I guess you could use that. I doubt any emulators authors would've ignored to add something as simple as that so it should be well emulaed.
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

J2 wrote:Sprite 0 hit will not occur. Why does rendering need to be turned off during the top portion of the screen and have a sprite-based status bar instead?
To prevent enormus gliches on vertical scrooling. The routine will draw block at one (like CastleVania, Megaman 1&2, etc...) and not meta-tile at once (this is a much complicated scroolin, but it's the only way to have a non-gliched multi-directionnal scrooling exept with my method).
Since Sprite rendering is turned on I assume the sprite overflow bit will still work so I guess you could use that. I doubt any emulators authors would've ignored to add something as simple as that so it should be well emulaed.
Okay, thanks.[/quote]
Useless, lumbering half-wits don't scare us.
Hyde
Posts: 101
Joined: Mon Sep 27, 2004 11:51 pm

Post by Hyde »

J2 wrote:Since Sprite rendering is turned on I assume the sprite overflow bit will still work so I guess you could use that. I doubt any emulators authors would've ignored to add something as simple as that so it should be well emulaed.
Don't count on that. Most of us, emulator authors, don't know exactly when to set the sprite overflow flag. So, take that into account.
J2

Post by J2 »

Hyde wrote:Don't count on that. Most of us, emulator authors, don't know exactly when to set the sprite overflow flag. So, take that into account.
That's true, good point. Although, I'm sure just because they don't know exactly when it occurs, it was ignored in their emulator (think about not allowing horizontal scrolling because of not knowing when to load the h-scroll counter, course that's exaggerated as horizontal scrolling is vital). I have tested quite a few emulators and ALL of them (aside from Nesticle LOL) set this bit when their are 9 sprites on scanline (although their actual implementation is incorrect in a lot of emulators, they all set the bit when their are 9 or more sprites on a scanline) so Bregelad's scrolling will work fine using that.

Some emulators handle this oddly though. VirtuaNES and NNesterJ miss the first scanline it should be triggered on + trigger it on >= 8 instead of >= 9 and they also reset it when their is not >=8 sprites on a scanline. Nestopia goes crazy and sets at weird times midscanline (seemingly random times not based upon anything) + resets the bit when there isn't >= 9 sprites on a scanline instead of resetting it later (I've forgotten when *exactly* to reset it, but it occurs after the end of the current frame that it was set on). So even though some implement it innaccurately, they still implement and it will work as desired on them all for Bregelads "demo?" FCE Ultra and Nintendulator emulate it just fine (as far as I know).

When do you set it? It seems to me like it should be set in the HBLANK prior to the scanline as thats where all the sprites are evaluated and such for the next scanline. Hyde, do you have an emulator somewhere (curious)?
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

AFAIK:

Sprites are checked to see if they're "in range" every 4 cycles in the scanline (I would assume sprite 0 is checked on cycle 0... sprite 1 is checked on cycle 4, spr2 on 8, etc... but it might be in between). When the 9th is found... the flag is set and remains set until the end of the next VBlank (when this bit and the spr0 hit flag are cleared).

So the exact time and scanline depends on which sprite is the 9th to be found. So if the 9th sprite is the 9th to be found (which would be the case if sprites 0-9 are all on this scanline), then the flag would be raised around (9*4) cycle 36 of the scanline. But if sprite 52 is the 9th, it'd be cycle (52*4) 208 of the scanline.

Also keep in mind that this is done on the scanline before it's actually rendered. So if all these sprites are to be drawn on scanline 6... the flag would actually be set X cycles into scanline 5.

That's how BT's doc suggests it, anyway.

I do it this way in my emu. But as already mentioned... most emus probably don't bother even trying to get the exact cycle right. YOUR only concern, however, should be whether or not this works on the real thing... which it would if done right. If you plan on going down this route... don't rely on ANY emu for testing since they're probably all unreliable -- get your rom tested on the real thing and leave it up to the emu authors to make their thing work right (and a ROM which tests this sort of thing and relies on its exact behavior would be a fantastic tool for emu developers).
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

J2 wrote:Although, I'm sure just because they don't know exactly when [$2002.d5] occurs, it was ignored in their emulator (think about not allowing horizontal scrolling because of not knowing when to load the h-scroll counter, course that's exaggerated as horizontal scrolling is vital).
Difference is that the timing for hscroll doesn't need to be as precise; most games will work even if the value is read a couple scanlines early or late. Mid-scanline effects that affect vertical scrolling may be tougher to get right.
I have tested quite a few emulators and ALL of them (aside from Nesticle LOL) set this bit when their are 9 sprites on scanline (although their actual implementation is incorrect in a lot of emulators, they all set the bit when their are 9 or more sprites on a scanline) so Bregelad's scrolling will work fine using that.
But if the timing is off, they'll glitch on one scanline, possibly moving the bottom half of the screen up or down one scanline. And what about games that actually have sprites, where nine line up on one scanline, and the game needs to multiplex (flicker) them to display them all?
Some emulators handle this oddly though.
That's the point.
So even though some implement it innaccurately, they still implement and it will work as desired on them all for Bregelads "demo?"
But if there are sprites overlapping the bottom half, something off by one scanline will throw off vertical alignment between sprites and the background.
Disch wrote:If you plan on going down this route... don't rely on ANY emu for testing since they're probably all unreliable -- get your rom tested on the real thing
Problem is that with the current commercial unavailability of rewritable NES carts, testing on real hardware would need at least one day per build to get a build to someone who has built such a cart and then get the results back.
(and a ROM which tests this sort of thing and relies on its exact behavior would be a fantastic tool for emu developers)
Yes, I agree that we need more of these.
Hyde
Posts: 101
Joined: Mon Sep 27, 2004 11:51 pm

Post by Hyde »

Disch wrote:and a ROM which tests this sort of thing and relies on its exact behavior would be a fantastic tool for emu developers
Would someone care to test this on an NES and post a screenshot?

http://rocknes.kinox.org/eight.zip

Hosting courtesy of Fx3 and code by Chris Covell I believe.
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

OK Tanks a lot.
The problem would be the inacuracy of this on Nester and VirtuaNES (the sprite-only status bar would take for sure 8 sprites somewhere, so it will be turned off too early : the BG will be shown between the status bar and this would be not readable).
Is there any other way to turn on BG mid-frame without any IRQ trigger ? (100% timed code would probabily not be possible in VBLank).
Useless, lumbering half-wits don't scare us.
Post Reply