- Added a new wilcard for importing savegames, which basically shows all saves (gci, gcs and sav). This is set as default (I really got frustrated of having to change the type every single time when making tests for GCMM, and I think it makes more sense at user level to just show all saves regardless the format)
- In icon retrieving I removed the "format check" as it shouldn't really matter to have mixed icon formats. Also removed the "Time splitters hack" as there's no reason for it since we are only checking the last 3 bits and I'm pretty sure having bits 1 and 2 set is the same as having them unset. - Icon retrieving uses AnimSpeed as stop signal (every icon must have an speed set, the first speed that is 0 means there are no more icons) - Also, in icon retrieving I added support for "blank frames"(Luigi's Mansion and Pikmin that I know of). With this the base for icon animation is complete. - Fixed PSOIII savegame patch which was wrong before. Signed-off-by: LPFaint99 <lpfaint99@gmail.com>
This commit is contained in:
parent
5dd49edaec
commit
d032c40a58
|
@ -31,7 +31,7 @@ const int lut3to8[] = { 0x00,0x24,0x48,0x6D,0x91,0xB6,0xDA,0xFF };
|
||||||
|
|
||||||
u32 Decode5A3(u16 val)
|
u32 Decode5A3(u16 val)
|
||||||
{
|
{
|
||||||
const u32 bg_color = 0x00000000;
|
const u32 bg_color = 0xFFFFFFFF;
|
||||||
|
|
||||||
int r, g, b, a;
|
int r, g, b, a;
|
||||||
|
|
||||||
|
|
|
@ -473,11 +473,20 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 GCMemcard::DEntry_AnimSpeed(u8 index) const
|
std::string GCMemcard::DEntry_AnimSpeed(u8 index) const
|
||||||
{
|
{
|
||||||
if (!m_valid || index > DIRLEN)
|
if (!m_valid || index > DIRLEN)
|
||||||
return 0xFF;
|
return "";
|
||||||
return BE16(CurrentDir->Dir[index].AnimSpeed);
|
int x = CurrentDir->Dir[index].AnimSpeed[0];
|
||||||
|
std::string speed;
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (i == 8) x = CurrentDir->Dir[index].AnimSpeed[1];
|
||||||
|
speed.push_back((x & 0x80) ? '1' : '0');
|
||||||
|
x = x << 1;
|
||||||
|
}
|
||||||
|
speed.push_back(0);
|
||||||
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GCMemcard::DEntry_Permissions(u8 index) const
|
std::string GCMemcard::DEntry_Permissions(u8 index) const
|
||||||
|
@ -1086,15 +1095,18 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const
|
||||||
|
|
||||||
// To ensure only one type of icon is used
|
// To ensure only one type of icon is used
|
||||||
// Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon
|
// Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon
|
||||||
int fmtCheck = 0;
|
//int fmtCheck = 0;
|
||||||
|
|
||||||
int formats = BE16(CurrentDir->Dir[index].IconFmt);
|
int formats = BE16(CurrentDir->Dir[index].IconFmt);
|
||||||
int fdelays = BE16(CurrentDir->Dir[index].AnimSpeed);
|
int fdelays = BE16(CurrentDir->Dir[index].AnimSpeed);
|
||||||
|
|
||||||
int flags = CurrentDir->Dir[index].BIFlags;
|
int flags = CurrentDir->Dir[index].BIFlags;
|
||||||
// Timesplitters 2 is the only game that I see this in
|
// Timesplitters 2 and 3 is the only game that I see this in
|
||||||
// May be a hack
|
// May be a hack
|
||||||
if (flags == 0xFB) flags = ~flags;
|
//if (flags == 0xFB) flags = ~flags;
|
||||||
|
// Batten Kaitos has 0x65 as flag too. Everything but the first 3 bytes seems irrelevant.
|
||||||
|
// Something similar happens with Wario Ware Inc. AnimSpeed
|
||||||
|
|
||||||
int bnrFormat = (flags&3);
|
int bnrFormat = (flags&3);
|
||||||
|
|
||||||
u32 DataOffset = BE32(CurrentDir->Dir[index].ImageOffset);
|
u32 DataOffset = BE32(CurrentDir->Dir[index].ImageOffset);
|
||||||
|
@ -1110,7 +1122,6 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const
|
||||||
switch (bnrFormat)
|
switch (bnrFormat)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
case 3:
|
|
||||||
animData += 96*32 + 2*256; // image+palette
|
animData += 96*32 + 2*256; // image+palette
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -1122,40 +1133,48 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const
|
||||||
u8* data[8];
|
u8* data[8];
|
||||||
int frames = 0;
|
int frames = 0;
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
fmts[i] = (formats >> (2*i))&3;
|
fmts[i] = (formats >> (2*i))&3;
|
||||||
delays[i] = ((fdelays >> (2*i))&3) << 2;
|
delays[i] = ((fdelays >> (2*i))&3);
|
||||||
data[i] = animData;
|
data[i] = animData;
|
||||||
|
|
||||||
if (!fmtCheck) fmtCheck = fmts[i];
|
if (!delays[i])
|
||||||
if (fmtCheck == fmts[i])
|
{
|
||||||
|
//First icon_speed = 0 indicates there aren't any more icons
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//If speed is set there is an icon (it can be a "blank frame")
|
||||||
|
frames++;
|
||||||
|
if (fmts[i] != 0)
|
||||||
{
|
{
|
||||||
switch (fmts[i])
|
switch (fmts[i])
|
||||||
{
|
{
|
||||||
case CI8SHARED: // CI8 with shared palette
|
case CI8SHARED: // CI8 with shared palette
|
||||||
animData += 32*32;
|
animData += 32*32;
|
||||||
frames++;
|
|
||||||
break;
|
break;
|
||||||
case RGB5A3: // RGB5A3
|
case RGB5A3: // RGB5A3
|
||||||
animData += 32*32*2;
|
animData += 32*32*2;
|
||||||
frames++;
|
|
||||||
break;
|
break;
|
||||||
case CI8: // CI8 with own palette
|
case CI8: // CI8 with own palette
|
||||||
animData += 32*32 + 2*256;
|
animData += 32*32 + 2*256;
|
||||||
frames++;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u16* sharedPal = (u16*)(animData);
|
u16* sharedPal = (u16*)(animData);
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (fmtCheck == fmts[i])
|
if (!delays[i])
|
||||||
|
{
|
||||||
|
//First icon_speed = 0 indicates there aren't any more icons
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fmts[i] != 0)
|
||||||
{
|
{
|
||||||
switch (fmts[i])
|
switch (fmts[i])
|
||||||
{
|
{
|
||||||
|
@ -1165,6 +1184,7 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const
|
||||||
break;
|
break;
|
||||||
case RGB5A3: // RGB5A3
|
case RGB5A3: // RGB5A3
|
||||||
decode5A3image(buffer, (u16*)(data[i]), 32, 32);
|
decode5A3image(buffer, (u16*)(data[i]), 32, 32);
|
||||||
|
buffer += 32*32;
|
||||||
break;
|
break;
|
||||||
case CI8: // CI8 with own palette
|
case CI8: // CI8 with own palette
|
||||||
u16 *paldata = (u16*)(data[i] + 32*32);
|
u16 *paldata = (u16*)(data[i] + 32*32);
|
||||||
|
@ -1173,6 +1193,33 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Speed is set but there's no actual icon
|
||||||
|
//This is used to reduce animation speed in Pikmin and Luigi's Mansion for example
|
||||||
|
//These "blank frames" show the next icon
|
||||||
|
for(j=i; j<8;++j)
|
||||||
|
{
|
||||||
|
if (fmts[j] != 0)
|
||||||
|
{
|
||||||
|
switch (fmts[j])
|
||||||
|
{
|
||||||
|
case CI8SHARED: // CI8 with shared palette
|
||||||
|
decodeCI8image(buffer,data[j],sharedPal,32,32);
|
||||||
|
break;
|
||||||
|
case RGB5A3: // RGB5A3
|
||||||
|
decode5A3image(buffer, (u16*)(data[j]), 32, 32);
|
||||||
|
buffer += 32*32;
|
||||||
|
break;
|
||||||
|
case CI8: // CI8 with own palette
|
||||||
|
u16 *paldata = (u16*)(data[j] + 32*32);
|
||||||
|
decodeCI8image(buffer, data[j], paldata, 32, 32);
|
||||||
|
buffer += 32*32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames;
|
return frames;
|
||||||
|
@ -1269,7 +1316,6 @@ void GCMemcard::FormatInternal(GCMC_Header &GCP)
|
||||||
calc_checksumsBE((u16*)p_bat_backup+2, 0xFFE, &p_bat_backup->Checksum, &p_bat_backup->Checksum_Inv);
|
calc_checksumsBE((u16*)p_bat_backup+2, 0xFFE, &p_bat_backup->Checksum, &p_bat_backup->Checksum_Inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GCMemcard::CARD_GetSerialNo(u32 *serial1,u32 *serial2)
|
void GCMemcard::CARD_GetSerialNo(u32 *serial1,u32 *serial2)
|
||||||
{
|
{
|
||||||
u32 serial[8];
|
u32 serial[8];
|
||||||
|
@ -1349,7 +1395,7 @@ s32 GCMemcard::PSO_MakeSaveGameValid(DEntry& direntry, std::vector<GCMBlock> &Fi
|
||||||
if (strcmp((char*)direntry.Filename,"PSO_SYSTEM")!=0)
|
if (strcmp((char*)direntry.Filename,"PSO_SYSTEM")!=0)
|
||||||
{
|
{
|
||||||
// check for PSO3 system file
|
// check for PSO3 system file
|
||||||
if (strcmp((char*)&FileBuffer[0].block[0x08],"PSO3_SYSTEM")==0)
|
if (strcmp((char*)direntry.Filename,"PSO3_SYSTEM")==0)
|
||||||
{
|
{
|
||||||
// PSO3 data block size adjustment
|
// PSO3 data block size adjustment
|
||||||
pso3offset = 0x10;
|
pso3offset = 0x10;
|
||||||
|
|
|
@ -116,8 +116,8 @@ private:
|
||||||
// bits 0 and 1: image format
|
// bits 0 and 1: image format
|
||||||
// 00 no banner
|
// 00 no banner
|
||||||
// 01 CI8 banner
|
// 01 CI8 banner
|
||||||
// 01 RGB5A3 banner
|
// 10 RGB5A3 banner
|
||||||
// 11 ? maybe ==01? haven't seen it
|
// 11 ? maybe ==00? Time Splitters 2 and 3 have it and don't have banner
|
||||||
//
|
//
|
||||||
u8 Filename[DENTRY_STRLEN]; //0x08 0x20 filename
|
u8 Filename[DENTRY_STRLEN]; //0x08 0x20 filename
|
||||||
u8 ModTime[4]; //0x28 0x04 Time of file's last modification in seconds since 12am, January 1st, 2000
|
u8 ModTime[4]; //0x28 0x04 Time of file's last modification in seconds since 12am, January 1st, 2000
|
||||||
|
@ -213,7 +213,7 @@ public:
|
||||||
u32 DEntry_ModTime(u8 index) const;
|
u32 DEntry_ModTime(u8 index) const;
|
||||||
u32 DEntry_ImageOffset(u8 index) const;
|
u32 DEntry_ImageOffset(u8 index) const;
|
||||||
std::string DEntry_IconFmt(u8 index) const;
|
std::string DEntry_IconFmt(u8 index) const;
|
||||||
u16 DEntry_AnimSpeed(u8 index) const;
|
std::string DEntry_AnimSpeed(u8 index) const;
|
||||||
std::string DEntry_Permissions(u8 index) const;
|
std::string DEntry_Permissions(u8 index) const;
|
||||||
u8 DEntry_CopyCounter(u8 index) const;
|
u8 DEntry_CopyCounter(u8 index) const;
|
||||||
// get first block for file
|
// get first block for file
|
||||||
|
|
|
@ -520,6 +520,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
||||||
? wxString::FromAscii("")
|
? wxString::FromAscii("")
|
||||||
: wxString::From8BitData(DefaultIOPath.c_str()),
|
: wxString::From8BitData(DefaultIOPath.c_str()),
|
||||||
wxEmptyString, wxEmptyString,
|
wxEmptyString, wxEmptyString,
|
||||||
|
_("GameCube Savegame files(*.gci;*.gcs;*.sav)") + wxString(wxT("|*.gci;*.gcs;*.sav|")) +
|
||||||
_("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) +
|
_("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) +
|
||||||
_("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) +
|
_("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) +
|
||||||
_("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")),
|
_("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")),
|
||||||
|
|
Loading…
Reference in New Issue