But you can't override PPU A9 throughBananmos wrote:- nametable#1 contains full nametable tiles, and uses bytes 768-1023 of nametable#2 for its attribute table. Its original 64 byte attribute table is unused.
Mapper30 8x8 attributes on Everdrive
Moderator: Moderators
Re: Mapper30 8x8 attributes on Everdrive
Last edited by lidnariq on Thu Apr 19, 2018 7:41 pm, edited 1 time in total.
- rainwarrior
- Posts: 8734
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Mapper30 8x8 attributes on Everdrive
Ah, so the insight is that if using single screen for a status bar you don't need the whole screen. That's pretty sensible.Bananmos wrote:I was thinking more of the following layout in CIRAM, roughly:
- nametable#1 contains full nametable tiles, and uses bytes 768-1023 of nametable#2 for its attribute table. It's original 64 byte attribute table is unused.
- nametable#2 only has space for 512 bytes (16 rows) of nametable tiles, and uses bytes 512-767 for its attribute table. (although only bytes 512-639 would actually correspond to valid nametable tiles)
Lidnariq just suggested that doesn't work with CIRAM but I don't think it's a real problem if it was in CHR-RAM. Like having a hardwired option for 4-screen and this 1.5-screen is probably good enough for most practical purposes, saving 2k worth of 32k CHR-RAM I don't think is hugely important. I guess even if only the nametable part was in CIRAM that'd be a decent bonus, making that last 8k page more usable. (If only we could get back the last 2 rows for nametable, and have much more sensible vertical coordinate systems. )
Even if it was just "standard" 1-screen mode, and the attributes were spread across CHR like before, I think that'd be pretty OK to. The importantly functional part is just having a single screen type mirroing available, IMO. Packing them efficiently is just icing. (Once I realized it was just <= 16 tiles from an 8k page and independent from banking I didn't think it was a huge imposition at all.)
Re: Mapper30 8x8 attributes on Everdrive
Whoops, you're right of course... just wasn't thinking straight.But you can't override PPU A9 through A7when fetching from CIRAM...
So yeah, the only thing you could do with CIRAM alone would be having a shared 8x16 or 16x8 attribute table as you said, using CIRAM A10. Which isn't greatly useful.
I guess a compact attribute table for single-screen mirroring that doesn't clash with CHR might still make some sense I guess, if say you had a tiny on-cart RAM that would provide the storage for attributes only. Or if you had a very size-constrained FPGA to implement 256-512 bytes of memory in.
But given it kills the aim of doing this with just minimal logic, I think the original CHR-RAM steal idea is more practical, even for 1screen. Or a variant on infiniteneslives mapper30, where one of the 8kB pages is not used for CHR.
Re: Mapper30 8x8 attributes on Everdrive
Hypotethical question: Could one make a ROM that automatically loads attribute table "version 8x8" if the hardware/emulator allows it, or attributle table "version 16x16" if it doesn't?
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
Re: Mapper30 8x8 attributes on Everdrive
Yes, but there's no point: this behavior would need its own mapper number anyway.
Game design for something that supported 8x8 attributes and something that didn't would be radically different, trying to cram both in at the same time would cripple the 8x8 version.
Game design for something that supported 8x8 attributes and something that didn't would be radically different, trying to cram both in at the same time would cripple the 8x8 version.
Re: Mapper30 8x8 attributes on Everdrive
Hmm, so thinking about this again, I think there's one (naughty) way in which remapping attribute fetches in CIRAM for single-screen mirroring *could* work... but keep in mind all this is after a few drinks at the pub
The original NES CIRAM is implemented with NMOS, which means a 0 wins over a 1, and you get a logical AND as the final result.
And when the PPU fetches from the original attribute table, PPU address bits 9:6 happen to all be high.
So a sequence for single-screen mirroring with attribute table could be:
* When a nametable fetch occurs on rising edge of PPU /OE, fineX and fineY are latched, as before. In addition
* ...but we also set an "attribute_override bit" here, which captures the state that we've just done a nametable fetch
* On the *next* rising edge of PPU /OE, we do not inspect the PPU address bits at all - as the "attribute_override" bit already tells us we are doing an attribute fetch.
* Instead, we drive A7/A6 low if fineY/fineX were low - or high-impedance if not.
* If we want an attribute table for the second half-nametable, we can also say that if nametable_select==1, we drive PPU A8 low as well
* Somewhere in this process (falling edge of PPU /OE and no nametable fetch?) we'll also clear the attribute_override_bit, which will remain unset until we detect yet another nametable fetch
The disclaimer is that I'm not sure how potentially damaging to circuitry it would be to intentionally cause temporary bank conflicts on NMOS circuits - although I imagine it shouldn't be significantly worse than using 6502 unofficial opcodes in your game?
And truth to be told, I doubt I'd actually try this out for real, as the extra complexity starts to diverge quite a bit from the intent of keeping this super-simple. So it's more of a pure thought experiment by now... and I think the simple CHR-steal is the more reasonable solution to get 8x8 attributes with minimal cost.
The original NES CIRAM is implemented with NMOS, which means a 0 wins over a 1, and you get a logical AND as the final result.
And when the PPU fetches from the original attribute table, PPU address bits 9:6 happen to all be high.
So a sequence for single-screen mirroring with attribute table could be:
* When a nametable fetch occurs on rising edge of PPU /OE, fineX and fineY are latched, as before. In addition
* ...but we also set an "attribute_override bit" here, which captures the state that we've just done a nametable fetch
* On the *next* rising edge of PPU /OE, we do not inspect the PPU address bits at all - as the "attribute_override" bit already tells us we are doing an attribute fetch.
* Instead, we drive A7/A6 low if fineY/fineX were low - or high-impedance if not.
* If we want an attribute table for the second half-nametable, we can also say that if nametable_select==1, we drive PPU A8 low as well
* Somewhere in this process (falling edge of PPU /OE and no nametable fetch?) we'll also clear the attribute_override_bit, which will remain unset until we detect yet another nametable fetch
The disclaimer is that I'm not sure how potentially damaging to circuitry it would be to intentionally cause temporary bank conflicts on NMOS circuits - although I imagine it shouldn't be significantly worse than using 6502 unofficial opcodes in your game?
And truth to be told, I doubt I'd actually try this out for real, as the extra complexity starts to diverge quite a bit from the intent of keeping this super-simple. So it's more of a pure thought experiment by now... and I think the simple CHR-steal is the more reasonable solution to get 8x8 attributes with minimal cost.
Re: Mapper30 8x8 attributes on Everdrive
Unfortunately, no, the CIRAM is a CMOS device but...Bananmos wrote:The original NES CIRAM is implemented with NMOS, which means a 0 wins over a 1, and you get a logical AND as the final result.
You're talking about inducing bus conflicts on the address bus, and that's "only" getting in a fight with the PPU ...
but only on A8-A13. A0-A7 are a fight with the 74'373. ... I guess you could predict when the ALE cycle is so that you can get in a fight with the PPU's data bus instead and change the value that the 74'373 latches.
The unofficial opcodes are definitely known safe (if nonsensical), because there's almost no explicit pullups; instead just the depletion-mode pullups that act like funny resistors. Any number of MOSFETs can pull a node low, even if it's two that don't make sense at the same moment.The disclaimer is that I'm not sure how potentially damaging to circuitry it would be to intentionally cause temporary bank conflicts on NMOS circuits - although I imagine it shouldn't be significantly worse than using 6502 unofficial opcodes in your game?
- rainwarrior
- Posts: 8734
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Mapper30 8x8 attributes on Everdrive
Here's another funny thought. As an alternative version of the mapper that makes a full screen framebuffer possible:
8k PPU-RAM banking:
If the sprite CHR data loss is a big deal, or just the added complexity, maybe the 8x8 attribute feature isn't even necessary for the idea, it's just a nice addition and shares the banking-for-read-patterns principle.
A nice thing about automation via attribute address is that it becomes fully scrollable too, since it's tied to the nametable itself rather than screen raster timing (sorta like what MMC2 can do). Though there's only enough framebuffer RAM for 1 screen, and having 2-screens would mean having to post the attributes twice... maybe 1-screen mirroring is best?
Actually maybe you don't even need CIRAM, you could just feed back the nametable fetch address into itself to select the CHR tile!? (I guess you could jam 16x8 attributes into CIRAM, if you really wanted?)
...of course a full screen framebuffer is a huge vblank bandwidth problem. With 2x the RAM you could maybe double buffer it, but otherwise you'd have to live with tearing or only small updates per frame.
This is probably too silly to really be useful, but I've often thought about what an NES with a framebuffer would be like.
8k PPU-RAM banking:
- Attribute banking: applies to any read from $20C0-20FF x 4
- Nametable CHR banking: applies to any CHR read from $1000-1FFF
- Sprite CHR banking: applies to any CHR read from $0000-0FFF
- A nametable fetch will set the attribute bank as before.
- An attribute fetch sets the nametable CHR bank.
- Sprite CHR bank is CPU controlled.
- 8x8 attribute data shares 16 tiles per bank with sprite CHR.
- Non-attribute nametable reads should go to CIRAM. (No 4-screen option here.)
If the sprite CHR data loss is a big deal, or just the added complexity, maybe the 8x8 attribute feature isn't even necessary for the idea, it's just a nice addition and shares the banking-for-read-patterns principle.
A nice thing about automation via attribute address is that it becomes fully scrollable too, since it's tied to the nametable itself rather than screen raster timing (sorta like what MMC2 can do). Though there's only enough framebuffer RAM for 1 screen, and having 2-screens would mean having to post the attributes twice... maybe 1-screen mirroring is best?
Actually maybe you don't even need CIRAM, you could just feed back the nametable fetch address into itself to select the CHR tile!? (I guess you could jam 16x8 attributes into CIRAM, if you really wanted?)
...of course a full screen framebuffer is a huge vblank bandwidth problem. With 2x the RAM you could maybe double buffer it, but otherwise you'd have to live with tearing or only small updates per frame.
This is probably too silly to really be useful, but I've often thought about what an NES with a framebuffer would be like.
Re: Mapper30 8x8 attributes on Everdrive
Ok, latch A5 and A0 on first fetch after A13 rises (alternatively, as long as A13 is high and any of A6-A9 are 0)rainwarrior wrote:A nametable fetch will set the attribute bank as before.
According to what? The value fetched from the extended attribute tables, mimicking MMC5 extgraphics (i.e. data bus)? The coordinate (i.e. address bus)?An attribute fetch sets the nametable CHR bank.
Also, double-checking: I assume you mean "background" here?
Are you thinking of a fixed layout, or think that's a separate question?Non-attribute nametable reads should go to CIRAM. (No 4-screen option here.)
Are you thinking more like mapper 96, or more like completely bypassing the nametable fetch altogether?feed back the nametable fetch address into itself to select the CHR tile!?
Ah, the latter.an NES with a framebuffer would be like.
- rainwarrior
- Posts: 8734
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Mapper30 8x8 attributes on Everdrive
The address, i.e. trying to identify the quadrant of the nametable that the next CHR tile read belongs to.lidnariq wrote:According to what? The value fetched from the extended attribute tables, mimicking MMC5 extgraphics (i.e. data bus)? The coordinate (i.e. address bus)?An attribute fetch sets the nametable CHR bank.
This is semantically difficult, so I'm not sure what the best word is to use, but the "nametable CHR bank" is banking applied for a tile data fetch from $1000-1FFF.lidnariq wrote:Also, double-checking: I assume you mean "background" here?
Well it's just that we can't use the 32k PPU-RAM on the cartridge for nametable data, because it's needed for the banked CHR tiles / framebuffer.lidnariq wrote:Are you thinking of a fixed layout, or think that's a separate question?Non-attribute nametable reads should go to CIRAM. (No 4-screen option here.)
Hmm, I guess that allows one other idea for double buffering: forget about sprites, forget about 8x8 attributes, and just bank whole 8k pages for CHR tile fetches. (i.e. use the bit in $2000 to select which "buffer" to use, interleaved in 4k portions).
Re: Mapper30 8x8 attributes on Everdrive
Ok, so ... effectively:rainwarrior wrote:The address, i.e. trying to identify the quadrant of the nametable that the next CHR tile read belongs to.
Latch A9, A8, A5, A0 on nametable fetches.
(A9 and A8 are repeated as A5 and A4 in attribute fetches)
Use latchedA5 and latchedA0 to control bank during ((address & 0x23C0) == 0x23C0)
Use latchedA9 and latchedA8 to control bank during fetches from 0x1000...0x1FFF
Use two bits of some latch from CPU to control bank during fetches from 0x0000...0x0FFF
Am I understanding correctly?
- rainwarrior
- Posts: 8734
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Mapper30 8x8 attributes on Everdrive
Oh yeah I guess you can latch during the nametable fetch can't you. Duh. Ha ha. I don't know why that didn't occur to me... but I think I was just thinking a little too sequentially.
Anyhow, yeah that's the idea: bank the CHR tiles used for nametables based on what 1/4 of the nametable we're trying to render to create an effective full screen framebuffer.
Anyhow, yeah that's the idea: bank the CHR tiles used for nametables based on what 1/4 of the nametable we're trying to render to create an effective full screen framebuffer.
Re: Mapper30 8x8 attributes on Everdrive
.... wait a moment, we don't actually need to decode the attribute zones strictly. We could rely on the fetch cadence instead, and instead just replace the 2nd (and later) reads from regions where A13 is high.lidnariq wrote:PPU A5-A9
That frees up four pins, enough to move the bankswitching register out from overlapping with flash:
PPU A0, A5, A13, /RD
CPU /ROMSEL, A12, M2, R/W, D0, D1, D4, D5
CHR A13, A14; PRG A15, A16.
total: 17 - one unused
We could make the register accessed serially to get more address space (xx, D1, D4, D5 -> PRG A17, A18, spare1, spare2), but I can't imagine we'd actually want that.
(edit) ... huh, what about a semi-serial register? One that's connected to D0,D2,D4,D6 and that you STA $5000 / LSR / STA $5000 ? Just two writes instead of five, so it's still quite fast, but it only uses half the inputs.