PowerMappers is a new set of mappers for the PowerPak NES flash cartridge. It is a complete rewrite of my previous Save State Mappers. I have been sitting on this for a while, but since there hasn't been significant progress in the last month or so, this seems like a good time to release it.
Download at
https://kkfos.aspekt.fi/If you encounter any problems, let me know. This is still in a beta state.
(Cross-posted to NintendoAGE forums.)
Thanks for the hard work! I'll try them out.
Do these contain whatever fixes were in loopy's mapper set for MMC3? (It's been a while...) I can pull my PowerPak out and test stuff if you need it!
koitsu wrote:
Do these contain whatever fixes were in loopy's mapper set for MMC3? (It's been a while...) I can pull my PowerPak out and test stuff if you need it!
MMC3 IRQ should be the same as in loopy's mappers. However, it can still be problematic for a couple of different reasons. It works well enough on my setup.
I don't have anything specific for you to test, but general testing would be welcome, since this was only tested by myself before release, and also very briefly by Pasky.
There was issue on one of Pasky's AV Famicoms (I believe) where loading would corrupt the nametable (in all mappers). Haven't been able to figure the cause of that one out yet, since I can't reproduce it.
So I go around to trying these out and to my surprise an particular NROM image that used to not work suddenly did. I guess I had *really* outdated mappers. Thank you. Also, nice touch on clearing the ram.

Great work fox! Some comments on your compatibility list :
All the games that rely on bus capacitance for input work fine for me, but I didn't test save states.
Bubble Bath Babes, Hot Slots and Peek-A-Boo Poker all run with your new mappers.
Pin Bot, High Speed, Gauntlet and Rad Racer II and Conflict now run with the new mappers.
In your prior mapper 4, Bucky O'Hare's scanlines seemed to be solid.
For Startropics, Mike's sprite doesn't flicker for me, but the last scanline before the border does. I didn't notice any flickering sprites or scanlines in Startropics II.
Try as I might, I can't see anything wrong with Perfect Fit's graphics, but I can see issues with the other games you listed as corrupting CHR-ROM.
Mickey in Numberland has severe glitches and is not playable, but Letterland is playable.
Great Hierophant wrote:
All the games that rely on bus capacitance for input work fine for me, but I didn't test save states.
Yeah, this is expected. I don't know what is wrong with this NES of mine that it has one of the controller bits high that's not supposed to be high.
Quote:
In your prior mapper 4, Bucky O'Hare's scanlines seemed to be solid.
Quote:
Mickey in Numberland has severe glitches and is not playable, but Letterland is playable.
MMC3 is really annoying to implement, because of the unclean PPU A12 that PowerPak provides. It's literally up to luck whether a certain revision of the mappers will work well or not, depending on how the logic is laid out. I'd suggest doing what the original MMC3 boards did, and add a 220 pf capacitor from ground to PPU A12 on the PowerPak. I'd be interested in hearing if this fixes any problems for anybody willing to try it.
Quote:
Try as I might, I can't see anything wrong with Perfect Fit's graphics, but I can see issues with the other games you listed as corrupting CHR-ROM.
IIRC you have to press SELECT to exit the game for the corruption to occur, or something like that. The CHR corruption problem is another flaw in the PowerPak hardware design and I don't know of a workaround for it (besides patching the ROM).
More MMC3 fun :
Crystalis - The screen shakes when a dialog window is present.
Star Trek 25th Anniversary - Corrupt graphics flicker when the dialog window appears on the ship. I see this with Little Ninja Bros. as well.
Quote:
MMC3 is really annoying to implement, because of the unclean PPU A12 that PowerPak provides. It's literally up to luck whether a certain revision of the mappers will work well or not, depending on how the logic is laid out. I'd suggest doing what the original MMC3 boards did, and add a 220 pf capacitor from ground to PPU A12 on the PowerPak. I'd be interested in hearing if this fixes any problems for anybody willing to try it.
Is this as simple as putting one leg of a capacitor on PPU/CHR A12 (say at pin 64 of the cartridge connector) and another leg on GND? Would this have any negative effect on games that do not use MMC3? Sounds easy enough to try.
Great Hierophant wrote:
Is this as simple as putting one leg of a capacitor on PPU/CHR A12 (say at pin 64 of the cartridge connector) and another leg on GND? Would this have any negative effect on games that do not use MMC3? Sounds easy enough to try.
As far as I understand, the cap should preferably be placed as close to the FPGA input as possible, but I'm no electrical engineer. Placing it close might be hard, though, so you can try placing it at the cart connector I guess. It shouldn't have any negative effects on other mappers/games.
A digital delay filter within your mapper might work as well.
2600 wrote:
A digital delay filter within your mapper might work as well.
Such implementation couldn't match the real MMC3 behavior very closely though, because on a real MMC3 the IRQ is asserted directly on the rising edge of A12.
thefox wrote:
2600 wrote:
A digital delay filter within your mapper might work as well.
Such implementation couldn't match the real MMC3 behavior very closely though, because on a real MMC3 the IRQ is asserted directly on the rising edge of A12.
I think it could match it closely, but you may think differently. I'm just talking about a delay of a few ns. Enough to filter out the random spike. The capacitor delays the rising edge of A12 as seen by the MMC3 as well.
2600 wrote:
I think it could match it closely, but you may think differently. I'm just talking about a delay of a few ns. Enough to filter out the random spike. The capacitor delays the rising edge of A12 as seen by the MMC3 as well.
How do you implement a few ns delay digitally? The PowerPak's on-board clock is 20 MHz.
You have A12 go through a buffer or two and let's call this A12_delay. Then you AND A12_delay with A12. You'll need to make sure that ISE doesn't optimize out the buffer so you may want to use 2 NOT gates, AND gates, or whatever instead of a buffer.
2600 wrote:
You have A12 go through a buffer or two and let's call this A12_delay. Then you AND A12_delay with A12. You'll need to make sure that ISE doesn't optimize out the buffer so you may want to use 2 NOT gates, AND gates, or whatever instead of a buffer.
Ah, combinational. Kind of dirty, but maybe it would be sufficient. I may test this at some point.
thefox wrote:
Ah, combinational. Kind of dirty, but maybe it would be sufficient. I may test this at some point.
It's not as bad as it sounds and is used quite often. The delay is whatever the propagation delay is through the buffers, but is still probably less then the MMC3's propagation delay. Might want to try it with your A13 issue as well. Just delay A13 and /A13 to your chip select logic.
Also, the kind of delay you mentioned by using the PowerPak's clock isn't a good idea and generally frowned upon since the PowerPak's clock isn't related to the PPU clock.
2600 wrote:
It's not as bad as it sounds and is used quite often. The delay is whatever the propagation delay is through the buffers, but is still probably less then the MMC3's propagation delay. Might want to try it with your A13 issue as well. Just delay A13 and /A13 to your chip select logic.
Well, the problem is that it relies on the propagation delays of the FPGA, which could change between the FPGA revisions and so on.
Quote:
Also, the kind of delay you mentioned by using the PowerPak's clock isn't a good idea and generally frowned upon since the PowerPak's clock isn't related to the PPU clock.
Yes, the signals would need to be synchronized, which would add additional delay.
You are amazing. I have a busy weekend, but I'm hoping to try this sometime. Let me know if you want us to test anything in particular, otherwise, I'll just start playing

Your new mappers are truly amazing. Thank you so much for the hard work. Is there a way to convert the old save states to the new ones?
cubeboy wrote:
Your new mappers are truly amazing. Thank you so much for the hard work. Is there a way to convert the old save states to the new ones?
Thank you. No, there is no way to convert save states at the moment.
Just coming in to again say how awesome your new power mappers are. I've played a few games now and beat them without any noticeable issues (no cheating with save states either, just a way to "pick up where I left off" between days

). I even have my 10 and 11 year old watching and helping me with the original Zelda right now, the game apparently still holds up enough to keep their interest. Now I just need to remember how to get through the lost woods without looking it up

For the A12 buffer circuit, a really simple debounce logic I use is to feed the input into a synchronous shift register and then take your output signal as the reduction-AND of all of the bits in the shift register. Then, you only get an output high when the input has remained high for that many consecutive clock cycles. Then all you have to do is adjust the size of the shift register until you get the result you want. More bits = more consistent, but more delay. At 20MHz, you may also need a clock divider on it, or else you'd need a really large number of bits in the shift register. It's simple, and it works.
qwertymodo wrote:
For the A12 buffer circuit, a really simple debounce logic I use is to feed the input into a synchronous shift register and then take your output signal as the reduction-AND of all of the bits in the shift register. Then, you only get an output high when the input has remained high for that many consecutive clock cycles. Then all you have to do is adjust the size of the shift register until you get the result you want. More bits = more consistent, but more delay. At 20MHz, you may also need a clock divider on it, or else you'd need a really large number of bits in the shift register. It's simple, and it works.
Like I said earlier, this kind of implementation can never match the original MMC3 behavior, because on the real MMC3 the IRQ is triggered directly on the rising edge of A12 (with a very minor delay). Such implementation might still be close enough to be usable, but some games won't like it (Mickey's Adventures in Numberland, for example, requires very precise IRQ timing).
Not sure if this is a glitch that you can control or not (or even care about

), but I was just playing Zelda 1, and on level 8, when I went into the boss room, some code showed up briefly on the screen while transitioning to the boss room. Everything worked fine after that.
cubeboy wrote:
Not sure if this is a glitch that you can control or not (or even care about

), but I was just playing Zelda 1, and on level 8, when I went into the boss room, some code showed up briefly on the screen while transitioning to the boss room. Everything worked fine after that.
Doesn't sound like something that would be caused by the mappers.
Mappers can cause "code" to be shown, especially when it causes mirroring to be wrong. This can cause uninitialized video memory to show, a sprite 0 hit to fail, or any of several other sorts of badness.
thefox wrote:
PowerMappers is a new set of mappers for the PowerPak NES flash cartridge. It is a complete rewrite of my previous Save State Mappers. I have been sitting on this for a while, but since there hasn't been significant progress in the last month or so, this seems like a good time to release it.
Download and more info at
http://kkfos.aspekt.fi/projects/nes/pow ... ermappers/If you encounter any problems, let me know. This is still in a beta state.
(Cross-posted to NintendoAGE forums.)
Great! Many thanks for the hard work.
Just wanted to ask; is there any possibility to have Mappers 90 supported, someday? As it has some cool pirates such as Tekken 2, Aladdin, Super Mario World, Mortal Kombat, et cetera.
Thanks again.
deksar wrote:
Just wanted to ask; is there any possibility to have Mappers 90 supported, someday? As it has some cool pirates such as Tekken 2, Aladdin, Super Mario World, Mortal Kombat, et cetera.
Some possibility yes, but I don't have any current plans to add support for it.
New version (v23) released:
https://kkfos.aspekt.fi/Changes:
Code:
- v23 (2015-12-28)
* New MMC3 IRQ implementation (RAMBO-1 style, based on M2). Doesn't
exactly match real MMC3 timings, but should be more robust than the
previous implementation.
* Don't enable CHR-RAM if PPU asserts /RD and /WR at the same time due
to rogue $2007 writes. Fixes graphics glitching in the following games:
- Noah's Ark (E)
- Addams Family, The - Pugsley's Scavenger Hunt (U)
- Baseball Stars II (U)
- Bigfoot (U)
- Krusty's Fun House (U)
- Perfect Fit (U)
- v21 (2015-12-16)
* Fixed a bug in controller read corruption handling (caused menu to
show up spuriously in Bomberman II). Thanks to WaverBoy for report.
* FME-7 IRQ acknowledgement behavior changed to match
http://forums.nesdev.com/viewtopic.php?p=142246#p142246 (should not
affect any games).
Awesome job, here are the games affected by these mappers that I have found to be buggy :
Low-G-Man : Music for Level 1 Boss is not correct, but it does not crash
Startropics 1 & 2 : Half of Mike's small sprite flickers constantly, as does his inventory in the action sequences.
Guerilla War : Single scanline flicker which begins about a third of the way into the first stage.
Rad Racer 2 : Occasional flickering of yellow/orange lines in the road
Mickey's Adventure in Numberland : Certain tiles in Mickey's sprite flicker constantly similar to Startropics
Mickey's Safari in Letterland : Status menu expands or constricts by 1-2 scanlines regularly
Little Ninja Brothers : Shaking in status menus, text boxes and the like. Also affects current EverDrive OS.
Great Hierophant wrote:
Low-G-Man : Music for Level 1 Boss is not correct, but it does not crash
Probably coincidental, since the game has a bug, relying on values read from WRAM (which the real cart doesn't have). So it'd depend on whatever values happened to be in the WRAM when you started the game. Should be possible to work around it simply by loading an 8KB save file full of $FF. I guess the mapper loader could check if the game has battery backing, and if not, initialize WRAM to $FF always...
How was the music not correct?
Quote:
Startropics 1 & 2 : Half of Mike's small sprite flickers constantly, as does his inventory in the action sequences.
Yeah, known. ST requires very precise IRQ timing on real hardware due to a PPU hardware bug (
http://wiki.nesdev.com/w/index.php/Erra ... nd_Sprites, "Turning rendering off in PPUMASK..."). At least that's my theory.
Quote:
Guerilla War : Single scanline flicker which begins about a third of the way into the first stage.
Unlikely to be a mapper problem since the game uses MMC1. Have you checked on a real cart? It sounds/seems like it might be caused by yet another hardware bug:
http://wiki.nesdev.com/w/index.php/Errata#Video ("When writing to PPUCTRL ($2000) at the exact start of horizontal blanking..."). I checked in emulator and this game does seem to be doing quite a lot of PPUCTRL writes midscreen.
EDIT: Same symptoms in
https://youtu.be/fTs-6dgGxqs?t=79 (AFAIK NESGuide's gameplay videos use original carts).
Quote:
Mickey's Adventure in Numberland : Certain tiles in Mickey's sprite flicker constantly similar to Startropics
Mickey's Safari in Letterland : Status menu expands or constricts by 1-2 scanlines regularly
These two require very precise IRQ timing. The current implementation fires the IRQ a little bit later than it should.
Quote:
Little Ninja Brothers : Shaking in status menus, text boxes and the like. Also affects current EverDrive OS.
Not entirely sure what's causing this, but wouldn't be surprised if it has tight timing in the IRQ handler as well...
Low-G-Man's music sounds more warbly compared to a real cart. Loading a Save RAM file with all FFs fixes the music.
I don't have a real cartridge of Guerilla War, but the lines appear with the PowerMappers, the Save Mappers and the EverDrive, so I am now of the belief that they should be there. The video was uploaded on July 8, 2007, which almost certainly predates the PowerPak. Odd that neither Nestopia UE nor Nintendulator show them.
I would note that Mickey's Letterland requires the Acclaim MMC3 IRQ timing, but Numberland uses a standard Nintendo MMC3.
Great Hierophant wrote:
Odd that neither Nestopia UE nor Nintendulator show them.
This bug was pinned down fairly recently (
viewtopic.php?f=2&t=10104), and we still don't know the exact details of it, so no emulator (to my knowledge) emulates it.
Thank you for these. I was experiencing graphical glitches in Zelda II with the mappers that came with the PowerPak. I tried your PowerMappers and it cleared it right up.
I tried to run Tecmo Super Bowl 2017 on my PowerPak with the PowerMappers, but it's failing for me. I get to the point where the progress bar gets to 100%, it goes to a black screen like normal, but it stays stuck on a black screen. Previous iterations of Tecmo Super Bowl 201X seem to work, but this one is failing. I'm assuming it's more of an issue with the rom file, versus the mappers. Not sure if anyone can "easily" determine the failure point or not.
http://tecmobowl.org/files/file/505-tec ... bowl-2017/
cubeboy wrote:
I tried to run Tecmo Super Bowl 2017 on my PowerPak with the PowerMappers, but it's failing for me. I get to the point where the progress bar gets to 100%, it goes to a black screen like normal, but it stays stuck on a black screen. Previous iterations of Tecmo Super Bowl 201X seem to work, but this one is failing. I'm assuming it's more of an issue with the rom file, versus the mappers. Not sure if anyone can "easily" determine the failure point or not.
http://tecmobowl.org/files/file/505-tec ... bowl-2017/That game uses MMC5, it should not even show the PowerMappers loading progress bar (PowerMappers doesn't include MMC5 support).
Loopy's MMC5 mappers work for the 2017 versoin.
One more for you, Jurassic Park's Ocean logo on the title screen, it should not show lines outside the natural edge of the logo's box.
hackfresh wrote:
Loopy's MMC5 mappers work for the 2017 versoin.
Thanks for the info.
Is there a way to have Loopy's MMC5 mapper be installed in parallel with the PowerMappers, or would I need to swap out the mappers anytime I want to run an MMC5 game?
You copy the mappers like this, overwriting in this order :
Latest official beta -> Loopys mappers -> PowerMappers
See here for more detail :
http://nerdlypleasures.blogspot.com/201 ... apper.html
Individual mappers are self-contained, so they can be mixed and matched at will. Each MAPXX.MAP file implements a particular mapper (XX = iNES mapper number in hexadecimal). MMC5 would be in a file named MAP05.MAP (this file is not included in PowerMappers).
thefox wrote:
Great Hierophant wrote:
Low-G-Man : Music for Level 1 Boss is not correct, but it does not crash
Probably coincidental, since the game has a bug, relying on values read from WRAM (which the real cart doesn't have). So it'd depend on whatever values happened to be in the WRAM when you started the game. Should be possible to work around it simply by loading an 8KB save file full of $FF. I guess the mapper loader could check if the game has battery backing, and if not, initialize WRAM to $FF always...
A while ago I made an IPS patch for Low-G-Man that does that in code. Here:
https://forums.nesdev.com/viewtopic.php?f=2&t=13105Two questions:
1. I was wondering if there could be a way to disable the SELECT + START menu, so that I could use those buttons "naturally" in games and especially in test programs. I would have suggested just disabling the menu automatically if no state file was selected, but the exit to menu feature is probably worth having by itself usually. An option to disable it would be appreciated, though. Not sure where, maybe in the file/game-genie select page?
2. Do you still plan to make source code available at some point?
I want to make an implementation of the (relatively simple)
mapper 31, and it would be nice to have solid ground to start on. I made
an implementation for the Everdrive while making the
Famicompo Pico ROM, because at 512k it was small enough to run on the Everdrive. (The
first mapper 31 ROM was 1MB.) Because it requires 4k banking, on the PowerPak it would be limited to 256k, though, so I never bothered. Since I recently made a
tool for building mapper 31 music ROMs, I finally have smaller ROMs worth trying on the PowerPak.
Anyhow, it's a relatively simple mapper, but it would need a custom loader to duplicate banks for simulated 4k mapping, like the NSF player. Since your powermappers seem to have such a custom loader, source code would be really helpful to understand how you did that.
rainwarrior wrote:
A while ago I made an IPS patch for Low-G-Man that does that in code. Here:
https://forums.nesdev.com/viewtopic.php?f=2&t=13105I guess I should implement that "fill WRAM with $FF if not battery-backed". It'd also provide a mostly consistent "power-on" state for games, since I'm already initializing most of the rest of the memory.
Quote:
1. I was wondering if there could be a way to disable the SELECT + START menu, so that I could use those buttons "naturally" in games and especially in test programs. I would have suggested just disabling the menu automatically if no state file was selected, but the exit to menu feature is probably worth having by itself usually. An option to disable it would be appreciated, though. Not sure where, maybe in the file/game-genie select page?
Yeah, the main reason it has not been done yet is that I haven't been able to think of where to put the option. It could be in the in-game menu as well, you just would not be able to go back to the menu after disabling it (and it would have to only be active for the current session).
Quote:
2. Do you still plan to make source code available at some point?
Probably not in the near future (too much work to clean it up for release). But could happen eventually. I have some other projects I should throw on GitHub as well...
Quote:
I want to make an implementation of the (relatively simple)
mapper 31, and it would be nice to have solid ground to start on. I made
an implementation for the Everdrive while making the
Famicompo Pico ROM, because at 512k it was small enough to run on the Everdrive. (The
first mapper 31 ROM was 1MB.) Because it requires 4k banking, on the PowerPak it would be limited to 256k, though, so I never bothered. Since I recently made a
tool for building mapper 31 music ROMs, I finally have smaller ROMs worth trying on the PowerPak.
Anyhow, it's a relatively simple mapper, but it would need a custom loader to duplicate banks for simulated 4k mapping, like the NSF player. Since your powermappers seem to have such a custom loader, source code would be really helpful to understand how you did that.
I would suggest starting with loopy's Verilog mappers as a base. The PowerPak firmware/menu source code is available
somewhere (can't remember where), I think the default mapper loader is there as well. If it's not, you can disassemble it, it's quite short; it's the first 1 KB of a .MAP file in normal mappers (not in PowerMappers because I ran out of space and had to chain multiple loaders...). You can grab the procedure/variable addresses used in firmware from the source code (I believe NESASM generates a file which has the labels at least). You should then be able to copy the routine that loads the PRG data from the firmware into your custom loader and modify accordingly.
thefox wrote:
rainwarrior wrote:
Anyhow, it's a relatively simple mapper, but it would need a custom loader to duplicate banks for simulated 4k mapping, like the NSF player. Since your powermappers seem to have such a custom loader, source code would be really helpful to understand how you did that.
I would suggest starting with loopy's Verilog mappers as a base. The PowerPak firmware/menu source code is available
somewhere (can't remember where), I think the default mapper loader is there as well. If it's not, you can disassemble it, it's quite short; it's the first 1 KB of a .MAP file in normal mappers (not in PowerMappers because I ran out of space and had to chain multiple loaders...). You can grab the procedure/variable addresses used in firmware from the source code (I believe NESASM generates a file which has the labels at least). You should then be able to copy the routine that loads the PRG data from the firmware into your custom loader and modify accordingly.
We have links to
the source from
our wiki page. However, the loader mini-module (loaded into $400-$7ff) assembly seems to be missing; the docs basically treat it as a magic 1024 bytes that you have to prepend to a mapper's verilog output. (The small modules, one-letter-named, get similarly loaded into $400-7ff.) I've already disassembled two versions of the mapper loader by hand, though. Lemme get it into a theoretically-assemblable format…
Older:
Code:
;bunnyboy's loader (identical between MAP00 and MAP03 as test points)
.org $400 ;module entry point
JMP $0407
;unwritten byte, FF
.org $404 ;module's deal-with-controller routine
JMP return ;046c
;and now we're at the "entry" 0407
JSR RenderingOff ;f703
JSR ClearNameTable ;e813
JSR LoadLogo ;e89e, this displays powerpak logo, omitted in Loopy's MAP03 loader
JSR ClearLine ;e844
LDA #$0C ;LOADGAME string ID.
STA $00A5 ;temp 0c@A5 ..and yes, all of these were 8d=STA $aaaa.
JSR StrCopy ;e927
LDA #$1B ;line to print on
STA $003A ;printY 1b@3A
JSR PrintLine ;e85e
LDA #$F8
STA $0030 ;cursorY f8@30
STA $002F ;cursorX f8@2f
LDA #$00
STA $0031 ;scrollY 0@31
STA $0032 ;scrollYCounter 0@32
STA $0033 ;scrollYUp 0@33
STA $0034 ;scrollYDown 0@34
STA $0035 ;cursorYCounter 0@35
STA $0036 ;cursorYUp 0@36
STA $0037 ;cursorYDown 0@37
JSR RenderingOn ;f6e1
;the other difference to Loopy's MAP03 loader is an inserted JSR to LoadWRAM here
;this is odd, as loader.asm's LoadWRAM consists of a lone RTS instruction
LDA #$00
STA $002E ;destBank 00@2e
STA $4200 ;PRGSIZEWR(PRGMASK) 00@4200, not sure why this is written now.
JSR LoadPrgRam ;f408
JSR RenderingOff ;f703
JSR LoadCHRRAM ;f51f
JSR LoadFPGA ;f602
JSR LoadMirroring ;f6da
JSR LoadPrgChrSize ;f6b7 ...as this uses the iNES header to write to
;PRGSIZEWR
JSR LoadgameGenie ;f665
LDA #$00
STA $4207 ;BOOTENWR
JMP (RESET) ;fffc
return: RTS ;this is at 046C. Why they don't just RTS at $0404 I don't know.
edit: variable addresses, since I also already did that work
Code:
Name [command] width start address
sourceLo .rs 1 0
sourceHi .rs 1 1
destLo .rs 1 2
destHi .rs 1 3
sourceStrLo .rs 1 4
sourceStrHi .rs 1 5
sourceEntryLo .rs 1 6
sourceEntryHi .rs 1 7
destEntryLo .rs 1 8
destEntryHi .rs 1 9
printAddrLo .rs 1 A
printAddrHi .rs 1 B
tempEntry .rs 34 C
destBank .rs 1 2E
cursorX .rs 1 2F
cursorY .rs 1 30
scrollY .rs 1 31
scrollYCounter .rs 1 32
scrollYUp .rs 1 33
scrollYDown .rs 1 34
cursorYCounter .rs 1 35
cursorYUp .rs 1 36
cursorYDown .rs 1 37
speedCounter .rs 1 38
speedScroll .rs 1 39
printY .rs 1 3A
spriteNum .rs 1 3B
partitionLBABegin .rs 4 3C
fatBeginLBA .rs 4 40
clusterBeginLBA .rs 4 44
sectorsPerCluster .rs 1 48
rootDirCluster .rs 4 49
baseDirCluster .rs 4 4D
sectorsPerFat .rs 4 51
reservedSectors .rs 2 55
sectorCounter .rs 2 57
sourceCluster .rs 4 59
sourceSector .rs 4 5D
fat32Enabled .rs 1 61
fat16RootSectors .rs 2 62
prevFrameCounter .rs 1 64
frameCounter .rs 1 65
joystick .rs 1 66
findEntry .rs 11 67
exMatch1 .rs 4 72
exMatch2 .rs 4 76
exMatch3 .rs 4 7A
selectedEntry .rs 2 7E
filesInDir .rs 2 80
lfnFound .rs 1 82
printString .rs 34 83
temp .rs 4 A5
source256 .rs 1 A9
sourceBytes .rs 1 AA
gameName .rs 32 AB
saveName .rs 32 CB
mapperData .rs 16 EB ;this is the iNES header
gameCluster .rs 4 FB
wramCluster .rs 4 FF
mapperCluster .rs 4 103
prgSize .rs 1 107
chrSize .rs 1 108
mapperNumber .rs 1 109
mirroring .rs 1 10A
mapperModule .rs 2 10B
powerOn .rs 1 10D
useBattery .rs 1 10E
wramBanks .rs 1 10F
gameGenie .rs 40 110
gameGenieOffset .rs 1 138
gameGenieCodes .rs 40 139
arcadeDip .rs 1 161
moduleReady .rs 1 162
bankCounter .rs 1 163
romVers .rs 3 164
oldButtons .rs 1 167
heldButtons .rs 1 168
scrollHoldTimer .rs 1 169
searchEntry .rs 34 16A
edit further:
I see a bug in the PowerPak firmware in LoadPrgChrSize. It assumes power-of-2 sizes for bank counts, as it subtracts one and uses that as its address line masks.
Thanks for the info, thefox.
An additional thing that source might help is to be able to send you additions/patches for PowerMappers. We're already in kind of a horrible situation where a lot of people have 3 layers of mappers installed on top of each other, I'd hate to be creating yet another mapper repository overlay. :S (Of course... this particular problem could be better solved by bunnyboy.)
Put in a bit above you, did you miss it?
Quote:
people have 3 layers of mappers installed on top of each other,
Or, if someone got the ones that I tinkered with Loopy's code to make, 4.
Even if he built them; I never got around to getting that Xilinx license. Then again, those are [so far] strictly disjoint from mappers that others implemented.
In any case, I've got a spreadsheet with who's made what mappers for PowerPak. Haven't managed to automate its color-coding yet, though.
If you've got info on other mapper sets maybe add it to the wiki under and "other mappers" heading?
https://wiki.nesdev.com/w/index.php/PowerPak
It's just a compilation of the information on that page and my own mappers, so it's not new information. The information I was trying to direct you to was the loader disassembly.
…besides, not all of the mappers in my pack are In Working Order; I was intending to wait until they were before adding my own to it. But I suppose I can add it in.
I can fill in a couple of details about the loader:
Quote:
;this is odd, as loader.asm's LoadWRAM consists of a lone RTS instruction
The LoadWRAM routine from firmware was probably patched out as being buggy at some point (and replaced with the same thing handled in the menu modules).
Quote:
return: RTS ;this is at 046C. Why they don't just RTS at $0404 I don't know.
IIRC, the firmware modifies the opcode at $404 to an RTS temporarily in some cases and then restores it to a JMP. So if you have a non-JMP opcode in there it will become invalid when it's "restored".
Quote:
I see a bug in the PowerPak firmware in LoadPrgChrSize. It assumes power-of-2 sizes for bank counts, as it subtracts one and uses that as its address line masks.
This depends on your point of view. ROMs with non-power-of-2 sizes are often considered invalid, anyways. It would make some sense for CHR, but we haven't standardized on how to map such sizes to the address space (quite many options here).
rainwarrior wrote:
We're already in kind of a horrible situation where a lot of people have 3 layers of mappers installed on top of each other, I'd hate to be creating yet another mapper repository overlay. :S (Of course... this particular problem could be better solved by bunnyboy.)
Yeah, the situation is not great, but I also don't have the time or motivation to become an active maintainer of the mappers.
...
I guess I might as well post the ca65fied firmware function and variable definitions:
Functions (and some other ROM symbols):
Code:
; The contents of this file were generated from loader.asm of PowerPak firmware.
.scope PowerPakFuncs
LoadCHRRam1 = $F526
CardLoadDirShortNameFound = $EFF2
DirFindEntry = $F2D6
CardLoadDirSaveEntryLoop = $F042
Joyloop = $E7FF
LOGO4 = $E25A
FPGACopyRomLoop2 = $F3F9
GameGenieAddressEncode = $EA4B
NewCFNotReady = $F98F
LoadFPGASectorDone = $F664
CardLoadDirLastEntryFound = $EEC0
CardLoadDirLongName2 = $EEF4
LoadFPGALoop = $F62D
LoadCHRRamLoopCheckBank = $F565
CardReadSector = $ED4C
DirPrintDirLoop = $F33C
LSRA3 = $EB92
CardLoadDirCheckUnused = $EEC1
ShiftLine = $E86E
LOGO5 = $E262
CardLoadDirClearEntryName = $EE07
CardReadSector496LoopInc = $EDD0
Short2Str = $E9C7
ClearNameTable = $E813
ResetFPGAConfigured = $E468
CardFormatError = $F79C
CardLoadDirShortNameLoop = $EFF4
LOGO6 = $E26A
CardReadSector496ChrLoop = $F5E3
CardLoadDirLastEntryCheck = $F10C
WaitFrame = $F8E4
CardCopyFatBeginLBA = $E6BA
LoadMirroring = $F6DA
LoadCHRRamLoopCheckDone = $F589
DoYScrollDone = $E32D
LOGO7 = $E272
CardLoadDirLongNameLoop1 = $EF00
DirFindEntryFailed = $F312
IRQ = $E282
WEBSITE = $E162
LoadLogoLineLoop = $E8A8
CheckCardReset = $E546
CardWriteSector = $EDDE
CardReadSector16 = $ED8B
LOADGAME = $E1A2
CardReadBytes = $ED76
LOGO8 = $E27A
CardLoadDirSaveEntry = $F020
CardWaitNotBusy = $ECF3
CheckYScroll = $E2FD
DirPrintDir = $F325
CardLoadDirLongNameLoop2 = $EF18
DoCursorScroll = $E2EF
WaitFrameLoop = $F8E7
DirPrintEntryCopyLoop = $F28E
CardLoadDirReadSector = $EEAF
GameGenie8Encode = $EB22
ScrollDownDone = $E440
NewCFBusy = $F949
DirFindEntryCharLoop = $F2E3
CardNotReady = $E5A9
Byte2Str = $E9FB
WaitVBlank = $E7ED
Forever = $E7D6
FPGACopyRom = $F39F
CardReadSector496Chr = $F5DF
CardLoadDirLongNameLoop3 = $EF30
GetVolumeID = $E642
ScrollDownCheckMiddle = $E42F
NextClusterDone = $ECB6
DirFindEntryNewNext = $F8A6
DirPrintEntryDone = $F2A3
LOADDIR = $E102
LoadGameGenie = $F665
ClearRamReturn = $E456
CardCopyClusterBeginLBA = $E6DD
CardReadSectorDone = $ED75
CardLoadDirLongNameLoop2FF = $EF21
DirPrintEntryShiftLoop = $F279
CardLoadDirLongName = $EEF9
ClusterToLBADone = $EC05
LoadPrgChrSize = $F6B7
CardLoadDirLoop = $EEB5
CardLoadLBA = $ED2A
DirPrintDirLoopDone = $F36D
CardBootLoop = $E52F
NewCFBoot = $F8ED
FileNotFoundLoop = $F8D6
CardReadSector16Chr = $F5AD
LoadLogo = $E89E
ScrollUp = $E32E
LoadCHRRamLoop = $F537
ClearLine = $E844
PrintChar = $E892
ClearSpriteRamLoop = $E83D
WritePalette = $E4B8
MemCopyLoop = $E94E
LoaderLoadModuleDone = $E7BC
CardLoadDirCheckEx3Loop = $EFC3
CardWriteSectorDone = $EE06
CardCheckError = $ED07
LoadPRGRamLoop = $F440
CardLoadDirLongShortNameFound = $F020
NOTREADY = $E062
DUDE = $E1E2
CardLoadDirNextSectorNum = $F14E
LoadModuleI = $E7AC
StrCopyLoop = $E93E
LoadFPGASectorLoop = $F655
Short2Str2 = $E9E3
DirGetEntryShiftLoop = $F2B7
CardCopyRootDirCluster16 = $E687
RenderingOff = $F703
CardGoodFormatX = $F84E
CardLoadDirLoadNextSector = $F156
ClusterToLBAAddClusterBeginLBA = $EBE0
CardLoadDirCheckHidden = $EF62
NewCFInserted = $F8ED
CardReadSector496 = $EDBC
StrCopy = $E927
ClearFindEntry = $E851
WERR = $E0C2
NOTFOUND = $E0E2
RERR = $E0A2
NewCFResetDone = $F929
CardLoadModuleNextSector = $F223
DirPrintEntry = $F257
CopyChrRamLoop = $E918
PP = $E022
DirGetEntryCopyLoop = $F2CB
CardLoadDirLongNameLoop3FF = $EF39
CardCopyPartitionLBABeginX = $F866
ClearLineLoop = $E848
LoadLogoCharLoop = $E8AA
CardReadSector496LoopDone = $EDDA
ForeverLoop = $E7D9
GameGenieEncode = $EAA7
NextClusterLoop = $EC94
CardReadSector496ChrDone = $F601
DirFindEntryNew = $F878
CardLoadDirShortName = $EFDA
CardLoadDirClearTempEntryName = $F071
CardReadSector16ChrLoop = $F5C2
LoadPRGRamLoopCheckBank = $F45F
NextCluster = $EC06
CardFormatErrorX = $F835
CardLoadDirLastEntryCheck2 = $F12B
ScrollDownCheckBottom = $E3FF
DoYScrollUnderflow = $E324
ClearSpriteRam = $E82E
CFBUSY = $E222
ScrollDown = $E3C0
CardLoadDirShortFileName = $EFFE
SAVERAM = $E202
CardReadSector496Done = $EDDD
FileNotFound = $F8D4
CheckCursor = $E2E5
CardLoadDirCheckDir = $EF77
CardLoadDirCheckLongName = $EED1
CardGoodFormat = $F7B5
GG = $E142
CardReadSector496ChrLoopInc = $F5F4
LoadPRGRamLoopCheckDone = $F476
CardLoadDirClearEntryNameLoop = $EE10
CardBusy = $E579
DirFindEntryLoop = $F2DE
CardCopyPartitionLBABegin = $F7B7
CardWriteSectorLoop = $EDF5
LoadModuleQ = $E7B4
DirFindEntryNewFailed = $F8C7
ScrollUpCheckTop = $E387
CardLoadDir = $EE19
ASLA3 = $EB8E
CheckCardFormat = $F745
RESET = $E441
CardNotBusy = $E59D
CardLoadDirSectorInc = $F0FB
CardReady = $E5C2
ScrollUpCheckMiddle = $E3AE
NextClusterSectorNum = $EC25
MESSAGETABLE = $E000
ASLA4 = $EB89
DoYScroll = $E305
CardLoadDirCheckEx2Loop = $EFA8
NOCARD = $E042
CheckCardFormatFail = $F7C8
CardLoadDirCheckShortName = $EF4D
Long2Str = $E95F
CardCopyRootDirEntries16 = $E6A9
Long2Str2 = $E97B
CardReadBytesLoop = $ED7C
ScrollDownCheckBottomDone = $E426
STARTG = $E182
LoadGameGenieLoop = $F66D
SetScroll = $E2B7
DirPrintDir32Check = $F356
ClearFindEntryLoop = $E855
LOADRAM = $E122
LoadCHRRamDone = $F59A
CardLoadModule = $F16C
NMI = $E283
Long2Str3 = $E993
LoadNextSectorNum = $ECB7
GameGenieEncodeBadJump = $EAA4
LoadPRGRamDone = $F487
ClearRam = $F714
DirFindEntryNewCharLoop = $F898
CardLoadDirLongNameLoop4FF = $EF45
ClusterToLBA = $EB96
CardCopyRootDirCluster32 = $E670
DirPrintDirFileCheck = $F35D
Long2Str4 = $E9AF
DoFrame = $E2DF
NewCFNotBusy = $F97E
CardLoadDirCheckEx1Loop = $EF8D
CardSectorError = $ED11
PrintLine = $E85E
ScrollUpDone = $E3BF
FindCardPartition = $F7E1
ClusterToLBALoop = $EBC8
GameGenie6Encode = $EAE7
Byte2Str2 = $EA17
CopyChrRam = $E8FF
FORMAT = $E082
LoadWRam = $F488
CardReset = $E559
CardReadSector16Loop = $EDA0
CardLoadDirCheckEx1 = $EF89
NewCFReset = $F907
LoadFPGASector = $F63E
LoadPRGRam = $F408
HEADER = $E1C2
Byte2Str3 = $EA2F
LoadNextClusterNum = $ECE7
GameGenieEncodeBad = $EA30
LoadCHRRam = $F51F
CardFormatCheckLoop = $F7F3
CardLoadDirLastEntryFoundJmp = $F0F8
CardLoadDirCheckEx2 = $EFA4
MemCopy = $E949
LoadLogoPaletteLoop1 = $E8DA
DirFindEntryNewLoop = $F893
CardReadSector496ChrLoopDone = $F5FE
LOGO1 = $E242
CardCopySectorsPerFat = $E663
LoadPrgChrSizeChrRam = $F6D4
CardLoadDirCheckEx3 = $EFBF
DirFindEntryNext = $F2F1
DirGetEntry = $F2A4
CursorDone = $E2FD
NewCFReady = $F983
CardReadSector496Loop = $EDC0
ClearRamLoop = $F718
LOGO2 = $E24A
FPGACopyRomLoop0 = $F3B7
CardLoadDirClearTempEntryLoop = $F078
CardWaitDataReq = $ECFD
DoYScrollOverflow = $E317
CardInserted = $E56D
LoadFPGA = $F602
ResetCopyFPGA = $E478
RenderingOn = $F6E1
CardLoadDirLongNameLoop1FF = $EF09
LOGO3 = $E252
FPGACopyRomLoop1 = $F3D8
CardLoadDirNextSector = $F09B
ClearNameTableLoop = $E824
NewCFDone = $F9B8
MoveSprite = $E291
CardLoadDirLongName1 = $EEEF
CardLoadDirNextEntry = $F080
ResetFPGANotConfigured = $E470
JoystickRead = $E7F3
.endscope
Variables/other stuff:
Code:
; The contents of this file were taken directly from variables.h of PowerPak
; firmware source code (added ca65isms).
.struct PowerPakVars
sourceLo .res 1 ;must be 0 page
sourceHi .res 1 ;must be 0 page
destLo .res 1 ;must be 0 page
destHi .res 1 ;must be 0 page
sourceStrLo .res 1 ;must be 0 page
sourceStrHi .res 1 ;must be 0 page
sourceEntryLo .res 1 ;must be 0 page
sourceEntryHi .res 1 ;must be 0 page
destEntryLo .res 1 ;must be 0 page
destEntryHi .res 1 ;must be 0 page
printAddrLo .res 1 ;must be 0 page
printAddrHi .res 1 ;must be 0 page
tempEntry .res 34
destBank .res 1
cursorX .res 1
cursorY .res 1
scrollY .res 1
scrollYCounter .res 1
scrollYUp .res 1
scrollYDown .res 1
cursorYCounter .res 1
cursorYUp .res 1
cursorYDown .res 1
speedCounter .res 1
speedScroll .res 1
printY .res 1
spriteNum .res 1
partitionLBABegin .res 4 ;sector number of beginning of partition
fatBeginLBA .res 4 ;sector number of beginning of fat table
clusterBeginLBA .res 4 ;sector number of beginning of data, cluster #2
sectorsPerCluster .res 1 ;number of sectors per cluster (8 sectors for 4KB cluster)
rootDirCluster .res 4 ;cluster number of root directory, 0 for fat16
baseDirCluster .res 4 ;cluster number of POWERPAK directory
sectorsPerFat .res 4 ;number of sectors in each fat, 2 fats assumed
reservedSectors .res 2 ;number of reserved sectors
sectorCounter .res 2
sourceCluster .res 4
sourceSector .res 4
fat32Enabled .res 1
fat16RootSectors .res 2 ;number of sectors in the root dir, (root dir entries * 32) / 512 bytes
prevFrameCounter .res 1
frameCounter .res 1
joystick .res 1
findEntry .res 11
exMatch1 .res 4
exMatch2 .res 4
exMatch3 .res 4
selectedEntry .res 2
filesInDir .res 2
lfnFound .res 1
printString .res 34
temp .res 4
source256 .res 1
sourceBytes .res 1
gameName .res 32
saveName .res 32
mapperData .res 16
gameCluster .res 4
wramCluster .res 4
mapperCluster .res 4
prgSize .res 1 ;how many 16KB banks
chrSize .res 1 ;how many 8KB banks
mapperNumber .res 1 ;mapper number in hex
mirroring .res 1 ;0x0=horiz, 0x1=vert, 0x8=four
mapperModule .res 2
powerOn .res 1
useBattery .res 1 ;00=no battery, 01=use battery must save wram
wramBanks .res 1 ;0=1x8KB bank, 2/4 others expected
gameGenie .res 40 ;5x8 chars
gameGenieOffset .res 1
gameGenieCodes .res 40 ;8 bytes x 5 codes addresslo, addresshi, newdata, comparedata, enable8, junk, junk, junk
arcadeDip .res 1
moduleReady .res 1
bankCounter .res 1
romVers .res 3
;;added in 1.33
oldButtons .res 1
heldButtons .res 1
scrollHoldTimer .res 1
searchEntry .res 34
.endstruct
.enum PowerPakConsts
messagePP = $00
messageNOCARD = $01
messageNOTREADY = $02
messageBADFORMAT = $03
messageREADERR = $04
messageWRITEERR = $05
messageNOTFOUND = $06
messageLOADDIR = $07
messageLOADRAM = $08
messageGG = $09
messageWEBSITE = $0A
messageSTARTGAME = $0B
messageLOADGAME = $0C
messageBADHEADER = $0D
messageDISKDUDE = $0E
messageSAVINGRAM = $0F
messageCARDBUSY = $10
.endenum
.scope PowerPakRegs
;variables = $0000-00FF 256 bytes
;stack = $0100-01FF 256 bytes
;sector = $0200-0400 512 bytes
;modules = $0400-0800 1024 bytes 0400 = module start vector 0404 = controller vector
;******************
;5xxx range
;(/ce=1 nand A14=1)=0 booten=1 a13=0 a12=1(sel) a11=sel a10=sel
;remove boot/en invert
;mapper /wr = prg/ce=clk (exp0=1 nand)or r/w=0 = /load
;0100 xxxx = $4xxx = do not use
;0101 0000 = $50xx = card /rd
;0101 0100 = $54xx = card /wr
;0101 1000 = $58xx = /program
;0101 1100 = $5Cxx = fpga /cs
;*******************
FPGADATA = $5C00
FPGAPROGRAM = $5800
MAPPERWR = $8000 ;;switch bank here
PRGBANK = $4200 ; registers in the loader fpga config
CHRBANK = $4201
PRGSIZEWR = $4200
CHRSIZEWR = $4201
MIRRORINGWR = $4202
ARCADEWR = $4203 ;;used for WRAM size
GAMEGENIEWR = $4204
BOOTENWR = $4207
FPGAREAD = $4208
FPGAREADLO = $08
FPGAREADHI = $42
;********************; pdf p113
; CF A10 A3 A2 A1 A0 /REG
; NES gnd A3 A2 A1 A0 vcc
;
; data read 0 0 0 0 xxx0
; error 0 0 0 1 xxx1
; status 0 1 1 1 xxx7
;
; data write 0 0 0 0 xxx0
; sector count 0 0 1 0 xxx2
; lba 0 0 0 1 1 xxx3
; lba 1 0 1 0 0 xxx4
; lba 2 0 1 0 1 xxx5
; lba 3 0 1 1 0 xxx6
; command 0 1 1 1 xxx7
; device 1 1 1 0 xxxE
;
;*********************;
CARDDATAREAD = $5000
CARDERROR = $5001
CARDSTATUS = $50F7
CARDDATAWRITE = $5400
CARDSECTORCOUNT = $5402
CARDLBA0 = $5403
CARDLBA1 = $5404
CARDLBA2 = $5405
CARDLBA3 = $5406
CARDCOMMAND = $5407
CARDDEVICE = $540E
.endscope
rainwarrior wrote:
Thanks for the info, thefox.
An additional thing that source might help is to be able to send you additions/patches for PowerMappers. We're already in kind of a horrible situation where a lot of people have 3 layers of mappers installed on top of each other, I'd hate to be creating yet another mapper repository overlay. :S (Of course... this particular problem could be better solved by bunnyboy.)
My preferred recipe has four layers plus : official, beta, loopy, power, then a few cherry picked individual ones, including from the save state mappers :
http://nerdlypleasures.blogspot.com/201 ... apper.html
Perhaps we should take general discussion of using and creating PowerPak mappers out of the topic about thefox's particular set?
edit: Also, Loopy already seems to have included an NSF player in with his mapper pack.
Hey silly question here, but where do we put the slot files? Do they go into the directory with the ROMs?
kruuth wrote:
Hey silly question here, but where do we put the slot files? Do they go into the directory with the ROMs?
You can put them anywhere you want.
Right now they're in a root directory called SLOTS but I don't seem to have the ability to save with them. The option isn't available. Am I missing something?
Do you mean "the save-/loadstate options are greyed out"? then…
You have to pick your slot file from the menu after you pick your ROM, before you boot the game. Unlike the built-in SRAM chooser, the [game-genie-code-entry] screen will not update to reflect that you have chosen one and display its name.
If you mean "the menu does not offer me the chance to save after I hold RESET (as one would using the pack-in SRAM saver)" then I suggest saving a state before you quit, and using that to hold your progress.
Aha. That makes sense then. I found it...wasn't looking. My bad.
I'm having an odd issue with these mappers when using an RGB-Modded AV Famicom with an adapter (the exact one from
this thread).
When I save and then load a state I'll see some pretty gnarly glitches in gameplay and sometimes on the menu, like this


^^ This will sometimes happen if I load a state directly from the menu.
When I use the default official or beta drivers the game runs smoothly. I've also tried stacked mappers (official, beta, loopy, power) with no luck.
Since the mappers work perfectly on an NES I'm leaning towards the issue being the 72-pin to 60-pin adapter, but the recommended fixes I've tried (resistors on certain pins, mmc5 and exp audio fix, copper tape) don't resolve this issue. Is there anything else I can try?
I have no idea what could be causing that, sorry.
Do you see that Ninja Gaiden glitch even if you don't save/load?
My immediate reaction was that maybe CF reads/writes aren't working properly, but it's unlikely to be the issue if it works perfectly on another system.
thefox wrote:
I have no idea what could be causing that, sorry.
Do you see that Ninja Gaiden glitch even if you don't save/load?
My immediate reaction was that maybe CF reads/writes aren't working properly, but it's unlikely to be the issue if it works perfectly on another system.
Thanks for the reply!
It's not just Ninja Gaiden. It's practically any game where I try to save/load.
I'll be doing some troubleshooting later this week, as I'm still leaning towards the adapter. I have a friend who has a non-RGB modded AV Famicom and I'll be testing it out on his to see what happens.
I installed these mappers and now when I try to play SMB1, it tries to start at World 0-1 instead of World 1-1
When I use mappers v1.12, v1.34 or Loopy's mappers, it loads fine. But once I install the power mappers it goes to 0-1
Are you using a dump of an authentic copy of Super Mario Bros. or a bootleg extracted from a multicart? One of the common bootlegs is hacked to expect the multicart menu to pass it a world number, and you may get 0-1 if it isn't set properly.
tepples wrote:
Are you using a dump of an authentic copy of Super Mario Bros. or a bootleg extracted from a multicart? One of the common bootlegs is hacked to expect the multicart menu to pass it a world number, and you may get 0-1 if it isn't set properly.
Hmm maybe that was the problem.. I got the powerpak second hand and the games were already loaded onto the flash card. I tried a different rom I had on my hard drive and that seems to work... though it's still pretty odd that all the old versions of the mappers worked with the original copy. I figured it was unlikely that the NROM mapper had any errors since it's the most basic one
Since the starting level in the hacked ROM is defined by the contents of RAM, the PowerPak menu is probably leaving different values in RAM depending on the mapper it loads. Are the mapper files temporarily stored in RAM when they're loaded into the FPGA?
Yeah, I was going to say, the PowerPak menuing system has gotta be at least partially responsible for this. Details:
https://wiki.nesdev.com/w/index.php/PowerPak_MenuIt isn't the first time this has come up/affected something. It's pseudo-documented:
https://wiki.nesdev.com/w/index.php/Pow ... imitationsIt's one of the downsides to a menuing system that runs natively on the NES itself. I don't know the actual hardware specs for the PowerPak other than it's an FPGA, but honestly if the hardware was capable of it, it should really copy (back up) the contents of NES RAM to somewhere on the cart itself, then immediately before switching control over to a loaded ROM, restore NES RAM contents so that it's consistent.
I wouldn't be surprised if the copy of Super Mario Bros pre-loaded on frantik's PowerPak was some unofficial version (do you know how many versions of this game there are? It's literally crazy) that did something slightly different, utilising said RAM.
koitsu wrote:
it should really copy (back up) the contents of NES RAM to somewhere on the cart itself, then immediately before switching control over to a loaded ROM, restore NES RAM contents so that it's consistent.
I don't think this would be of much help to anyone, because even if the power up state of RAM is preserved, the rest of the state (CPU and PPU) is still gonna be destroyed. There have been a few cases of games that don't wait for the PPU to warm up running on the PowerPak but failing on standalone cartridges, so unless the devcart is able to retain the ROM contents and mapper configuration during a power cycle, it'll remain unreliable for testing boot up procedures.
I'm not sure I follow...
My concern isn't about "restoring RAM contents" on a power-cycle of the PowerPak; that would be roughly the equivalent to a save state. I'm not talking about that or anything close to that.
My concern is that the PowerPak's menuing system utilises RAM and ZP, which are then "tainted" prior to a ROM load+run. If a game -- there are several known (I think you and I both have been in threads discussing such) -- uses said RAM or ZP locations, it can end up misbehaving (compared to if the PowerPak wasn't involved (real game/cartridge used)). Thus, if the PowerPak had the ability to temporarily back up RAM and ZP somewhere **prior** to the menuing system being loaded, then later restore RAM/ZP immediately prior to ROM load+run, would it not solve this problem?
As for CPU and PPU state (of power-on and reset), those are known, but I don't understand how those would be relevant. Generally speaking almost all games operate off the assumption that several CPU flags, and the PPU state, is "effectively unknown" on reset/power-on, so they set them up themselves. Anyway, here's the known details (I believe blargg did most of the heavy lifting):
https://wiki.nesdev.com/w/index.php/CPU_power_up_statehttps://wiki.nesdev.com/w/index.php/PPU_power_up_state
Power-on RAM isn't really that reliable anyway. The only thing saving and restoring that would do is replicate its inconsistent behaviour, which is true to life at least.
...but all it would mean in this case is the hacked SMB will sometimes start up in different worlds.
The PowerPak loaders, on the other hand, leave it in some
consistent, but not intentionally designed state (and part of that state might have to do with filenames and directory structure and other junk specific to your system).
I'm not really sure which is better.

It could also just initialize RAM to 00 or FF, but I don't know if that's particularly helpful either. It would probably make testing more consistent from system to system using the same PowerPak, at least? (Neither 00 nor FF will "work" with every game, depending on what you want to run, but the same is true for a system that has SRAM that powers up with an 00 or FF tendency. One or the other breaks.)
Could also use a RNG to initialize it, if you really want something that's inconsistent and might have a chance of flushing unwanted behaviours. While I think this is a good option for dev testing, I think it's actually a terrible option for general users.
koitsu wrote:
My concern isn't about "restoring RAM contents" on a power-cycle of the PowerPak; that would be roughly the equivalent to a save state. I'm not talking about that or anything close to that.
That's not what I meant. The power cycle I mentioned was meant to provide programs with a clean boot state, but that'd only be possible if the PowerPak could retain the previously loaded ROM and mapper configuration. It'd could then give control to the loaded ROM immediately on power on, without running menu software, accessing the CF card or configuring the FPGA. The PowerPak can't do this, of course.
Quote:
As for CPU and PPU state (of power-on and reset), those are known
Knowing them doesn't necessarily mean you can recreate them, like you can with the RAM. Like I mentioned before, the PPU has a boot up period, if you try to use certain registers or VRAM before the PPU is ready, it won't work correctly. This is why games are supposed to wait 2 or so frames before doing any PPU operations. When the PowerPak transfers control to the game, this warm-up period is long gone, so even games without wait loops will work fine, but will fail once they're put on standalone cartridges.
Quote:
but I don't understand how those would be relevant.
The PPU warm-up period is very relevant. As far as games running on the PowerPak are concerned, this period doesn't exist, and that may result in games with improper initialization routines.
rainwarrior wrote:
Power-on RAM isn't really that reliable anyway. The only thing saving and restoring that would do is replicate its inconsistent behaviour, which is true to life at least.
...but all it would mean in this case is the hacked SMB will sometimes start up in different worlds.
Right, and that's primarily my point (re: your first paragraph). I really don't see a downside, if it's possible. Do you?
Of course, if this can't be done with the PowerPak, then it's completely moot for me to even bring up (and then I'll feel like I was wasting everyone's time). All I know is that the Xilinx FPGA does in fact have some on-board or on-die RAM, since the PowerPak is advertised as having "extra graphics ram for four screen games and MMC5 exram". NES ZP/RAM is 2KBytes, and RAM for 4-screen games tends to be 2KBytes; MMC5 ExRAM is only 1KB. I don't know if the FPGA RAM for 4-screen games could temporarily be used as a storage buffer for (a copy of) NES ZP/RAM on power-on or not. I don't do FPGA stuff, nor do I have familiarity with the system.
rainwarrior wrote:
It could also just initialize RAM to 00 or FF, but I don't know if that's particularly helpful either. It would probably make testing more consistent from system to system using the same PowerPak, at least? (Neither 00 nor FF will "work" with every game, depending on what you want to run, but the same is true for a system that has SRAM that powers up with an 00 or FF tendency. One or the other breaks.)
The
list of games that rely on ZP/RAM contents is always helpful. In general, for most it seems $00 (for all of ZP and RAM) is a good default, but not always. For others, $FF might seem like a good value, but not always. I think most notable are games that use ZP or RAM contents as a kind of "RNG seed".
It's remarkable how often this subject keeps coming up on the forum especially in recent days. Between the F-1 Race ordeal, then a discussion about Who Framed Roger Rabbit, and now this...
@tokumaru -- Okay, PPU warm-up period is a valid one. But the crux of what's getting discussed these days is ZP/RAM contents not "being true" to what the underlying hardware has on power-on (i.e. without a PowerPak involved). I'm focused on that since it's the subject that's bitten frantik and might be solvable.
PowerMappers clear most of the RAM (including PPU memories) to $FF before starting the game, that would explain the problem with the bad SMB ROM.
I loaded up the rom into FECUXD and it also showed world 0-1. It looks like on the title screen the rom tries to load a value from $013E, which, if it's any value besides $5A, gets copied over into the memory address for the current world, which is offset by 1.. $00 means world 1, and $FF means world 0. FECUXD appears to set memory on power up in chunks of $00 and $FF, and it just happens $013E ends up as $FF, so it displays world 0-1. The game never initializes this area of memory. If you manually change $013E it to $00 then it loads world 1-1.
So what I'm guessing is happening is that the old mappers reset memory to $00 and the power mapper resets it to $FF (actually it looks like thefox confirmed this as I was typing this post). This ROM probably was the kind ripped from a multicart as tepples mentioned.. the file date is from 1996 so who knows. This does explain why the world select feature after beating the game never worked right though!
frantik wrote:
So what I'm guessing is happening is that the old mappers reset memory to $00
Old mappers don't touch the memory at all, the contents are whatever happened to be left there by the menu.
frantik wrote:
I loaded up the rom into FECUXD and it also showed world 0-1. It looks like on the title screen the rom tries to load a value from $013E, which, if it's any value besides $5A, gets copied over into the memory address for the current world, which is offset by 1.. $00 means world 1, and $FF means world 0. FECUXD appears to set memory on power up in chunks of $00 and $FF, and it just happens $013E ends up as $FF, so it displays world 0-1. ...
rainwarrior described about 1.5 years ago what FCEUX does in its code:
viewtopic.php?p=178159#p178159 . It also prompted him to send in a patch to allow the user to select what the behaviour should be:
viewtopic.php?p=178170#p178170 . This isn't in FCEUX 2.2.3, but should be in the next version when it comes out (under Config -> RAM Init).
You can read the entire 7-page thread for interesting information all pertaining to this exact type of problem, and some others.
koitsu wrote:
Of course, if this can't be done with the PowerPak, then it's completely moot for me to even bring up (and then I'll feel like I was wasting everyone's time). All I know is that the Xilinx FPGA does in fact have some on-board or on-die RAM, since the PowerPak is advertised as having "extra graphics ram for four screen games and MMC5 exram". NES ZP/RAM is 2KBytes, and RAM for 4-screen games tends to be 2KBytes; MMC5 ExRAM is only 1KB. I don't know if the FPGA RAM for 4-screen games could temporarily be used as a storage buffer for (a copy of) NES ZP/RAM on power-on or not. I don't do FPGA stuff, nor do I have familiarity with the system.
AFAIK you don't want to look at the FPGA here. It'll be uninitialized (i.e. useless) at power-on. You want to look at the BIOS code that runs at boot, and whether or not it has any ability to map the onboard RAM before the FPGA gets set up. If that RAM is inaccessible before the FPGA is programmed, you might be SOL.
Though, at the same time the FGPA setup RAM usage requirement might be very low. You could probably compromise with only a few bytes clobbered (or even store them in PPU memory if it's less important).
Though IMO, my own experience with the memory test is that the power on values of RAM aren't useful, at least on my machines. Any decent RNG would be an OK substitute, but like I feel about emulators a wipe is a better default option for non dev testing purposes.
rainwarrior wrote:
koitsu wrote:
Of course, if this can't be done with the PowerPak, then it's completely moot for me to even bring up (and then I'll feel like I was wasting everyone's time). All I know is that the Xilinx FPGA does in fact have some on-board or on-die RAM, since the PowerPak is advertised as having "extra graphics ram for four screen games and MMC5 exram". NES ZP/RAM is 2KBytes, and RAM for 4-screen games tends to be 2KBytes; MMC5 ExRAM is only 1KB. I don't know if the FPGA RAM for 4-screen games could temporarily be used as a storage buffer for (a copy of) NES ZP/RAM on power-on or not. I don't do FPGA stuff, nor do I have familiarity with the system.
AFAIK you don't want to look at the FPGA here. It'll be uninitialized (i.e. useless) at power-on. You want to look at the BIOS code that runs at boot, and whether or not it has any ability to map the onboard RAM before the FPGA gets set up. If that RAM is inaccessible before the FPGA is programmed, you might be SOL.
FPGA takes care of mapping that RAM so it's not accessible before it has been programmed. However, the FPGA can be programmed simply by copying a bunch of bytes from the BIOS ROM to the FPGA configuration register and in fact the default BIOS does this as one of the very first things at bootup. Unfortunately IIRC the BIOS ROM is not self-flashable (unlike it's on SNES PowerPak), so replacing it is not so easy. By replacing the BIOS ROM it should be possible to back up the initial RAM contents to the FPGA's on-chip RAM or one of the 512 KiB RAMs used for PRG/CHR, but it's a lot of work for very little gain.
Okay, then we'll consider the matter closed.
Well, the alternative of simulating it with an RNG from the loader is still quite viable. Or wiping it, as the power mappers are apparently already doing.