@@ -91,9 +91,19 @@ static bool HashISOFile(ISOFileSystem *fs, const std::string filename, md5_conte
91
91
return true ;
92
92
}
93
93
94
+ static std::string FormatRCheevosMD5 (uint8_t digest[16 ]) {
95
+ char hashStr[33 ];
96
+ /* NOTE: sizeof(hash) is 4 because it's still treated like a pointer, despite specifying a size */
97
+ snprintf (hashStr, 33 , " %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ,
98
+ digest[0 ], digest[1 ], digest[2 ], digest[3 ], digest[4 ], digest[5 ], digest[6 ], digest[7 ],
99
+ digest[8 ], digest[9 ], digest[10 ], digest[11 ], digest[12 ], digest[13 ], digest[14 ], digest[15 ]
100
+ );
101
+ return std::string (hashStr);
102
+ }
103
+
94
104
// Consumes the blockDevice.
95
105
// If failed, returns an empty string, otherwise a 32-character string with the hash in hex format.
96
- static std::string ComputePSPHash (BlockDevice *blockDevice) {
106
+ static std::string ComputePSPISOHash (BlockDevice *blockDevice) {
97
107
md5_context md5;
98
108
ppsspp_md5_starts (&md5);
99
109
@@ -111,14 +121,23 @@ static std::string ComputePSPHash(BlockDevice *blockDevice) {
111
121
112
122
uint8_t digest[16 ];
113
123
ppsspp_md5_finish (&md5, digest);
124
+ return FormatRCheevosMD5 (digest);
125
+ }
114
126
115
- char hashStr[33 ];
116
- /* NOTE: sizeof(hash) is 4 because it's still treated like a pointer, despite specifying a size */
117
- snprintf (hashStr, 33 , " %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ,
118
- digest[0 ], digest[1 ], digest[2 ], digest[3 ], digest[4 ], digest[5 ], digest[6 ], digest[7 ],
119
- digest[8 ], digest[9 ], digest[10 ], digest[11 ], digest[12 ], digest[13 ], digest[14 ], digest[15 ]
120
- );
121
- return std::string (hashStr);
127
+ static std::string ComputePSPHomebrewHash (FileLoader *fileLoader) {
128
+ md5_context md5;
129
+ ppsspp_md5_starts (&md5);
130
+
131
+ // Cap the data we read to 64MB (MAX_BUFFER_SIZE in rcheevos' hash.c), and hash that.
132
+ std::vector<uint8_t > buffer;
133
+ size_t fileSize = std::min ((s64)(1024 * 1024 * 64 ), fileLoader->FileSize ());
134
+ buffer.resize (fileSize);
135
+ fileLoader->ReadAt (0 , fileSize, buffer.data (), FileLoader::Flags::NONE);
136
+ ppsspp_md5_update (&md5, buffer.data (), (int )buffer.size ());
137
+
138
+ uint8_t digest[16 ];
139
+ ppsspp_md5_finish (&md5, digest);
140
+ return FormatRCheevosMD5 (digest);
122
141
}
123
142
124
143
static inline const char *DeNull (const char *ptr) {
@@ -927,11 +946,17 @@ bool IsReadyToStart() {
927
946
}
928
947
929
948
void SetGame (const Path &path, IdentifiedFileType fileType, FileLoader *fileLoader) {
949
+ bool homebrew = false ;
930
950
switch (fileType) {
931
951
case IdentifiedFileType::PSP_ISO:
932
952
case IdentifiedFileType::PSP_ISO_NP:
933
953
// These file types are OK.
934
954
break ;
955
+ case IdentifiedFileType::PSP_PBP_DIRECTORY:
956
+ // This should be a homebrew, which we now support as well.
957
+ // We select the homebrew hashing method.
958
+ homebrew = true ;
959
+ break ;
935
960
default :
936
961
// Other file types are not yet supported.
937
962
// TODO: Should we show an OSD popup here?
@@ -957,8 +982,14 @@ void SetGame(const Path &path, IdentifiedFileType fileType, FileLoader *fileLoad
957
982
g_gamePath = path;
958
983
g_isIdentifying = true ;
959
984
960
- // TODO: Fish the block device out of the loading process somewhere else. Though, probably easier to just do it here.
961
- {
985
+ if (homebrew) {
986
+ // Homebrew hashing method - just hash the eboot.
987
+ s_game_hash = ComputePSPHomebrewHash (fileLoader);
988
+ } else {
989
+ // ISO hashing method.
990
+ //
991
+ // TODO: Fish the block device out of the loading process somewhere else. Though, probably easier to just do it here,
992
+ // we need a temporary blockdevice anyway since it gets consumed by ComputePSPISOHash.
962
993
BlockDevice *blockDevice (constructBlockDevice (fileLoader));
963
994
if (!blockDevice) {
964
995
ERROR_LOG (ACHIEVEMENTS, " Failed to construct block device for '%s' - can't identify" , path.c_str ());
@@ -967,7 +998,7 @@ void SetGame(const Path &path, IdentifiedFileType fileType, FileLoader *fileLoad
967
998
}
968
999
969
1000
// This consumes the blockDevice.
970
- s_game_hash = ComputePSPHash (blockDevice);
1001
+ s_game_hash = ComputePSPISOHash (blockDevice);
971
1002
if (!s_game_hash.empty ()) {
972
1003
INFO_LOG (ACHIEVEMENTS, " Hash: %s" , s_game_hash.c_str ());
973
1004
}
@@ -1031,7 +1062,7 @@ void ChangeUMD(const Path &path, FileLoader *fileLoader) {
1031
1062
g_isIdentifying = true ;
1032
1063
1033
1064
// This consumes the blockDevice.
1034
- s_game_hash = ComputePSPHash (blockDevice);
1065
+ s_game_hash = ComputePSPISOHash (blockDevice);
1035
1066
if (s_game_hash.empty ()) {
1036
1067
ERROR_LOG (ACHIEVEMENTS, " Failed to hash - can't identify" );
1037
1068
return ;
0 commit comments