New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Random RAM #158
Implement Random RAM #158
Conversation
Thanks! The randomization looks good, but there are two things that I get caught on: First, I'm not sure I with the change in the initialization argument from Also, what's all the numpy stuff for? Is that just to avoid using It'll be good to have this, though! That particular to-do has been there for quite a while, haha. |
Hey @krs013, thanks for the comments. I changed the flag to Yup, I used numpy for figuring out the max value of the |
Ah, I see, of course. I guess I didn't think about the name aliasing before the import was needed. Could I suggest Regardless of the platform that PyBoy is running on, the maximum value for a gameboy register will always be the same, so you can just hardcode that to 0-255 (or 0x00-0xFF if you want it to look nicer)! Also, Python And yeah, I love numpy and it's great, but leaving it as an install dependency is a hassle sometimes since numpy is sometimes problematic to install. I've been trying to squeeze it out to only be in the optional parts of PyBoy for quite a while now! Maybe one day I'll finish. |
Sounds good. I've gone ahead and hardcoded the max value, and removed |
It was written before the first PPU was implemented 😉 |
Thanks for your work @naclander! I think it needs a little more before we're ready to merge. Do you want to do it? I can see we need the following:
|
@krs013 Does it make sense to implement this as a plugin? |
I think this belongs in the core, since it's part of what you can expect any emulator to do, not just ours. |
I only think WRAM/HRAM should be randomized (Well VRAM and OAM too technically). Some registers have bits that are unreadable/writeable. Also, IO registers are initialized to specific values, where most are just 0xFF. |
pyboy/core/ram.py
Outdated
self.internal_ram0 = array.array("B", [0] * (INTERNAL_RAM0)) | ||
self.non_io_internal_ram0 = array.array("B", [0] * (NON_IO_INTERNAL_RAM0)) | ||
self.io_ports = array.array("B", [0] * (IO_PORTS)) | ||
self.internal_ram1 = array.array("B", [0] * (INTERNAL_RAM1)) | ||
self.non_io_internal_ram1 = array.array("B", [0] * (NON_IO_INTERNAL_RAM1)) | ||
self.interrupt_register = array.array("B", [0] * (INTERRUPT_ENABLE_REGISTER)) | ||
|
||
if randomize: # NOTE: In real life, the RAM is scrambled with random data on boot. | ||
for mem in (self.internal_ram0, self.non_io_internal_ram0, self.io_ports, self.internal_ram1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FEA0-FEFF range seems not to be randomized on DMG
Also, not really important, but maybe write hardware instead of real life?
for mem in (self.internal_ram0, self.non_io_internal_ram0, self.io_ports, self.internal_ram1, | |
for mem in (self.internal_ram0, self.internal_ram1): |
pyboy/core/ram.py
Outdated
self.internal_ram0 = array.array("B", [0] * (INTERNAL_RAM0)) | ||
self.non_io_internal_ram0 = array.array("B", [0] * (NON_IO_INTERNAL_RAM0)) | ||
self.io_ports = array.array("B", [0] * (IO_PORTS)) | ||
self.internal_ram1 = array.array("B", [0] * (INTERNAL_RAM1)) | ||
self.non_io_internal_ram1 = array.array("B", [0] * (NON_IO_INTERNAL_RAM1)) | ||
self.interrupt_register = array.array("B", [0] * (INTERRUPT_ENABLE_REGISTER)) | ||
|
||
if randomize: # NOTE: In real life, the RAM is scrambled with random data on boot. | ||
for mem in (self.internal_ram0, self.non_io_internal_ram0, self.io_ports, self.internal_ram1, | ||
self.non_io_internal_ram1, self.interrupt_register): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only randomize RAM
self.non_io_internal_ram1, self.interrupt_register): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What isn't RAM in this case?
Everything is inside the RAM class, should some things be moved elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the IO registers and the interrupt register shouldn't be randomized.
I've attached an example from BGB that shows the values of some of the IO Registers.
WRAM, HRAM, VRAM, and OAM do contain random values on boot. Initializing VRAM with random values is redundant though, as the bootrom clears it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still want to randomize VRAM, as we have our own boot ROM, which currently doesn't clear VRAM. If somebody makes a mistake and the VRAM isn't cleared, it will show up.
You're totally right. But I'm not sure if this can easily be fixed in this PR, or if we should do that separately? |
Is this something we want to plumb all the way from the user? As a user starting PyBoy, I would imagine the emulator starting with random RAM ( as close to the hardware as possible ) by default is good enough. I do agree that this should be a flag on the Motherboard class, and so probably on the PyBoy class, so that it can programmatically be changed.
I would have to look at these classes more closely. I wasn't thinking of changing anything outside the RAM module initially.
Cool, I'll do that.
I would say any end to end tests should be run with how the emulator is presented to users by default, that is, with In either case, I don't have access to all the ROMs that the unit tests use, so I can't verify all tests pass, but from the small amount of testing I did manage to do everything seems to be working fine. BTW, I like the mooneye and blargg tests, but some of them seem to be broken when ran ( at least on my machine ). |
I'm not sure why this was closed |
If the random flag is set, iterate through the existing RAM arrays and randomize the values. While there are no specific RAM unit tests, I played through some of the ROMs I have locally and the games seemed to be running fine. (cherry picked from commit 76604d5)
(cherry picked from commit e921fe9)
Co-authored-by: Nico <55274642+nicoeps@users.noreply.github.com> (cherry picked from commit 13139ec)
(cherry picked from commit 130a782)
(cherry picked from commit 57b5c6a)
0e66de5
to
9b80a59
Compare
I've reset the base branch and cherry picked the commits that belong in this PR. Unfortunately, since that technically creates new commits, the time stamps have changed, so the comments are a little out of order. Still, we can at least see the real history and file changes now. |
Cython does not return array length with len() so I had to change it for explicit for loops. All tests pass.
I started adding the arguments and things got away from me and I ended up finishing the tests and the feature. I ended up having to change more than I expected; it turns out that you can't use |
Great work on fixing this PR up @krs013! I think we'll need to run at least one test-ROM to determine, that the emulator is still functional after this modification. Does Blargg's tests for example work after randomization? |
Just tried it and they all pass with randomization on. I'll configure some to rerun with randomization, or I guess we could run all of them twice if we want maximum coverage but that sets a tedious precedent. |
Just some quick ones. Or even just add it to one of the existing tests. For example the ones generating GIFs? |
Done. Sorry it took so long for so little, haha, I took a while before deciding that randomizing the Blargg tests wasn't really worth it, and then had to use a different machine to do the GIF tests because I don't trust my Linux machine due to a GIF bug that I need to confirm. If it shows up on Debian or Ubuntu or something then expect an issue... sometimes I get 1.GIF rendering with lingering pixels in the health bar. Also a problem is that somehow this doesn't fail the tests? |
Ok, that should be good enough. Maybe one day, I'll move more and more of the tests over to use randomized RAM as default. I think I've disabled the GIF testing on Linux, as that doesn't work because of the artifacts you describe. I haven't been able to make it go away. But it's outside PyBoy it happens. |
If the random flag is set, iterate through the existing RAM arrays and
randomize the values.
While there are no specific RAM unit tests, I played through some of the
ROMs I have locally and the games seemed to be running fine.