Skip to content
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

MBC6: Fix Flash Write Enable description #573

Merged
merged 1 commit into from
Oct 15, 2024

Conversation

msinger
Copy link
Contributor

@msinger msinger commented Oct 5, 2024

While testing something else on the Nintendo Power flash cartridge, I accidentally found out that the /WP pin of the flash doesn't protect the whole flash. I forgot to disable the protection and was able to write sectors 1-7 anyway. Then I also tested Net de Get and the flash has the same /WP pin. It behaves identical, so I did some more tests to verify and fixed some stuff in the MBC6 description:

  • The Flash Write Enable bit doesn't influence the /WE signal of the flash. It directly controls the /WP (/write protect; pin 12) signal.
  • It is not true that the Flash Enable register can only be changed when the Flash Write Enable register is set to 1. Both registers are in fact independent of each other.
  • The Flash Write Enable register does not protect the whole flash from being erased and programmed. It only protects sector 0 and the hidden 256 byte region. Sectors 1 to 7 can always be modified.
  • The status bytes are not exactly $80 or $10. Only a few of the bits are driven by the flash when reading status bytes. The undriven bits are random.

@CasualPokePlayer
Copy link
Contributor

The undriven bits are always high due to the Game Boy chip's internal pull-up resistors on the data I/Os.

This probably wouldn't be exactly right: this is the cartridge area, which isn't subject to strictly always having high bits for open bus like internal I/O. Rather it would just be some bitwise OR against the bits last on the cartridge bus, and possibly randomly having some other bits be high regardless (although if execution was in say HRAM, this doesn't really apply since whatever is on the cartridge bus would have floated up to 0xFF by now).

@msinger
Copy link
Contributor Author

msinger commented Oct 5, 2024

@CasualPokePlayer are you sure? I haven't tested it on the real Game Boy hardware recently. I would need to do some cartridge swapping there, and I'm not sure if the level shifters on an Everdrive cartridge would override the pull-ups. I used my own hardware instead of a Game Boy. My board has level shifters with hold-function, so they behave like you describe, I read the value that was on the bus previously. But I'm pretty sure that on the real Game Boy with an original cartridge, you read 0xFF when the bus is undriven. When reading, the Game Boy chip enables pull-up resistors on the I/O pads. Those pull up the external data bus. They are there, so that the data lines are never really floating. The internal bus doesn't have pull-ups. The internal bus uses capacitive precharging instead.
Or do you mean that the data lines from the flash are only connected to the MBC6, and not to the cartridge connector? In that case I don't know if the MBC6 has pull-ups. I don't have a schematic of this cartridge.
Anyway, I just wrote this in the commit message, it isn't in the markdown file.

@CasualPokePlayer
Copy link
Contributor

CasualPokePlayer commented Oct 5, 2024

An Everdrive would completely throw off any results here: that is known to somehow "force" the bus value to stay the same rather than turn to 0xFF.

On real GameBoy hardware, it is generally very much ""expected"" for the last value to get read off the bus: a few games rely on such behavior, crashing if 0xFF is read. The value on the bus does eventually get pulled up to 0xFF, but this happens generally in around 1 single speed m-cycle, so any delay will likely just result in 0xFF being read off the bus (e.g. a pop in open bus would have 0xFF in the second read byte, typically). This can vary heavily since this is non-deterministic behavior (hence "randomly some bits get pulled up to 1 regardless"): perhaps the MBC6 does something to throw this out completely too, although it's probably a safe assumption it behaves similarly to other cartridges.

@msinger
Copy link
Contributor Author

msinger commented Oct 5, 2024

Ah, okay. Maybe the pull-ups are too weak, so that it takes a moment. Interesting, I didn't know that some games rely on that. Do they do this for copy protection?

@msinger
Copy link
Contributor Author

msinger commented Oct 5, 2024

Ah, no, I just read the link. They are bugged. :)

* The Flash Write Enable bit doesn't influence the /WE signal of the
  flash. It directly controls the /WP (/write protect; pin 12) signal.
* It is not true that the Flash Enable register can only be changed when
  the Flash Write Enable register is set to 1. Both registers are in
  fact independent of each other.
* The Flash Write Enable register does not protect the whole flash from
  being erased and programmed. It only protects sector 0 and the hidden
  256 byte region. Sectors 1 to 7 can always be modified.
* The status bytes are not exactly $80 or $10. Only a few of the bits
  are driven by the flash when reading status bytes. The undriven bits
  are random.
@msinger msinger force-pushed the fix_mbc6_flash_wp branch from cb966f9 to 8ab69c4 Compare October 5, 2024 17:55
Copy link
Member

@ISSOtm ISSOtm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a way to verify what's stated here, but I don't see anything wrong either (e.g. formatting-wise).

Since no further objections have been made for one week, I'm thus going to merge this.

@ISSOtm ISSOtm merged commit b0c42f0 into gbdev:master Oct 15, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants