PowerPak mapper 30 implementation

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderators: B00daW, Moderators

User avatar
rainwarrior
Posts: 8716
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: PowerPak mapper 30 implementation

Post by rainwarrior »

Hm, I guess that's a very innocuous bug until you wanted to put stuff at $100. ;)

Anyhow, go ahead and post the revision here, please revise or reuse that code any way you like.
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

Here's the updated version:
30_test_src.zip
(32.38 KiB) Downloaded 676 times
Anyway, this test should hopefully make debugging the Powerpak write sequence detector way easier. Though it might still need hooking up the cheap&buggy misbehaving logic probe from amazon to my debug board

(still have plenty of these around if anyone needs one for hardware experiments)
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

...and of course, the rule of thumb in computer science is that as soon as you've written that fancy debugging app, you only need to take a quick second look on your source code to spot that blatant bug. :oops:
IMG_20190322_003422.jpg
So yeah, verilog code looks good now. But hey, still happy to have embraced test-driven development, with some useful output for posterity...

Still code clean-up to do, but should have a Powerpak flash saving bundle in a day or two.
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

Despite having fixed a bug, I also added some new ones. Namely forgetting some ppu_wait calls, and thus causing a real cart with true sector erase delay to push writes outside of vblank.

Here is the latest bugfixed source:
30_test_src.zip
(32.61 KiB) Downloaded 647 times
I also couldn't help trying the theory of whether the Powerpak could do bus conflicts by just omitting the disabling of PRG output for CPU writes, and it turns out this does give the "proper" AND-behavior:
and_bus_conflicts_on_powerpak.jpg
...but even so, I don't feel comfortable adding this "emulation" into the Powerpak mapper. As lidnariq pointed out, the longevity of the cart (and perhaps your NES) might possibly be compromised. And how much I'm not really knowledgeable enough to say how severely. So I'd rather play it safe and not get future anger directed towards me. :|

But if anyone does want this extra level of compatibility at their own risk, the Verilog source code will be available, and it is just a one-line change...
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

Oh, and another thing where I might want some opinions...

As the "manufacturer id" doesn't necessarily need to be equal to $BF, I was thinking of putting something different in there for the Powerpak implementation. Say $BB (=BunnyBoy) on the Powerpak, and $ED for the Everdrive. This could allow software to know which of the 3 implementations it is running on, in case it needs to make compromises on one target platform (like for example the mentioned optimisation to avoid writing all bytes after clearing sectors)

But I'm not sure if this is a great idea, in case any software will depend on it to be exactly $BF to support saves. OTOH, the only game I know to support flash saving is Black Box Challenge... and BBC doesn't appear to care about the software id at all. So this might be the right time to set such expectations...

Thoughts on this?
lidnariq
Posts: 11222
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: PowerPak mapper 30 implementation

Post by lidnariq »

Bananmos wrote:As the "manufacturer id" doesn't necessarily need to be equal to $BF, I was thinking of putting something different in there for the Powerpak implementation. Say $BB (=BunnyBoy) on the Powerpak, and $ED for the Everdrive. This could allow software to know which of the 3 implementations it is running on, in case it needs to make compromises on one target platform (like for example the mentioned optimisation to avoid writing all bytes after clearing sectors)
Greenliant's GLS27SF flash is compatible with Microchip's SST39SF flash. For those parts, they still use a "manufacturer" of $BF, but the second byte changes:
Upper nybble=$A = Greenliant. Upper nybble=$B = Microchip.
Lower nybble specifies size as 2^(n+12) bytes, or 2^n 4KiB sectors.

Macronix seems to be other remaining vendor of all-new 5V parallel NOR flash; their parts use a much larger sector size.
Thoughts on this?
Software could use this for crappy DRM purposes. I don't know if that's important or not.
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

lidnariq wrote:
Bananmos wrote:As the "manufacturer id" doesn't necessarily need to be equal to $BF, I was thinking of putting something different in there for the Powerpak implementation. Say $BB (=BunnyBoy) on the Powerpak, and $ED for the Everdrive. This could allow software to know which of the 3 implementations it is running on, in case it needs to make compromises on one target platform (like for example the mentioned optimisation to avoid writing all bytes after clearing sectors)
Greenliant's GLS27SF flash is compatible with Microchip's SST39SF flash. For those parts, they still use a "manufacturer" of $BF, but the second byte changes:
Upper nybble=$A = Greenliant. Upper nybble=$B = Microchip.
Lower nybble specifies size as 2^(n+12) bytes, or 2^n 4KiB sectors.

Macronix seems to be other remaining vendor of all-new 5V parallel NOR flash; their parts use a much larger sector size.
Thoughts on this?
Software could use this for crappy DRM purposes. I don't know if that's important or not.
Thanks for mentioning that. Although looking at the data sheet:
http://www.icbase.com/File/PDF/GRT/GRT00071106.pdf

...I'm not sure how relevant this type of chip is, as it doesn't have the sector erase command, and the chip erase, byte-write and software id are all accessed by forcing a 12V voltage on one of the pins. So I would never expect to see this part in a self-flashable configuration, as I can't see how software running on the NES would access this anyway? You would need a new register that sets 12V, and even then the lack of a sector erase would make the feature only useful for deleting all the software on the cartridge.

Though I suppose we could more strictly formalise the size as being given by the bottom 3 bits of B7. Even reserving the fourth top-bit as well as you suggest. Although in practice, > 512kB isn't really possible anyway on UNROM512, unless some bits like CHR bank or one-screen toggle are reclaimed.

DRM wasn't what I had in mind - I was more thinking some software might want to know about the limitations of the Powerpak/Everdrive implementation.

But yeah, it could be used for DRM too I suppose. But you can already take advantage of the lack of sector erase and flash-write AND behavior anyway. If anyone wants to add some very minimal copy protection, then by all means let them have a go at it. I would personally just see it as just yet-another neat trick. And if people want to crack it, they might just gain some NES knowledge along the way and bring fresh blood to our aging community... :)
lidnariq
Posts: 11222
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: PowerPak mapper 30 implementation

Post by lidnariq »

Bananmos wrote:I'm not sure how relevant [GLS27SF] is, as it doesn't have the sector erase command, and the chip erase, byte-write and software id are all accessed by forcing a 12V voltage on one of the pins. So I would never expect to see this part in a self-flashable configuration, as I can't see how software running on the NES would access this anyway?
... you know, I read the data sheet repeatedly and kept on managing to overlook that? At least the "27" part of the part number is less bewildering to me now.

I think I meant the GLS29EE010, which still doesn't have a "page erase" command because each byte is reprogrammable as-is.
If anyone wants to add some very minimal copy protection, then by all means let them have a go at it. I would personally just see it as just yet-another neat trick. And if people want to crack it, they might just gain some NES knowledge along the way and bring fresh blood to our aging community... :)
Heh, fair enough.
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

Wow, that sure was a grind. Not only was finding room for code in the Powerpak plugins a challenge, but also (again) was hit by that nasty Xilinx ISE when debugging: Pasting lines sometimes puts them at the top of the source file, the file gets invalid and disabled in the project. But the whole thing helpfully compiles with an older cached version... making you perplexed as to why your changes have no effect anymore... :evil:

Anyway, writing to CF appears to be working now, without breaking existing games. Only auto-save is supported for Mapper30, due to the boot ROM PRG corruption when browsing directories.

Powerpak Mapper30 v3 with flash save

And Everdrive version is also available, but won't save anything back to the SD card (it would need an OS update from Krikzz):
Everdrive Mapper30 v3 with flash save
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

Looks like PowerpakMapper30_v3 came with a pretty bad bug, courtesy of nesasm, which due to its daft addressing syntax had turned the final "jmp ($FFFC)" into a plain "jmp $FFFC".

Strangely, Troll Burner, Black Box Challenge and the test ROM all seemed to boot fine with this bug in-place. But the Byte-off compos did not fare so well...

New version here: PowerpakMapper30_v4.zip

And yes, I hate nesasm as much as the next guy. The only reason for using here is that the Powerpak source code used it, and I didn't want to diverge from the main source code too much.
User avatar
rainwarrior
Posts: 8716
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: PowerPak mapper 30 implementation

Post by rainwarrior »

Testing that on my PowerPak, saving and loading appears to work correctly for Black Box Challenge and Larry and the Long Look..., which are the two UNROM512 games I have that require a save.

Just to check I tried a few other games with saves to make sure they weren't broken, but they also seemed to work fine.

Non-saving games like Twin Dragons also appear to work fine. Tower of Turmoil also seemed fine despite incorrectly having the battery flag set, which might suggest NESMaker is already reserving the relevant page for saves anyway.

So... :beer: :D

We could use some documentation on exactly what this compatibility subset of flash save actually supports, and how to set up the .SAV before starting. I didn't see anything that really describes it in the readme. Is the first 8k of PRG automatically replaced by the save file on load? Is it always 8k or does the size of the provided .SAV file affect it?

I was a bit uncertain about what I should put in the .SAV file before running the ROM the first time. I just used 8k files filled with $FF. Presumably one should put a copy of the original PRG in there?
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

rainwarrior wrote: We could use some documentation on exactly what this compatibility subset of flash save actually supports, and how to set up the .SAV before starting. I didn't see anything that really describes it in the readme.
Basically, neither sector erase nor the bitwise-and-behavior when writing cleared sectors are supported. But as long as you follow the rule "always write the exact byte you wish to read back in the future", you shouldn't have any problems. The memory writes are protected by requiring the specific write sequence for flash writes, no matter which page is written to.
rainwarrior wrote: Is the first 8k of PRG automatically replaced by the save file on load? Is it always 8k or does the size of the provided .SAV file affect it?
No .sav file should be needed AFAIK. Said that, I did keep a .sav file in the directory myself while refining the solution, so didn't actually test that all menus in fact work as expected without it...

Anyway, the idea is that the original .sav file contents will never be used. Any .sav file you select at .NES loading time would be discarded. This functionality is a no-op for Mapper30 rather than disabled just because I couldn't be bothered to hack yet another Powerpak .MAP module, so just left the .NES loader untouched :)
rainwarrior wrote: I was a bit uncertain about what I should put in the .SAV file before running the ROM the first time. I just used 8k files filled with $FF. Presumably one should put a copy of the original PRG in there?
No, you shouldn't need a .sav file at all.

The way it works is:
* The mapper loader (contained in the first 1kB of MAP1E.MAP, with source code in mapper30hdr.asm) will "jsr CopyPrgToWram", to copy the first 8kB of the PRG ROM to the first 8kB of WRAM. This will happen before the FPGA is re-programmed with the mapper bitfile, when the "boot mapper" controls all bank switching.
* Whilst running the game, flash writes to the first 8kB of PRG will enable /WE on both the PRG and WRAM chip, while /OE will always be disabled on the WRAM, to prevent accidental writes.
* When the power button has been held and the boot ROM re-initialised the FPGA with the "boot mapper", it will then load the Q.MAP module (if the iNES header had the battery bit set)
* The Q.MAP module will (partially) load the iNES header of the last game, and if the mapper number was #30, then the "HackMenuForMapper30" subroutine will replace wramCluster with gameCluster, and saveName with gameName. Manual file selection will also be disabled (to avoid the boot ROM trashing more than 8kB of the WRAM)
* Auto-saving will load S.MAP, where the mapper30 code path will have the .NES file be written by looping over sectors, and incrementing the 8kB bank at $6000 as necessary. The first bank is initialised with bit7 set to select the the first 8kB of WRAM, and any subsequent banks will have it clear to select an 8kB PRG bank instead

So the documentation is brief because AFAIK it should mostly just work "automagically". With the obvious caveat that a large root or POWERPAK directory can cause the boot ROM to trash more than the first 8kB of PRG. Which can't really be fixed without changing the boot ROM, and which I did put a big warning text about.

Extending the mapper to use the full 32kB of WRAM for "flash mirroring" would be easy to do, but it would compromise the ability to use WRAM and flash writes together for a future hypothetical mapper implementation that could have both. Besides, I reckoned that if you are getting close to this limit, you're already doing something "bad", and it might as well fail early..

Though as we're unlikely to ever see a use for 24kB of spare WRAM, perhaps I might extend the WRAM-mirroring hack to use 16kB of the WRAM at some point, just in case we predict the Powerpak mapper set to grow big enough that nearly every iNES mapper has an entry in the POWERPAK directory... :)
User avatar
rainwarrior
Posts: 8716
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: PowerPak mapper 30 implementation

Post by rainwarrior »

Oh.... so for mapper 30 the save file is just a placebo and it just writes directly back to the .NES? (...and consequently loads its save from there too?)

Will writes to everywhere work (despite note being saved) or is only the low 8k writable?
Bananmos
Posts: 552
Joined: Wed Mar 09, 2005 9:08 am
Contact:

Re: PowerPak mapper 30 implementation

Post by Bananmos »

rainwarrior wrote:Oh.... so for mapper 30 the save file is just a placebo and it just writes directly back to the .NES? (...and consequently loads its save from there too?)

Will writes to everywhere work (despite note being saved) or is only the low 8k writable?
Writes anywhere will work, and the whole 512kB PRG *is* saved to the .NES file on the CF card. For example, Black Box Challenge writes its save data to somewhere in the middle of the PRG.

The .sav file is never used, and the only reason there's any interaction with the WRAM at all is just due to the boot ROM claiming the 512kB PRG area for storing directory entries. This is actually a kind of clever design by BunnyBoy: For normal games that only need to save WRAM, the whole PRG can be discarded after you've stopped playing it. So the PRG ROM area is a free resource for storage of directory names / their clusters, and allows the Powerpak to easily support browsing very large directories - whereas the Everdrive has quite a strict limit on directory entries IIRC.

But mapper30 breaks that assumption, because it flips everything around: PRG ROM now needs preserving, but WRAM does not. Because mapper30 uses the entire 512kB PRG there's also no possibility to restrict the game ROM to the upper area.

The clean way to fix this would therefore be to change the boot ROM to switch to loading the directory entries into WRAM when a mapper30 game has finished playing.

But as updating the boot ROM is not easy, I instead opted for a work-around which duplicates the first page to allow recovering it after the boot ROM has trashed it. Think of the first 8kB WRAM page as just a backup of the PRG area. Again, to summarize the process:

1) After loading the MAP1E.MAP module from the CF, this module will copy the first 8kB bank of the PRG ROM from the .NES file to the first 8kB of WRAM, making this 8kB WRAM bank a duplicate of the first 8kB of PRG.

2) While playing the game, the mapper30 logic in the FPGA will duplicate any writes to the first 8kB bank of the PRG ROM to the first 8kB of WRAM. Other 8kB PRG ROM pages will be written to the PRG ROM only, as expected. This ensures that WRAM always remains a duplicate of PRG ROM for the first 8kB bank, even after the PRG has been updated.

3) After resetting, the Powerpak boot ROM will load the (modified) Q.MAP module. This operation will have trashed the first N bytes of the PRG ROM with directory entries even before control is handed over to Q.MAP

4) If you choose to save, the new mapper30 save code in S.MAP will save the entire 512kB PRG to the .NES ROM on the CF, but substitute the first 8kB bank with the contents of the first 8kB WRAM bank. All other banks will be from the 512kB PRG memory chip, as expected.

Despite jumping through hoops, it should all just work transparently to the user. The only caveat - as mentioned already - is that you can break this by having too many directory entries in either the root directory or the POWERPAK directory.
Each directory entry will use up 32 bytes (28 bytes for the truncated filename, and 4 bytes for the cluster) of the PRG ROM, which should result in a limit of 254 files / directories in total IIUC (as '.' and '..' would take up an entry as well) when only the first 8kB bank is duplicated. But I put ~200 in the readme just to keep people extra careful...
User avatar
rainwarrior
Posts: 8716
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: PowerPak mapper 30 implementation

Post by rainwarrior »

Ah! So it's way better than I expected! So in the end it's a very close match except for sector/chip erase, and otherwise the save filename is a placebo because it saves directly to the .NES.

I'm curious how FDS saving was implemented... though I suppose the modified BIOS could just write out the file any time it changed.

You mentioned Mapper 30 + WRAM as a possibility... I guess 8k of WRAM could theoretically be added to the mapper, but I don't think 32k ever could? New banking bits for that would require a new mapper assignment, and this mapper is already terribly overloaded with flash/non-flash and 4-screen configurations.

At any rate, not important to support WRAM until something actually requires it, IMO.
Post Reply