I am trying to find someone who is capable of creating a rom, for use with a flash cart, that would read the default memory values of an NES, since these can vary with Front Loaders. Of course I am assuming to use it on an NES that has reliable memory. I say Front Loaders because it is my understanding that all Top Loaders use a repeating pattern of 00 00 00 00 FF FF FF FF, setting values to 0 or 255 every four addresses, such as the FCEUX emulator does.
I am also interested in finding someone who can write a lua script for me that would set the default memory values in FCEUX to anything I would like so that I can set the emulator to what I find on the memory testing rom. This way I can actually TAS out variations for input manipulation with games that do not have initialized memory that would actually work with my system. I would be willing to pay money for someone to create both of these for me, let me know if you or someone else you know are capable and in need of some extra cash.
Additionally, I am curious to know if flash carts such as Everdrive or Powerpak utilize the default values of the NES it is used with or if these flash carts populate these addresses with their own default values?
Any thoughts or ideas are also appreciated since I am too new to this field to know exactly how I should be asking these questions.
The default memory state is
#1 - a function of the specific manufacturer/part number/manufacturing run of RAM ICs used in the console
#2 - somewhat random anyway.
For example, the Sharp-manufactured LH5116s (made late 1988) in my NES power up with mostly FF, but there are many locations in memory that don't.
I think the idea of this project is to characterize common properties of "the specific manufacturer/part number/manufacturing run of RAM ICs used in the console", including any pattern tendencies and how much entropy there is. This way, a tool-assisted speedrunner can determine whether inconsistent behavior when attempting to console-verify a movie is due to unspecified values that a game reads before the first write to a given location.
The PowerPak and EverDrive menus absolutely do overwrite RAM with the menu code. This means a test would have to run on a single-game cartridge. And in order to view both the 2K CPU memory and the 2K nametable memory, it'd need to have at least 2K or so of its own RAM to receive data copied from the first nametable and beginning of CPU memory so that the displayer can display it. This can be WRAM at $6000 or CHR RAM at $0000.
So which board did you want it for? A CHR RAM board, such as UNROM, ANROM/AOROM, or SGROM/SNROM? Or a CHR ROM board with WRAM, such as SKROM, TSROM/TKROM, or JSROM/BTR? Boards without any RAM, such as NROM, CNROM, SLROM, and TLROM, are out of the question.
An alternative that can get away without the 4K of its own memory is something like TapeDump, which beeps out the initial contents of memory without needing video display.
My point is that
there are no reliable common properties. There are groups of different RAMs used on different consoles, and we already know that they sometimes completely contradict each other.
The last time this came up I linked to
this article about RAM randomness.
We don't have to re-sample things. We can take advantage of observing the sets of games that fail to initialize memory and already rely on the hardware powering up with mostly FF, or mostly 00.
The only possible correct options are:
* Bake the required default RAM state into your ROM database
* Let the user choose on a game-by-game basis
—
Anyway, I've actually already written a program that will dump the 4 KiB RAM on a NES using the controller port to transmit RS232 at 230400 baud. It requires that you have extra hardware to receive the results, though.
As far as ROMs for this, there's one at
viewtopic.php?f=22&t=11520.
Since I use an Everdrive, is there a way to determine the values that the Everdrive is using? If I can find this out then all I would need is a lua script to get FCEUX to use those default values.
I will check out this rom shortly, thanks for posting the link.
I think that the Rom worked great, most of the memory addresses are set to zero. Someone had mentioned that a Lua Script could be used to get FCEUX to set the default values to FF FF FF FF FF FF FF FF instead of 00 00 00 00 FF FF FF FF etc. Does anyone have a link to a Lua Script that I could use with FCEUX to set the default values to 00 00 00 00 00 00 00 00 , ect???
I also wrote a ROM to test this:
http://forums.nesdev.com/viewtopic.php?t=13334It's not particularly useful on PowerPak or Everdrive though, because they can't do power-on tests. Tou need to put it on its own cart.
There's no consistent startup state for a lot of machines though. Any given bit on mine might power up as either 0 or 1. There's maybe some tendencies but that's about it.
The latest interim build of FCEUX does now have 4 options now for power-on RAM state: 00 / FF pattern (default), all 00, all FF, random. You can use the hex editor to load or save any other pattern you wish, I suppose.
Most excellent! Where in FCEUX will I find these settings for different RAM states?
CLChambers00 wrote:
Most excellent! Where in FCEUX will I find these settings for different RAM states?
Get an interim build of FCEUX. You can find one at the FCEUX download page (the third option, "up-to-date"):
http://www.fceux.com/web/download.htmlIt's under Config > RAM Init
Very Nice! Found it! Going to grind out some research with it. Thanks everyone! You all contributed to my growing knowledge and tools in this regard. Cheer!
I set the values to all zero, but there must be more changed by the Everdrive because even though the ram viewer rom shows most values set to zero there must be more that the everdrive is doing that makes it not exactly the same as setting FCEUX to all zeros setting. Hmm, still wondering what else I might be able to try.
From what I recall of the Everdrive / PowerPak they end up overwriting a lot of (all?) the power-on state of RAM, and don't make any attempt to initialize it to a consistent value or anything before launching a ROM, so the actual values they start up with is probably highly dependent on various things like what files were in the same folder as the ROM you launched, etc.
I don't think that the FCEUX option to set it to all FF or any other variation works correctly, it appears to work for a few frames but then changes back to the same values gives me every time. When I set it to all FF, load the rom, and open tas editor, I should be getting the same results as Bizhawk, however, this is not the case. Maybe I am using the setting wrong or it does not work as intended. If this option does not work I would need a lua script. I see "memory.writebyte(0x1000,9)" is an example of how to rewrite one value but how would one write this to include all SET variables such that 'The BizHawk default memory can be simulated in the FCEUX Lua script by entering 0xFF for all the SET variables.'
For example, when I load NES Who Framed Roger Rabbit into Bizhawk all the FF values in the start of the hex editor change to mostly 00 on the 2nd frame, and they change to certain values. When I set FCEUX to all FF, this same region starts with FF but switches to mostly 00 on the 4th frame but then populates different values than did Bizhawk. This setting change in FCEUX does not appear to be simulating Bizhawk results as expected.
To get more specific, with NES Who Framed Roger Rabbit, the addresses 0012, 0013, 0014, 0015, 0043 are constantly changing variables every frame and are even influenced by inputs, and even though I get one set of values for these addresses with Bixhawk for the first 10 frames, I am not able to simulate these same values with FCEUX even after setting the RAM Init to all FF, load the rom, start the tas editor, and watch these addresses in the RAM. No matter what setting I choose, whether default, 00, or FF, even if for a frame or two it may appear to have used the setting, by frame 4 it all switches to the exact values it gives me every single time no matter what. So it does not appear to be working as intended because Bizhawk which defaults to all FF, gives me a set of values that I am unable to duplicate with FCEUX.
MOST games will set initial values for quite a lot of RAM within a frame or two of startup (often all RAM). In these cases whatever the emulator initialized it as is irrelevant, it's determined by the ROM not the emulator. What you see in RAM on frame 2 usually has little or nothing to do with what was in RAM at power-up.
This setting ONLY matters in games where the game accidentally (or in some cases intentionally) does not initialize some value in RAM before it reads it, but this is a relatively rare thing.
BizHawk and FCEUX could have many other emulation differences besides the power-on RAM state. Just because you have them both start with RAM with $FF doesn't mean they are the same emulator in all other respects. (Though, if you're not using the "new ppu" setting, I would recommend doing that at least, since it is a lot more accurate than the default old ppu.)
I was under the impression that Who Framed Roger Rabbit had uninitialized memory since I was able to manipulate the RNG via inputs and these manipulations did not yield the same results in Bizhawk, FCEUX, Frontloader w/ Everdrive. Who Framed Roger Rabbit is an LJN title like Nightmare on Elm Street which I know functions similarly. I was using Old PPU in FCEUX, will this yield different results by using New?
If the game initialize these values then that does not explain why Bizhawk has this occur on frame 2 and FCEUX has this occur on frame 4, or perhaps maybe that difference does not matter at all? IF more differences can exist than mere RAM Initial State, then perhaps this is more complicated than I first thought.
CLChambers00 wrote:
I was under the impression that Who Framed Roger Rabbit had uninitialized memory...
Who Framed Roger Rabbit initializes everything except the stack page:
Code:
00:8031: A9 00 LDA #$00
00:8033: AA TAX
00:8034: 95 00 STA $00,X @ $0000 = #$00
00:8036: 9D 00 02 STA $0200,X @ $0200 = #$00
00:8039: 9D 00 03 STA $0300,X @ $0300 = #$60
00:803C: 9D 00 04 STA $0400,X @ $0400 = #$36
00:803F: 9D 00 05 STA $0500,X @ $0500 = #$21
00:8042: 9D 00 06 STA $0600,X @ $0600 = #$1F
00:8045: 9D 00 07 STA $0700,X @ $0700 = #$32
00:8048: E8 INX
00:8049: D0 E9 BNE $8034
Unless the PRNG is on the stack page (which doesn't seem likely to me, from a brief inspection with the debugger), the power-on values of RAM are not going to influence it.
It
does seem to use the stack page for NMI updates (the PLA, STA $2007 technique) but it appears to fully initialize any part of the stack page it uses before reading it. So... I don't see any "unitialized RAM" bug here, at first glance.
Do you know where the PRNG seed is stored in this game?
Quote:
...since I was able to manipulate the RNG via inputs and these manipulations did not yield the same results in Bizhawk, FCEUX, Frontloader w/ Everdrive.
I was using Old PPU in FCEUX, will this yield different results by using New? ... If the game initialize these values then that does not explain why Bizhawk has this occur on frame 2 and FCEUX has this occur on frame 4, or perhaps maybe that difference does not matter at all?
IF more differences can exist than mere RAM Initial State, then perhaps this is more complicated than I first thought.
In a lot of cases the difference between emulators will be subtle/irrelevant to what you're trying to do.
RAM's power-on state, for example, isn't necessarily a factor in why the behaviour is different (and from what I mentioned above, it really shouldn't be a factor in this game).
There are a lot of things that could explain the difference between seeing something on frame 2 and frame 4. NES games normally need to wait 2 frames before they start doing anything because the PPU has a warmup cycle that you need to wait for. How that warmup state is emulated might effect this specific timing, not really in a way that would change how a game works, but it might make that initial wait last more time, so yes I think it's probable that this 2 frame difference doesn't matter in this case. It could even be something as simple as maybe BizHawk has an additional 1 or 2 frames of "reset" that comes before the first frame of CPU running, etc. I'm not really sure, but this difference isn't necessarily very meaningful.
New PPU has better emulation, and BizHawk is a more recent and more accurate emulator in general, so the new PPU setting should maybe be closer to BizHawk's, but I don't really know how different they are as emulators. I think it's just generally a good idea to use the new PPU unless trying to run an old TAS file or have a slow computer.
Lots of games have a PRNG that ticks every frame, so the very specific timing of when you press buttons can easily change the outcome. In a game that does that, unless you're using a TAS there's really no way to compare it. You wouldn't be able to get the same results every time with human input.
If you want to investigate the PRNG, the first thing I'd suggest is try to figure out where it resides in RAM, and then watch how/when it changes.
Thanks for the response. I have been observing the addresses 0012, 0013, 0014, 0015, and 0043 because they are constantly changing every frame and are even influenced by inputs. Are one of these the PRNG address you are referring to? I am not sure. But I have observed that the values in these addresses were always the same in FCEUX no matter what RAM Init State I used. But in Bizhawk, these addresses had different values. For instance,
FCEUX
Address 0043 had with Old PPU
Frame 4: Zero
Frame 5: 125
Frame 6: -40
Frame 7: -2
Frame 8: 1
Though with New PPU 0043 has 127 in frame 5, and has a 77 instead of 76 on frame 17, but a lot of the other numbers seem the same. Address 0043 can not be manipulated with inputs until frame 18.
What is interesting is that with New PPU values for addresses 0012, 0013, 0014, and 0015 are also different with new versus with Old, these start changing values at frame 16:
Values at Frame 16 with NEW:
0012 has 69
0013 has 109
0014 has -71
0015 has 55
Old PPU has:
0012 has -61
0013 has 47
0014 has -71
0015 has -22
Now let me share a little more of what I have been doing. I have been able to duplicate the same "seed" with Roger Rabbit in order to speed run the same item placements. I have been holding A from power on and press and hold start around the first opportunity to do so, and I continue to hold A and Start until the following addresses populate with values which do so within 4 frames during a deadzone transition between the title screen and the screen that show how many lives you begin with. I have been able to get the same outcome using both an Everdrive with my Frontloader, and the same Everdrive with my TopLoader. I have not yet tried an original cart which should arrive in a few days to do more testing.
Address for item spawns. These addresses populate with values as explained and remain the same unless it is an item that is replenish-able and re-spawns in another location once collected.
0657 Shoes
064B Rattle
0639 Detonator
0631 Whistle
0645 Baseball
0661 Will Piece #1
065D Will Piece #2
0663 Will Piece #3
065F Will Piece #4
When I run NEW PPU, and I use no input manipulation, and only do start for one frame on Frame #534, which is the first frame possible to start the game, the item spawns are
0657 has 41
064B has 128
0639 has 28
0631 has 21
0645 has 52
0661 has 6
065D has 2
0663 has 16
065F has 13
But with Old PPU these values are
0657 has 43
064B has 42
0639 has 22
0631 has 20
0645 has 53
0661 has 6
065D has 2
0663 has 16
065F has 12
So simply using either Old or New PPU changes the outcomes in FCEUX using the default 00 00 00 00 FF FF FF FF Ram Init State.
However, using Bizhawk gives us another set of values with same one frame input start on frame number 534.
0657 has 41
064B has 128
0639 has 28
0631 has 19
0645 has 47
0661 has 7
065D has 2
0663 has 16
065F has 13
This Bizhawk outcome is similar to NEW PPU in FCEUX except that three of the addresses are different.
So changing the initial Ram state in FCUEX does not alter the outcome, but using NEW verses Old PPU in FCEUX changes it, and Bizhawk is unlike either of these outcomes.
And the outcomes I get with my Everdrive with Top and Front Loader also differs from these three emulator outcomes. I will try an original cart with my Top and Front Loader to see if any of these three emulator outcomes match with one of these two hardware configurations. If not, then I am not sure how to force these emulators to correlate so I can TAS out variations of input manipulations that I can utilize in actual speedrun attempts.
I am curious exactly how the different PPU is causing these values to be different, and if it would be possible or a simple solution just to write a Lua Script to overwrite address 0043 with different values and then check outcomes, but I am not sure if 0043 is what I think it is, nor do I know if it would be this simple to respond to the different PPU outcomes?
So I wrote a Lua Script in order to change the 0043 address on frame 5 to what it was with Old PPU, while still using New PPU, and it continued to changed according to New PPU instead of old. I was hoping that by changing this initial value that it would progress differently but it didn't do anything at all, hmmm.
I just tried the same thing with addresses 0012, 0013, 0014, and 0015 and the same thing happened. I changed the values on one frame to what it would be for Old PPU, and when I advanced one frame I only got the New PPU results. Not sure how these numbers are being influenced or what else I might be able to try to hopefully get the emulator to play out differently. Maybe it is a single memory address but I am sure it is much deeper than that perhaps???
Is there a quick way to see what is causing the initial values in these addresses on the first frame it is changed from a zero value?
Debug >
Debugger...
There's a breakpoints panel in the top right. Click "Add"
Type in the address (or address range), check off "write", select CPU Mem.
This breakpoint will halt execution whenever it is written to and show you the code that is responsible. (You can click "Run" to resume, and in the breakpoints list you can double click one to toggle it on or off.)
I see read and execute as options to check as well, it doesn't stop if I have nothing checked though does this mean that read is when that address is read by something else, and execute is when it is used by something else? I am confused.
"Read" means the address is the operand in an instruction that reads memory, such as $0127 in LDX #$04 ADC $0123,X.
"Execute" means the address is the first byte of an instruction, such as $A060 if the first byte of ADC $0345 is at $A060.
Anyone interested in helping me determine what causes values to populate and why the values that it does in the following addresses:
0657 Shoes
064B Rattle
0639 Detonator
0631 Whistle
0645 Baseball
0661 Will Piece #1
065D Will Piece #2
0663 Will Piece #3
065F Will Piece #4
Likewise, anyone interested in helping me understand why FCEUX (Old PPU), FCEUX (New PPU), and Bizhawk all have different values for the following addresses:
0012, 0013, 0014, 0015, and 0043
What specifically is causing different values and different outcomes? And how might I change how it works so that I can TAS more states than just FCEUX (Old PPU), FCEUX (New PPU), and Bizhawk?
Any and all help would be greatly appreciated, would be willing to compensate someone's time and expertise in helping me unravel this.
addresses $43-45 appear a temporary place that A,X,Y are stored during the NMI routine. Since the A register is changing constantly in normal use, the very specific timing that NMI fires will interrupt it and store different values. (Thus old PPU or new PPU could cause very subtle differences in timings that affect what code is interrupted). The NMI only stores A most of the time, which is why you noticed only $43 changing.
I don't think the contents of $43-45 have any gameplay effects, though. They seem to be isolated for this purpose.
I have now confirmed that neither Old PPU or New PPU in FCUEX, nor Bizhawk correlate to any hardware configuration, whether Front or Top Loader with Everdrive, or Front or Top Loader with original cart. I am not able to get these emulators to correlate to the original hardware, and I am not sure if there is a way to do this. If there is a way to write in a value or two in an address that would modify how these emulators work, even if I have to try 255 values in a single address to get a correlation, I will do it, but I would need to know if a correlation is even possible.
So I have confirmed that changing the core in Bizhawk from QuickNES to NesHawk gives yet another set of values. So FCEUX(Old PPU), FCEUX(New PPU), Bizhawk(QuickNES), and Bizhawk(NesHawk) all yield different results, so four different outcomes. Once again changing the initial RAM State either in Bizhawk or FCEUX does not modify outcomes since the Rom initializes its own values. What changes this? Why such a difference between emulator outcomes? And yet none of these outcomes match original cart with Front Loader, or with Top Loader, nor use of Everdrive with Front/Top Loader. There must be a way to know why and have the ability to sync some of this. Any thoughts?
I have also confirmed that resetting the game does not retain RNG values so it is not required to power cycle the NES in order to do RNG manipulation.
I have also confirmed that it does not matter the hardware that you use. I have been able to get the same RNG manipulation for real cart with Top Loader, real cart with Front Loader, Everdrive with Top Loader, and Everdrive with Front Loader. All the outcomes are the same, just can't get any emulator with a TAS editor to sync with it.
I have concluded that the state of NES emulation is not yet sufficient in order to TAS this game. It is a personal opinion of mine that it isn't the same if the emulator is not synced with the NES, and can't be reproduced on original hardware in the same way, therefore I will not TAS it. This non-sync issue will need to be corrected in the future so that emulators can be utilized to TAS 1000's of variations of this game which would otherwise take weeks. Until that day comes...
What exactly is the test you are doing?
I had found that I can get the same item placements in the game by doing inputs to manipulate the RNG. For example, I will press and hold A then hit reset, I will continue to hold A until after the screen blacks out after hitting start. When I press start I continue to hold it with the A button until the same black out. This way all the input manipulation can be duplicated and the only thing I had to reset over and over again for was to begin pressing start on the same frame as before. I increased the world record several times using this method and since I knew where all the items were with that outcome I was able to focus on optimizing the route. So naturally I wanted to search for other routes that would be faster and focus on running that route to improve the record further. I kept a log of all the trials I ran with the TAS editor for both FCEUX(Old PPU), and FCEUX(New PPU).
https://docs.google.com/spreadsheets/d/ ... =903343879I did over 2000 trials only to find that none of the results actually correlated with original hardware. I thought maybe the memory was not initialized and therefore impacted by the Initial Ram State, but neither of these were the case. It seems that the state of NES emulation is not yet accurate enough in order to produce the same results as original hardware. I have been able to reproduce the same outcomes with original cart/Top Loader, original cart/Front Loader, Everdrive with both. All of these hardware configurations all yielded the same results. It baffles me why I can get four different results from the emulators: Bixhawk(quickNes), Bizhawk(NesHawk), FCEUX(Old PPU), and FCEUX(New PPU). None of these yielded the same results as the other,s and none of them especially did not sync with original hardware.
The plan was to TAS 1000's of variations of input manipulation that I could duplicate in real time and watch the item address values. I found a route that was 19 seconds faster and it would have been nice to actually use the input manipulation in order to achieve it with original hardware. I was able to observe outcomes for each trial within 10 seconds and it was incredibly expedient. As you can tell from the spreadsheet it was very rare for me to find an outcome that would have been a faster route than what I discovered by luck by simple trial and error with my console. I would have TASed the outcome I received from my input manipulation with original hardware but once again I am not able to force the emulator to simulate original hardware.
I was able to drive the world record down to 4:36 with my discovery:
https://www.twitch.tv/videos/160313557I am hoping that maybe I can force one of these emulators to produce the same outcomes by maybe writing a Lua script to change a value or two in some important address that influences the course of the process. I am sure through a process of trial and error I would be able to produce the same results with the input manipulation I do with original hardware. But I am not sure it is really that simple, or if the issue is much more complicated and not easily solved, even where to begin. I spent some time with the debugger but I was not able to make sense out of what I observed, and then concluded that maybe the state of NES emulation is not yet perfected and there is nothing that I can do until it improves. That is to say that perhaps the matter is simply beyond both present software limitations and my lack of knowledge in this area.
Can you give step by step instructions about the test, though? You started to explain about holding A etc. but what is the result? What do you do in the game to see that the PRNG has been set to something specific?
Certainly. I have been holding A from power on and press and hold start around the first opportunity to do so, and I continue to hold A and Start until the following addresses populate with values which do so within 4 frames during a dead zone transition between the title screen and the screen that show how many lives you begin with. If I began to press start on the right frame I will get the following results. I can not say exactly what the frame is when I press start because it is on console, but when I check for the same outcome in any of the 4 emulator configurations I obtain results from the first 20 available frames to find a match, which has not occurred.
0657 has 40
064B has 42
0639 has 29
0631 has 21
0645 has 53
0661 has 6
065D has 2
0663 has 16
065F has 13
I use the TASeditor to apply the inputs and I see what the result is in these addresses. That is exactly what I am doing.
I have noticed that the values in addresses 0012, 0013, 0014, and 0015 differ between emulator configurations, meaning Bizhawk(quickNes), BizHawk(NesHawk), FCUEX(Old PPU), FCEUX(New PPU). I am not sure what PRNG is, nor where have I found a way that I understand to dig deeper.
So basically I use the Taseditor to replicate my input manipulation and watch the results from initializing my start input from frame 1 to 20 of first opportunity which is around frame 534.
What about on hardware though? Specifically I wanted to know how you test the result of the PRNG in the game (not to do with memory values you see in a debugger).
So...
1. Hold A from power on.
2. Press and hold Start when the "PRESS START" thing has finished fading in.
I'm unclear on what to do next. Eventually the game begins, and I'm in a room and I can punch Roger. Where do I go, what do I do to see the statue of the PRNG?
Here, I'll try and go through the steps of how I'd look into this using FCEUX. You mentioned that the memory address $0657 holds some randomly generated value for "shoes". Let's look at that...
Step 1: Go to Tools > RAM Watch and add an entry for 0657 so wee can look at it as the game is running.
Step 2: Start the game and play it until it changes. Here I notice it happens when leaving the "PRESS START" screen.
Step 3: Go back to before it changed (by resetting or with a savestate, etc.) and try to get close to the point where it is about to change and pause the emulator.
Step 4: Go to Debug > Trace Logger, select Log to File and click browse to create a file. Start Logging.
Step 5: Go to Debug > Debugger and add a breakpoint on writes to 0657, this is going to automatically pause when it gets written to.
Step 6: Click Run in the debugger, or otherwise unpause. Execution will proceed slowly (the trace is writing everything that's happening to a file), and it will eventually automatically pause when $0657 is written to. Once it pauses click "Step Into" once just to finish the instruction that actually writes $0657.
Step 7: Stop logging in the trace. Open the file you created and go to the bottom. Here's the last two instructions:
Code:
]A:00 X:28 Y:00 S:F8 P:nVUbdIZC $9928: A5 06 LDA $0006 = #$29
Breakpoint 0 Hit at $992A: $0657:EC-W--
A:29 X:28 Y:00 S:F8 P:nVUbdIzC $992A: 9D 2F 06 STA $062F,X @ $0657 = #$00
So we see here that a value $29 is loaded from $0006 and written to $0657. We want to find out where that value came from...
Step 8: Use a text search tool to search backwards for "0006" from that line until you find a write to $0006.
This ends up taking a little while because there's a long repetitive series of this loop:
Code:
A:00 X:28 Y:88 S:F8 P:NVUbdIzC $9916: B9 2E 06 LDA $062E,Y @ $06B6 = #$00
A:00 X:28 Y:88 S:F8 P:nVUbdIZC $9919: 30 07 BMI $9922
A:00 X:28 Y:88 S:F8 P:nVUbdIZC $991B: B9 2F 06 LDA $062F,Y @ $06B7 = #$00
A:00 X:28 Y:88 S:F8 P:nVUbdIZC $991E: C5 06 CMP $0006 = #$29
A:00 X:28 Y:88 S:F8 P:NVUbdIzc $9920: F0 BF BEQ $98E1
A:00 X:28 Y:88 S:F8 P:NVUbdIzc $9922: C8 INY
A:00 X:28 Y:89 S:F8 P:NVUbdIzc $9923: C8 INY
A:00 X:28 Y:8A S:F8 P:NVUbdIzc $9924: C4 50 CPY $0050 = #$00
A:00 X:28 Y:8A S:F8 P:NVUbdIzC $9926: D0 EE BNE $9916
It seems to look at a list of previously generated values and compare against it. You said this number determines the location of the shoes, right? Well, this is probably trying to make sure it doesn't put 2 objects in the same location.
Step 9: Here we see that $0006 comes from a series of 2 table lookups (i guess some kind of "location" table), but those lookups are determined by a combination of $0012 and $0005. Next to find out how those two values were filled... keep searching backwards!
Code:
A:54 X:28 Y:00 S:F8 P:nVUbdIZc $9900: A5 12 LDA $0012 = #$45
A:45 X:28 Y:00 S:F8 P:nVUbdIzc $9902: 29 03 AND #$03
A:01 X:28 Y:00 S:F8 P:nVUbdIzc $9904: 05 05 ORA $0005 = #$54
A:55 X:28 Y:00 S:F8 P:nVUbdIzc $9906: A8 TAY
A:55 X:28 Y:55 S:F8 P:nVUbdIzc $9907: B9 AB E7 LDA $E7AB,Y @ $E800 = #$33
A:33 X:28 Y:55 S:F8 P:nVUbdIzc $990A: A8 TAY
A:33 X:28 Y:33 S:F8 P:nVUbdIzc $990B: B9 23 E8 LDA $E823,Y @ $E856 = #$29
A:29 X:28 Y:33 S:F8 P:nVUbdIzc $990E: C5 FA CMP $00FA = #$FF
A:29 X:28 Y:33 S:F8 P:nVUbdIzc $9910: F0 CF BEQ $98E1
A:29 X:28 Y:33 S:F8 P:nVUbdIzc $9912: 85 06 STA $0006 = #$15
Step 10: A little futher back we see that $0005 is actually just the value from $0004 but times 4. So now we have to keep searching for $0004 instead. In the same place we also find where $0012 came from, and this looks like our main PRNG step, maybe?
Code:
A:80 X:28 Y:2A S:F8 P:NVUbdIzc $98E6: A5 12 LDA $0012 = #$A1
A:A1 X:28 Y:2A S:F8 P:NVUbdIzc $98E8: 45 13 EOR $0013 = #$87
A:26 X:28 Y:2A S:F8 P:nVUbdIzc $98EA: 65 14 ADC $0014 = #$1F
A:45 X:28 Y:2A S:F8 P:nvUbdIzc $98EC: 85 12 STA $0012 = #$A1
A:45 X:28 Y:2A S:F8 P:nvUbdIzc $98EE: 45 13 EOR $0013 = #$87
A:C2 X:28 Y:2A S:F8 P:NvUbdIzc $98F0: 85 13 STA $0013 = #$87
A:C2 X:28 Y:2A S:F8 P:NvUbdIzc $98F2: E5 02 SBC $0002 = #$68
A:59 X:28 Y:2A S:F8 P:nVUbdIzC $98F4: 85 14 STA $0014 = #$1F
A:59 X:28 Y:2A S:F8 P:nVUbdIzC $98F6: A5 04 LDA $0004 = #$15
A:15 X:28 Y:2A S:F8 P:nVUbdIzC $98F8: 0A ASL
A:2A X:28 Y:2A S:F8 P:nVUbdIzc $98F9: 0A ASL
A:54 X:28 Y:2A S:F8 P:nVUbdIzc $98FA: 85 05 STA $0005 = #$50
$0012-0014 seem to be part of a 24-bit PRNG seed, though now there's also a value from $0002 that seems to be involved. If I keep searching back from here, I just see iterations of this same step for $0012-0014. My trace log doesn't seem to go far enough back to figure out how they were initially set up, but that's fine, we have identified that they were important for setting up $0657 and we can begin a new investigation from here.
Similarly the determination for $0002 is not immediately clear from the trace log I have saved, but it's something we can now dig into.
Step 11: Add $0002, $0012-0014 to the ram watch again. I notice that they're changing all the time. $0002 in particular is increasing by 1 each frame. Putting a breakpoint on writes to it, I notice that it's incremented by 1 each frame, during the NMI routine. So... this appears a frame counter.
So...
Observation 1: the random setup depends on how many frames have elapsed since power-on before you start the game.Step 12: Putting a breakpoint on writes to $0012, I find this routine that runs in a loop many many times each frame during startup:
Code:
00:8539: A2 03 LDX #$03
00:853B: B5 12 LDA $12,X @ $0012 = #$B9
00:853D: F5 11 SBC $11,X @ $0011 = #$80
00:853F: 75 16 ADC $16,X @ $0016 = #$00
00:8541: ED 02 04 SBC $0402 = #$00
00:8544: 4D 23 04 EOR $0423 = #$00
00:8547: 45 02 EOR $0002 = #$08
00:8549: FD F7 03 SBC $03F7,X @ $03F7 = #$00
00:854C: 5D 23 04 EOR $0423,X @ $0423 = #$00
>00:854F: 95 12 STA $12,X @ $0012 = #$B9
00:8551: CA DEX
00:8552: 10 E7 BPL $853B
00:8554: 60 RTS
This just runs being called over and over in an infinite loop until an NMI interrupts it and eventually manipulates the stack to get it out of that infinite loop. This is setting up the 24-bit PRNG seed. It maybe runs 40 times per frame.
Observation 2: this random seed loop is broken only by the NMI, so this will require precise PPU emulation to get correct. If it's even one cycle different, the PRNG seed could be changed.Step 13: That seed generating loop from before also depends on other values from other places, in particular $0016-0019 are where controller inputs are stored (16 = gamepad 0, 17 = gamepad 0 new presses this frame, 18-19 = gamepad 1 similar).
Observation 3: the random seed is influenced by controller input before the start.$0011 also seems to fold into it but it appears to be a constant $80 after startup, so I won't bother looking into it.
SUMMARYSo... I mean we could keep going here, but here's what the situation looks like to me:
- For a consistent PRNG setup, you have to press START on the very first possible frame that you can.
- Input on both gamepads before that start does influence the PRNG seed.
- Power-on RAM values so far do not appear to have any influence.
- Even one cycle difference in the specific timing of the NMI can also alter the seed.
That last one in particular is one that emulators might easily behave differently on, especially reset/warmup behaviour of the PPU. It's also possible that on hardware the variability of
PPU alignment might mean you only have a 1 in 4 chance of getting a consistent alignment on reset/power-up too, even if you could get that frame-perfect START every time.
Does this agree/disagree with your experience with the game?
This reply is absolutely amazing! I can not thank you enough! It certainly deserves a much more though response than this, but I will need to unpack what has been said here and watch through the steps to better understand how I might be able to reproduce your findings. While understanding its progress will most likely elude me it may help me see more than I had before in terms of learning.
As for how I see if I have the right PRNG or not... I simply have to walk up to the top store location every time to see if the shoes are sitting at that location, if so I go two buildings to the right and if there is a rattle behind the mouse then I am on the right 'seed" 100% of the time. Otherwise I simply reset and try again.
Are you saying that even if I am frame perfect and do the same input manipulation every time that there is still a 75% chance that I will get different results than the expected "seed"? If so, then I can say that I have often observed longer periods of time between successful attempts than I would expect. There have been times when it has taken me 20-30 mins before I get the right "seed" and I have had a faint suspicion that maybe there is something else going on. I was not certain of this because getting a frame perfect input is not always easy, in fact at times even with an audio cue it can be hard to hit a 7 frame window such as in Teenage Mutant Ninja Turtles in order to get a good Technodrome location, but again having achieved 10 consecutive frame perfect punches on Mike Tyson before I felt that something else was happening. If this is indeed the case, then could it be that there are times when original hardware may in fact intersect with one of these emulator configurations? I have ran several trials and this does not seem to be the case.
I will also play around with overwriting values to some of these new found addresses to see if I can manipulate the outcomes, but wondering if this would be an over-simplified attempt to solve a broader problem?
CLChambers00 wrote:
Are you saying that even if I am frame perfect and do the same input manipulation every time that there is still a 75% chance that I will get different results than the expected "seed"? If so, then I can say that I have often observed longer periods of time between successful attempts than I would expect. There have been times when it has taken me 20-30 mins before I get the right "seed" and I have had a faint suspicion that maybe there is something else going on. I was not certain of this because getting a frame perfect input is not always easy, in fact at times even with an audio cue it can be hard to hit a 7 frame window such as in Teenage Mutant Ninja Turtles in order to get a good Technodrome location, but again having achieved 10 consecutive frame perfect punches on Mike Tyson before I felt that something else was happening. If this is indeed the case, then could it be that there are times when original hardware may in fact intersect with one of these emulator configurations? I have ran several trials and this does not seem to be the case.
Well, as far as I can tell controller input is only read once per frame, so anything you can
influence with input should not require anything more detailed than that. Maybe I misspoke when I said "first" frame. You could get a consistent seed from
any consistent number of frames from the start, I think.
So... you have one "known" PRNG seed that you have managed to get several times in your tests, right? I would presume that you don't know, however, which exact frame you triggered start on this successful seed, though. If you are trying to find a TAS that hits that seed, if the emulator
was sufficiently equal to your hardware version in behaviour you would also need to use the same start frame too. (I think you already mentioned this above anyway, but just trying to confirm.)
It's a bit strange to me that this game ticks it PRNG so many times per frame like this. Without polling the controller more than once per frame, it's basically the same as just ticking it once per frame as far as entropy-gathering goes.
So do you think that it would be possible for me to write in a value in one of these addresses mentioned above via Lua Script early on in the TAS that would modify the results and potentially get the outcome I am expecting, or is it more complicated than that?
So, it sounds like what you want is to be able to practice/TAS a particular setup that you could later duplicate on a live hardware run?
On the frame where you press start to begin it seems to keep cranking on the PRNG seed for a few more frames before it starts setting up those location variables. It seems like any subtle timing differences are still going to lead to divergence right up to that point. So if you're going to insert values it would probably be right at that moment.
I don't think you can really do this through the PRNG seed though ($12-14). You can't really reverse engineer what values to put in there from what you see in the game. You could probably just set up the location values manually at that point, though? Like it seems that the stuff that it sets up there at the start of the game is the only thing that's reliable anyway, so maybe just focus on building that?
Something that may be interesting, the first frame where $12-14 get written on FCEUX New PPU vs Bizhawk, $12 and $14 are the same but $13 is different (on one, that entropy-gathering loop doesn't get to $13 before the NMI interrupts it) but if I "correct" FCEUX's byte $13 manually at that point they seem to synchronize perfectly afterward across the whole RAM. So... after that first frame of activity (something like 14 frames after boot) it seems like they do start to agree on the results. The divergence may only be due to differences in how the reset timing is emulated?
Correct, being able to TAS out thousands of input variations and different frames upon which to initiate start would be extremely expedient. For example, instead of holding A and pressing start on frame 534, I could see immediately all the variations such as holding A, B, and Select, and checking out pressing start for frames 534 through 553. That spreadsheet that I linked earlier in this thread was me tracking all of the item placement results. If the results from the emulator were the same as hardware I would be able to duplicate the same inputs on the same frames and get the same item placements. It is about finding the most optimized route quickly, and something which can be reasonably duplicated.
The syncing that you managed between FCEUX New PPU vs Bizhawk was only a matter of changing a value in the $13 address? If so could it then be possible for me to play around with this value and potentially sync with original hardware? Obviously I will have to examine the item placement addresses and run many trials to see if sync occurs using same input manipulation that I do for console. It is possible for this to work? I am only looking at 255 possible values right? Maybe the idea of syncing one of these emulators to original hardware is possible, if we can force them to sync with one another?
How are you "correcting" $13? When I change the value via lua script it does not seem to really change anything since values are being written to it by something that I am not changing. Though maybe if $13 is being read at that time then perhaps it does alter something?
I started the game in FCEUX and advanced until the first frame where $12-15 changed (something like 14 frames), then I did the same in Bizhawk. At that point, only $13 was different between the two, so I set the value at $13 in FCEUX to be equal to the one from Bizhawk. After that they stayed the same on subsequent frames.
The game is just spinning in a loop that cycles $15,14,13,12. Between the two emulators one of them seems to come out of reset very slightly later than the other, so that first frame gets one more tick of the loop, which updates $13 one more time. So, aside from that very small timing difference after reset the two emulators actually appear to match up.
My observations are different. FCEUX (New PPU) populates $12-$14 on frame 16, and Bizhawk(NesHawk) populates them on frame 15. I observe that the initial values in these addresses...
Addresses $12 and $13 were the same, it was $14 that was different.
$12 (69)
$13 (109)
$14 (-71 FCEUX), (185 Bizhawk)
These are the values taken from FCEUX on frame 16, and from Bizhawk on frame 15.
Also when I write in a value it shows it changed for that frame but then all the subsequent frames are the same as what they would have been had I not changed it.
Also, you mentioned earlier that address $11 was a constant 80 after startup but it is -128 for me. This is using FCEUX New PPU. Why would this be different?
CLChambers00 wrote:
(-71 FCEUX), (185 Bizhawk)
-71 and 185 are the same 8-bit byte, just interpreted as a signed or unsigned type. (Either way, it's $B9)
CLChambers00 wrote:
Also, you mentioned earlier that address $11 was a constant 80 after startup but it is 128 for me.
He said it was a constant
$80. The $ means "hexadecimal". The 8-bit byte $80 is the unsigned decimal quantity 128, or the signed decimal quantity -128.
Oh, ok, it is a signed/unsigned issue. Did not know that was an issue. Sorry for the false observations.
Ok, after setting all the ram watch addresses to unsigned I see the following:
0012-0014 are the same in both FCEUX and Bizhawk for the first two initial frames, on the 3rd initial frame in either 0013 and 0014 both diverge.
0013 in Bizhawk 199, while it is 202 in FCEUX
0014 in Bizhawk 238, while it is 144 in FCEUX
That is frame 17 in Bizhawk, frame 18 in FCEUX
So when I write 199 and 238 respectively into via a Lua Script file which merely includes the following text:
memory.writebyte(0x0013,199)
memory.writebyte(0x0014,238)
I run this script and then progress one frame, to the frame I want those values written to.
... I see that it changed the values for that frame but when I progress one more frame these addresses populate the same values they would have 219 and 145 respectively. So changing those values did not seem to change the outcomes. Unless I am doing something wrong?
^ Is a Lua script like this sufficient for an address change? I see that it changes in RAM watch but as it progresses I so no influence from it.
So concerning the NMI and PPU Alignment, if I am really only getting a 1 in 4 chance for my input manipulation, when done perfectly, then could it be possible that one of the other 3 PPU alignments actually syncs with FCEUX or Bizhawk?
Also, I am offering a $200 bounty for the person who figures out how to get outcomes to match in original hardware and an emulator with TAS such as Bizhawk and FCEUX. If interested please send me a PM, and we can discuss the details.
ok, so the emulator route is totally out, I have exhausted today's nes emulation capability but I another twitch streamer by the name threecreepio hacked the rom so that it gives you the values in the score section upon starting the game so we can try out new variations, found a new route and carved off 1.5 seconds already, will grind it some more but another route may work better