bodgit / memcardpro

Utility for 8BitMods MemCard PRO
https://8bitmods.com/accessories/memcard-pro/
BSD 3-Clause "New" or "Revised" License
36 stars 2 forks source link

Some MCP2 generated VMCs seem to cause checksum errors with this tool #38

Closed K3zter closed 6 months ago

K3zter commented 6 months ago

Hi,

I've spoken to a couple people on Discord who have been trying to use this tool on VMCs generated with the MCP2, but the tool returns this error: Error: unable to create PlayStation reader: bad directory frame checksum

I'm not sure if this is a genuine checksum issue with the VMC or not - however they work fine in the MCP2 and MemCardRex can also read them without issue.

I've attached an example VMC with this issue. vmc.zip

Thanks :)

bodgit commented 6 months ago

I haven't done anything for the MCP2 yet despite having one sat in my to-do pile, so there's no support for the PS2 card images yet. However it should in theory be fine with PS1 card images.

Thanks for attaching an example, I'll take a look. I have an MCP(1) too so I can compare and see if there's any differences.

The checksum in general is pretty simple as it's a single XOR-d byte.

bodgit commented 6 months ago

@K3zter please try the 0.0.6 release, this should now be fixed.

As to the cause, the PS1 card format in some of its frames have areas of unused bytes. Common convention is to treat them as zero values, but it turns out the image you provided which came from the MCP2 has some non-zero values in those areas but I was assuming they were zero so the checksum value would never match up.

image

(It's the area marked "Garbage", offset 20h to 7Eh)

I've not seen that before with any previous images so I'm tempted to say it's technically the MCP2 that is/was at fault although it's a matter of interpretation with the spec/format, (SHOULD vs MUST).

The code is now fixed so it always uses the actual byte values when checking the checksum so they match up now.

K3zter commented 6 months ago

Ahh, interesting! I've tested the new version on the handful of VMCs I had with this issue and it ran without a hitch. Thanks for looking into it. :)

JonathanDotCel commented 6 months ago

@K3zter please try the 0.0.6 release, this should now be fixed. ... The code is now fixed so it always uses the actual byte values when checking the checksum so they match up now.

Hi @bodgit, I wrote a good chunk of the MCP2 fw... I'm pretty sure it doesn't add those extra bytes! (And certainly not only on files which are in use)

It looks fairly regular and structured though, so my best guess is some third party tool has left settings or garbage data in there.

Cheers for the fix though! J

bodgit commented 6 months ago

@K3zter please try the 0.0.6 release, this should now be fixed. ... The code is now fixed so it always uses the actual byte values when checking the checksum so they match up now.

Hi @bodgit, I wrote a good chunk of the MCP2 fw... I'm pretty sure it doesn't add those extra bytes! (And certainly not only on files which are in use)

It looks fairly regular and structured though, so my best guess is some third party tool has left settings or garbage data in there.

When I added some debugging it looked like the same byte pattern was present in the padding of each offending directory frame, I put it down to a case of some code not zeroing out the memory fully.

I haven't actually checked to see if it's maybe one of the games with data on this card image that might be writing that bad data rather than the MCP2 itself. That seems a more likely scenario.

The issue was slightly exacerbated by a language feature of Golang, here's the struct used to read in directory frames:

type directoryFrame struct {
        AvailableBlocks byte
        _               [3]byte
        Size            uint32
        LinkOrder       uint16
        CountryCode     [2]byte
        ProductCode     [10]byte
        Identifier      [8]byte
        _               [97]byte
        Checksum        [1]byte
}

The _ fields allow you to pad out the struct for I/O but not care what the value of those fields are, however if you write it back out any value is replaced with the zero value for that type, (which for numeric fields is zero), so any random values in the padding were lost on read, but as they were considered when calculating the original checksum it meant when I recalculated it, it would always be wrong.

I will get around to adding support for PS2 card images, the documentation for those is a bit more lacking compared to PS1 so any pointers appreciated!

bodgit commented 6 months ago

Ahh, interesting! I've tested the new version on the handful of VMCs I had with this issue and it ran without a hitch. Thanks for looking into it. :)

I haven't looked too closely at your card image yet, but was it always a particular game on the VMC that triggered this issue?

JonathanDotCel commented 6 months ago

Heh, we're not sure yet what the 2 people who had this issue did in common! Could well be some non-zero'd memory somewhere, I'll keep an eye on it and get back if anything turns up.

Aww dear, yeah, PS2's a whole nother beast!

Hopefully these will be useful: http://www.csclub.uwaterloo.ca:11068/mymc/ps2mcfs.html https://www.psdevwiki.com/ps2/Memory_Card

Maybe also Appolo, FMCB, uLaunchElf, PS3MCA and OPLsources? (I believe SD2PSX is using the PS3MCA filesystem source, and that seems to be working well)

Worth maybe pointing out though that there are 2 major structures to support: 512 byte per sector (raw images, like a memcard flash dump would have) 528 byte per sector (raw images, but 16 EDC bytes tacked on the end of every 512, like pcsx2 uses) (the EDC bytes can be stored as a contiguous part of the file, or just generated on the fly with a quick lookup)

Gl!

K3zter commented 6 months ago

I haven't looked too closely at your card image yet, but was it always a particular game on the VMC that triggered this issue?

Doesn't seem like it. I have a few more affected VMCs here:

vmcs.zip

This is secondhand info as it didn't happen to me directly, but it seems as though the saves were copied using the native PS2 browser, so nothing really unusual or weird about it. The first VMC I shared earlier was copied using a PS1.

Furthermore, when I copied the saves from an MCP2 to new VMCs on an MCP1 using a PS1, the new cards were fine.