What's new
@Amos When you start up a dimm and there is no game loaded in memory, you get Error 31.

Did you try loading a game?
 
Last edited:
@Amos When you start up a dimm and there is no game loaded in memory, you get Error 31.

Did you try loading a game?
Yes of course ;)
And I have this error on the screen : error 31.

And when I delete the famous line, everything works again.
 
btw, unsure if this will help you but there is no need to comment out `s.send(struct.pack("<I", 0x7F000008) + data)`. It sets the keychip to 0, and I'm unsure if this is required so probably best to leave it in. Just add the new check-off line below that.

It sounds to be like your not copying it in correctly. Make sure you have the same amount of tabs/spaces as the line above or python won't work properly.
 
Are you using a zero pic in your setup ?
No. No zero key.
btw, unsure if this will help you but there is no need to comment out `s.send(struct.pack("<I", 0x7F000008) + data)`. It sets the keychip to 0, and I'm unsure if this is required so probably best to leave it in. Just add the new check-off line below that.

It sounds to be like your not copying it in correctly. Make sure you have the same amount of tabs/spaces as the line above or python won't work properly.
I try many things, let or comment out the line "s.send(struct.pack("<I", 0x7F000008) + data)".
I suppose I copy correctly and still verify the line(s) before/after added it, I have the same tabs/spaces too.

Here is an exemple.
 

Attachments

  • Clipboard 1.jpg
    Clipboard 1.jpg
    158.5 KB · Views: 72
Has anyone verified that the new "skip memory test" code works without a network zero PIC ?
 
Has anyone verified that the new "skip memory test" code works without a network zero PIC ?
Thx rtw, that's what I suspected first, that's why I specified it (but if someone can validate or invalidate it) :

I tested different ways but it doesn't work for me...

I have a Pi 2 with a LCD screen (from the member Squallrs, I bought it on another forum) and I have the same "structure" as opt2not :

def SECURITY_SetKeycode(data):
assert len(data) == 8
s.send(struct.pack("<I", 0x7F000008) + data)

I try to comment out/delete/let the line "s.send(struct.pack("<I", 0x7F000008) + data)" before adding this one "s.send(struct.pack(">IIIIIIIIH", 0x00000001, 0x1a008104, 0x01000000, 0xf0fffe3f, 0x0000ffff, 0xffffffff, 0xffff0000, 0x00000000, 0x0000))" but nothing happens, the LCD screen doesn't light up, so I can't do anything.

Any idea?

Thx!

PS : for the Pi from Squallrs, no need to have a Zero-key, everything comes from python (that's what the creator said to me)
 
@rtw The code does work without a security pic, as I've never had one and it works for me. That was why I was slightly concerned with commenting that set security line out though, and reccomend it's just left in place.

@Amos I can see there is something wrong with your tabs / spaces. In your editor on the left there are lines drawn from the start to the end of the function. On the set security key code function, there are lines drawn from the start of the function to the last 2 lines in the function. This to me looks like you've tabbed / spaced them incorrectly. Play around with it until you can get it to draw only a line from the start of the function, to the end like the rest of the functions have.
 
@rtw The code does work without a security pic, as I've never had one and it works for me. That was why I was slightly concerned with commenting that set security line out though, and reccomend it's just left in place.

@Amos I can see there is something wrong with your tabs / spaces. In your editor on the left there are lines drawn from the start to the end of the function. On the set security key code function, there are lines drawn from the start of the function to the last 2 lines in the function. This to me looks like you've tabbed / spaced them incorrectly. Play around with it until you can get it to draw only a line from the start of the function, to the end like the rest of the functions have.
You're right, it works! Thx :) (it was logical and I missed it...)
And I can confirm : we can switch from an Atomiswave game to another one without turn off/turn on.
 
btw, unsure if this will help you but there is no need to comment out `s.send(struct.pack("<I", 0x7F000008) + data)`.
I commented it out and it works for me. <shrug>
 
Thanks,It works perfectly with my Naomi2 (jap bios) Netdimm 3.17 256Mo with PicZero and Raspberry2 (piforce 1.5). Symply adding one line !
Playing AW games then Naomi games works well too.
MERCI
 
We know this (as this is the same with any system, there is some memory, it get's changed, things happen) but I'm not sure what any of those commands mean or translate too - it's an odd packet as it's got lots of 0xFFs in it.

For some background: we found a bunch of files shipped with a DVD card builder Chihiro game. It included some exes, and perl scripts that it obviously used to netboot the games (gundam mobile suit something or other).

One of the .exe's was called checkoff.exe and would seemingly turn the memory check off on the chihiro. @chunksin ran the .exe and wire-sharked it to find out what the bytes it sent were. We then just repacked the bytes into a way python can send them to put them into triforcetools.py, and then @mathieulh found that the command that was setting the check back on was the one that sets the key, so we just replayed those bytes after that command and presto - no more memory checking!

Started at about 9am today, and had a solution by about 2pm whilst most of us were at work :P
I know, holy thread necro and all that, but I've been apparently wasting my time reverse-engineering the 3.17 firmware since there was no (to my ability to find) public information on any of this stuff. That's over here: https://www.arcade-projects.com/threads/netboot-naomi-with-eeprom-presets.18977/page-2

I am replying since I can explain basically every part of that command, so hopefully for the curious I can demystify why it does what it does and what's actually going on. Okay, so, the bytes are as such:

Code:
00 00 00 01 1a 00 81 04 01 00 00 00 f0 ff fe 3f 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00

Let's break it down. The net dimm protocol uses the first 4 bytes as a packet header. The first two bytes are little-endian length of any additional packet data. The next byte is a flag byte. I don't know what the top bit is supposed to signify, but the bottom bit is set to 1 for the "last" packet and 0 for any additional. Most packets do not use this since most of them are standalone. The dimm send and dimm receive packets do. This is why the dimm send packet has a "mark" bit in triforcetools.py. Similarly, if you request more than 0x2000 bytes from the dimm receive packet, the firmware will split it into multiple responses each with maximum length of 0x2000 data, setting the "last" flag to 0 for all packets it sends except for the final packet. The final byte is the packet type. If there is a length set, then "length" bytes will follow, and should be viewed as data for that packet. This holds for responses as well, so you can decode any response you get from the net dimm in a similar manner.

Okay, so now we have this:

Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.

1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 f0 ff fe 3f 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 26 bytes of data (as specified in length above) for this packet.

Okay cool. First, packet 0x01 is a "NOP" packet. In fw 3.17 the handler simply returns success, does not matter. I don't know why tools send this, maybe in some version of firmware this enabled some communications? Anyway, triforcetools does not bother with this, but official tools send this. It is safe to drop this from the request, it does nothing. Second, packet 0x04 is "send to dimm". It is the same packet that is used for uploading games to the DIMM, funny enough. It has access to the entire memory space for the dimm, but it also has access to the special pool of memory reserved for the net dimm itself. Since this is battery-backed, anything written here gets stored until your battery dies. It has the following format. First 4 bytes are a little-endian integer specifying the sequence number. This can be ignored or set to whatever you want in practice, dimm fw 3.17 ignores this. However, official tools start at sequence number 1 and increment every data packet sent. Similarly, if you use command 0x05 (receive from dimm) and you ask for too much data, when it splits the response into multiple packets the sequence number will be incremented for each packet, starting at 1. The second 4 bytes are the memory address to write to. Normally you start at 0 for game upload. Special system config lives at the top of RAM. The net dimm firmware, at least in 3.17 will calculate the maximum memory size based on the inserted memory modules, subtract some amount for its own memory and always stick thet system config there, so the addresses are the same no matter how much memory you put in your dimm. The address here is "0x3ffefff0". Note that this is mirrored. In my own tools, I send instead to "0xfffefff0" and it works just the same. The next 2 bytes are always zero. At least in fw 3.17 it does not even attempt to parse them. They are just there to be useless. The remaining data (packet length - 10 bytes) is the bytes that get written starting at the memory address.

Okay, so now we have this:

Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.

1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 = sequence number 1
f0 ff fe 3f = please write to address 0x3ffefff0
00 00 = useless short, maybe for some expansion in the future?
ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 16 bytes to write starting at address 0x3ffefff0.

Okay cool, so this is how that packet works. But why that particular address? What makes it so special. For that, lets go to 3.17 firmware reverse engineering. In the bootup state machine we find this:

Untitled.png

I've renamed a lot of stuff from disassembly garbage names to make the code more clear. The top circled bit looks up the base dimm address. The second chunk of code calls the vxWorks DIMM read driver function with the address base + 0xfffefff0 (simply 0xfffefff0 from the send to dimm/receive from dimm packet's perspective). Remember how I said that was mirrored. That's the same address as 0x3ffefff0. Okay cool. It reads 16 bytes into the "memory values" buffer which is set currently to 4 32-bit values. Then, the critical bit of code compares the first 32-bit value to the bitwise inverse of the 3rd, and the 2nd 32-bit value to the bitwise inverse of the 4th. If they match, then it prints "non crc mode" to the debug console serial and sets the system CRC status to 5. Otherwise it goes on to CRC the data that is in the DIMM.

Side node, the CRC status is retrievable using a "read from dimm" command to another system memory location "0xfffeffe0". You can read it with the "read from dimm" command 0x05. It has the following values: 0 or 1 - we have not finished checking CRC. The system will be displaying "NOW CHECKING" on the screen. 2 - CRC is good, game should boot, 3 - CRC is bad, don't boot, 4 - Your DIMM memory has something wrong with it, 5 - CRC checking is disabled, we will boot without checking.

Okay, cool, so let's put this all together.

Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.

1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 = sequence number 1
f0 ff fe 3f = please write to address 0x3ffefff0
00 00 = useless short, maybe for some expansion in the future?
ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 16 bytes to write starting at address 0x3ffefff0. The first and 3rd "integer" are bitwise opposite (0xffffffff = ~0x00000000) and the second and 4th "integer" are also bitwise opposite! The magic flag values to make CRC checking disable. So, in reality according to the code we should be able to put anything we want here as long as the 3rd and 4th 4-byte integers are bitwise opposite of the 1st and 2nd integers respectively. It also tells us why setting all 0's here re-enables the CRC check.

And that's why this packet does what it does. For more comments on what's actually going on, when I reverse-engineered the firmware because I couldn't find any public documentation, I wrote a TON of documentation here: https://github.com/DragonMinded/netboot/blob/trunk/netboot/netboot.py As another aside, the "set information" packet that sends the CRC and length is just writing to special location 0xffff0000 with a CRC32 over the first 28 bytes in byte location 28-32. So you can read 4 bytes back at location 0xffff0004 to get the set size of the game that's running. You can also read 0xffff0000 to get the CRC of the game, but that's already available in the "get information" packet. There are probably a lot more system values in that section that I haven't begun to reverse-engineer. For instance the net dimm firmware knows what target it is running on and I suspect that it might be possible to find that info somewhere in the system section.
 
Last edited:
I know, holy thread necro and all that, but I've been apparently wasting my time reverse-engineering the 3.17 firmware since there was no (to my ability to find) public information on any of this stuff. That's over here: https://www.arcade-projects.com/threads/netboot-naomi-with-eeprom-presets.18977/page-2

I am replying since I can explain basically every part of that command, so hopefully for the curious I can demystify why it does what it does and what's actually going on. Okay, so, the bytes are as such:

Code:
00 00 00 01 1a 00 81 04 01 00 00 00 f0 ff fe 3f 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00

Let's break it down. The net dimm protocol uses the first 4 bytes as a packet header. The first two bytes are little-endian length of any additional packet data. The next byte is a flag byte. I don't know what the top bit is supposed to signify, but the bottom bit is set to 1 for the "last" packet and 0 for any additional. Most packets do not use this since most of them are standalone. The dimm send and dimm receive packets do. This is why the dimm send packet has a "mark" bit in triforcetools.py. Similarly, if you request more than 0x2000 bytes from the dimm receive packet, the firmware will split it into multiple responses each with maximum length of 0x2000 data, setting the "last" flag to 0 for all packets it sends except for the final packet. The final byte is the packet type. If there is a length set, then "length" bytes will follow, and should be viewed as data for that packet. This holds for responses as well, so you can decode any response you get from the net dimm in a similar manner.

Okay, so now we have this:

Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.

1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 f0 ff fe 3f 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 26 bytes of data (as specified in length above) for this packet.

Okay cool. First, packet 0x01 is a "NOP" packet. In fw 3.17 the handler simply returns success, does not matter. I don't know why tools send this, maybe in some version of firmware this enabled some communications? Anyway, triforcetools does not bother with this, but official tools send this. It is safe to drop this from the request, it does nothing. Second, packet 0x04 is "send to dimm". It is the same packet that is used for uploading games to the DIMM, funny enough. It has access to the entire memory space for the dimm, but it also has access to the special pool of memory reserved for the net dimm itself. Since this is battery-backed, anything written here gets stored until your battery dies. It has the following format. First 4 bytes are a little-endian integer specifying the sequence number. This can be ignored or set to whatever you want in practice, dimm fw 3.17 ignores this. However, official tools start at sequence number 1 and increment every data packet sent. Similarly, if you use command 0x05 (receive from dimm) and you ask for too much data, when it splits the response into multiple packets the sequence number will be incremented for each packet, starting at 1. The second 4 bytes are the memory address to write to. Normally you start at 0 for game upload. Special system config lives at the top of RAM. The net dimm firmware, at least in 3.17 will calculate the maximum memory size based on the inserted memory modules, subtract some amount for its own memory and always stick thet system config there, so the addresses are the same no matter how much memory you put in your dimm. The address here is "0x3ffefff0". Note that this is mirrored. In my own tools, I send instead to "0xfffefff0" and it works just the same. The next 2 bytes are always zero. At least in fw 3.17 it does not even attempt to parse them. They are just there to be useless. The remaining data (packet length - 10 bytes) is the bytes that get written starting at the memory address.

Okay, so now we have this:

Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.

1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 = sequence number 1
f0 ff fe 3f = please write to address 0x3ffefff0
00 00 = useless short, maybe for some expansion in the future?
ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 16 bytes to write starting at address 0x3ffefff0.

Okay cool, so this is how that packet works. But why that particular address? What makes it so special. For that, lets go to 3.17 firmware reverse engineering. In the bootup state machine we find this:

Untitled.png

I've renamed a lot of stuff from disassembly garbage names to make the code more clear. The top circled bit looks up the base dimm address. The second chunk of code calls the vxWorks DIMM read driver function with the address base + 0xfffefff0 (simply 0xfffefff0 from the send to dimm/receive from dimm packet's perspective). Remember how I said that was mirrored. That's the same address as 0x3ffefff0. Okay cool. It reads 16 bytes into the "memory values" buffer which is set currently to 4 32-bit values. Then, the critical bit of code compares the first 32-bit value to the bitwise inverse of the 3rd, and the 2nd 32-bit value to the bitwise inverse of the 4th. If they match, then it prints "non crc mode" to the debug console serial and sets the system CRC status to 5. Otherwise it goes on to CRC the data that is in the DIMM.

Side node, the CRC status is retrievable using a "read from dimm" command to another system memory location "0xfffeffe0". You can read it with the "read from dimm" command 0x05. It has the following values: 0 or 1 - we have not finished checking CRC. The system will be displaying "NOW CHECKING" on the screen. 2 - CRC is good, game should boot, 3 - CRC is bad, don't boot, 4 - Your DIMM memory has something wrong with it, 5 - CRC checking is disabled, we will boot without checking.

Okay, cool, so let's put this all together.

Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.

1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 = sequence number 1
f0 ff fe 3f = please write to address 0x3ffefff0
00 00 = useless short, maybe for some expansion in the future?
ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 16 bytes to write starting at address 0x3ffefff0. The first and 3rd "integer" are bitwise opposite (0xffffffff = ~0x00000000) and the second and 4th "integer" are also bitwise opposite! The magic flag values to make CRC checking disable. So, in reality according to the code we should be able to put anything we want here as long as the 3rd and 4th 4-byte integers are bitwise opposite of the 1st and 2nd integers respectively. It also tells us why setting all 0's here re-enables the CRC check.

And that's why this packet does what it does. For more comments on what's actually going on, when I reverse-engineered the firmware because I couldn't find any public documentation, I wrote a TON of documentation here: https://github.com/DragonMinded/netboot/blob/trunk/netboot/netboot.py As another aside, the "set information" packet that sends the CRC and length is just writing to special location 0xffff0000 with a CRC32 over the first 28 bytes in byte location 28-32. So you can read 4 bytes back at location 0xffff0004 to get the set size of the game that's running. You can also read 0xffff0000 to get the CRC of the game, but that's already available in the "get information" packet. There are probably a lot more system values in that section that I haven't begun to reverse-engineer. For instance the net dimm firmware knows what target it is running on and I suspect that it might be possible to find that info somewhere in the system section.
Getting the CRC would actually be useful to add a skip in the triforcetools that would not send the game again to the dimm if the crc matches the binary you want to send. Transfergame does this already.

I am also considering skipping the memory checks altogether as a patch in the dimm firmware but I am unsure as to what kind of side effect this may bring.
 
I am also considering skipping the memory checks altogether as a patch in the dimm firmware but I am unsure as to what kind of side effect this may bring.
CRC check is the only way DIMM detecting game change if GD or CF boot, not sure if it makes a sense for net boot.
 
Skipping sending again if the CRC matches and is considered valid by the net dimm (state 3) is precisely how my dimm management server works. My management server can even be restarted and re-sync state since it can check the game that it wants to send after it reboots against the CRC to figure out that it really should be in a different internal state (code if you are curious: https://github.com/DragonMinded/netboot/blob/trunk/netboot/cabinet.py#L127)

If you skip the checks using the "unofficial" official method as documented here, it is definitely part of the designed state machine as it has its own "CRC state" and everything for querying from the "get information" packet. What advantages does skipping with a memory patch to the dimm firmware have over setting the skip flag using the dimm upload packet as documented in this thread?
 
What advantages does skipping with a memory patch to the dimm firmware have over setting the skip flag using the dimm upload packet as documented in this thread?
It would be useful to people using regular DIMM or using NetDIMM to boot CF/GD/CD-R, this would decrease load times as it would no longer perform the (arguably unnecessary) CRC checks. If you aren't using a NetDimm, you can't really send a packet to disable the CRC check since it isn't connected to the network.
 
CRC check is the only way DIMM detecting game change if GD or CF boot, not sure if it makes a sense for net boot.
That makes more sense, though the likelihood of anyone switching from GD to CF or vice versa without disconnecting the battery on the same setup is rather low.
 
That makes more sense, though the likelihood of anyone switching from GD to CF or vice versa without disconnecting the battery on the same setup is rather low.
If there is no CRC check how would a netdimm loading a CF game know that the game is loaded at all ? The memory check is verified against the checksum stored in the loader file on the CF.
 
Back
Top