ZeldaHLE: Support GBA crypto through command 0C. Reuses the pre-existing GBA crypto code from the separate UCode.
This commit is contained in:
parent
0b1af50316
commit
fbe727b0bb
|
@ -7,6 +7,81 @@
|
||||||
#include "Core/HW/DSPHLE/UCodes/GBA.h"
|
#include "Core/HW/DSPHLE/UCodes/GBA.h"
|
||||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||||
|
|
||||||
|
void ProcessGBACrypto(u32 address)
|
||||||
|
{
|
||||||
|
struct sec_params_t
|
||||||
|
{
|
||||||
|
u16 key[2];
|
||||||
|
u16 unk1[2];
|
||||||
|
u16 unk2[2];
|
||||||
|
u32 length;
|
||||||
|
u32 dest_addr;
|
||||||
|
u32 pad[3];
|
||||||
|
} sec_params;
|
||||||
|
|
||||||
|
// 32 bytes from mram addr to DRAM @ 0
|
||||||
|
for (int i = 0; i < 8; i++, address += 4)
|
||||||
|
((u32*)&sec_params)[i] = HLEMemory_Read_U32(address);
|
||||||
|
|
||||||
|
// This is the main decrypt routine
|
||||||
|
u16 x11 = 0, x12 = 0,
|
||||||
|
x20 = 0, x21 = 0, x22 = 0, x23 = 0;
|
||||||
|
|
||||||
|
x20 = Common::swap16(sec_params.key[0]) ^ 0x6f64;
|
||||||
|
x21 = Common::swap16(sec_params.key[1]) ^ 0x6573;
|
||||||
|
|
||||||
|
s16 unk2 = (s8)sec_params.unk2[0];
|
||||||
|
if (unk2 < 0)
|
||||||
|
{
|
||||||
|
x11 = ((~unk2 + 3) << 1) | (sec_params.unk1[0] << 4);
|
||||||
|
}
|
||||||
|
else if (unk2 == 0)
|
||||||
|
{
|
||||||
|
x11 = (sec_params.unk1[0] << 1) | 0x70;
|
||||||
|
}
|
||||||
|
else // unk2 > 0
|
||||||
|
{
|
||||||
|
x11 = ((unk2 - 1) << 1) | (sec_params.unk1[0] << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 rounded_sub = ((sec_params.length + 7) & ~7) - 0x200;
|
||||||
|
u16 size = (rounded_sub < 0) ? 0 : rounded_sub >> 3;
|
||||||
|
|
||||||
|
u32 t = (((size << 16) | 0x3f80) & 0x3f80ffff) << 1;
|
||||||
|
s16 t_low = (s8)(t >> 8);
|
||||||
|
t += (t_low & size) << 16;
|
||||||
|
x12 = t >> 16;
|
||||||
|
x11 |= (size & 0x4000) >> 14; // this would be stored in ac0.h if we weren't constrained to 32bit :)
|
||||||
|
t = ((x11 & 0xff) << 16) + ((x12 & 0xff) << 16) + (x12 << 8);
|
||||||
|
|
||||||
|
u16 final11 = 0, final12 = 0;
|
||||||
|
final11 = x11 | ((t >> 8) & 0xff00) | 0x8080;
|
||||||
|
final12 = x12 | 0x8080;
|
||||||
|
|
||||||
|
if ((final12 & 0x200) != 0)
|
||||||
|
{
|
||||||
|
x22 = final11 ^ 0x6f64;
|
||||||
|
x23 = final12 ^ 0x6573;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x22 = final11 ^ 0x6177;
|
||||||
|
x23 = final12 ^ 0x614b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the result back to mram
|
||||||
|
*(u32*)HLEMemory_Get_Pointer(sec_params.dest_addr) = Common::swap32((x20 << 16) | x21);
|
||||||
|
*(u32*)HLEMemory_Get_Pointer(sec_params.dest_addr+4) = Common::swap32((x22 << 16) | x23);
|
||||||
|
|
||||||
|
// Done!
|
||||||
|
DEBUG_LOG(DSPHLE, "\n%08x -> key: %08x, len: %08x, dest_addr: %08x, unk1: %08x, unk2: %08x"
|
||||||
|
" 22: %04x, 23: %04x",
|
||||||
|
address,
|
||||||
|
*(u32*)sec_params.key, sec_params.length, sec_params.dest_addr,
|
||||||
|
*(u32*)sec_params.unk1, *(u32*)sec_params.unk2,
|
||||||
|
x22, x23);
|
||||||
|
}
|
||||||
|
|
||||||
GBAUCode::GBAUCode(DSPHLE *dsphle, u32 crc)
|
GBAUCode::GBAUCode(DSPHLE *dsphle, u32 crc)
|
||||||
: UCodeInterface(dsphle, crc)
|
: UCodeInterface(dsphle, crc)
|
||||||
{
|
{
|
||||||
|
@ -48,79 +123,8 @@ void GBAUCode::HandleMail(u32 mail)
|
||||||
else if (nextmail_is_mramaddr)
|
else if (nextmail_is_mramaddr)
|
||||||
{
|
{
|
||||||
nextmail_is_mramaddr = false;
|
nextmail_is_mramaddr = false;
|
||||||
u32 mramaddr = mail;
|
|
||||||
|
|
||||||
struct sec_params_t
|
ProcessGBACrypto(mail);
|
||||||
{
|
|
||||||
u16 key[2];
|
|
||||||
u16 unk1[2];
|
|
||||||
u16 unk2[2];
|
|
||||||
u32 length;
|
|
||||||
u32 dest_addr;
|
|
||||||
u32 pad[3];
|
|
||||||
} sec_params;
|
|
||||||
|
|
||||||
// 32 bytes from mram addr to DRAM @ 0
|
|
||||||
for (int i = 0; i < 8; i++, mramaddr += 4)
|
|
||||||
((u32*)&sec_params)[i] = HLEMemory_Read_U32(mramaddr);
|
|
||||||
|
|
||||||
// This is the main decrypt routine
|
|
||||||
u16 x11 = 0, x12 = 0,
|
|
||||||
x20 = 0, x21 = 0, x22 = 0, x23 = 0;
|
|
||||||
|
|
||||||
x20 = Common::swap16(sec_params.key[0]) ^ 0x6f64;
|
|
||||||
x21 = Common::swap16(sec_params.key[1]) ^ 0x6573;
|
|
||||||
|
|
||||||
s16 unk2 = (s8)sec_params.unk2[0];
|
|
||||||
if (unk2 < 0)
|
|
||||||
{
|
|
||||||
x11 = ((~unk2 + 3) << 1) | (sec_params.unk1[0] << 4);
|
|
||||||
}
|
|
||||||
else if (unk2 == 0)
|
|
||||||
{
|
|
||||||
x11 = (sec_params.unk1[0] << 1) | 0x70;
|
|
||||||
}
|
|
||||||
else // unk2 > 0
|
|
||||||
{
|
|
||||||
x11 = ((unk2 - 1) << 1) | (sec_params.unk1[0] << 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 rounded_sub = ((sec_params.length + 7) & ~7) - 0x200;
|
|
||||||
u16 size = (rounded_sub < 0) ? 0 : rounded_sub >> 3;
|
|
||||||
|
|
||||||
u32 t = (((size << 16) | 0x3f80) & 0x3f80ffff) << 1;
|
|
||||||
s16 t_low = (s8)(t >> 8);
|
|
||||||
t += (t_low & size) << 16;
|
|
||||||
x12 = t >> 16;
|
|
||||||
x11 |= (size & 0x4000) >> 14; // this would be stored in ac0.h if we weren't constrained to 32bit :)
|
|
||||||
t = ((x11 & 0xff) << 16) + ((x12 & 0xff) << 16) + (x12 << 8);
|
|
||||||
|
|
||||||
u16 final11 = 0, final12 = 0;
|
|
||||||
final11 = x11 | ((t >> 8) & 0xff00) | 0x8080;
|
|
||||||
final12 = x12 | 0x8080;
|
|
||||||
|
|
||||||
if ((final12 & 0x200) != 0)
|
|
||||||
{
|
|
||||||
x22 = final11 ^ 0x6f64;
|
|
||||||
x23 = final12 ^ 0x6573;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x22 = final11 ^ 0x6177;
|
|
||||||
x23 = final12 ^ 0x614b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the result back to mram
|
|
||||||
*(u32*)HLEMemory_Get_Pointer(sec_params.dest_addr) = Common::swap32((x20 << 16) | x21);
|
|
||||||
*(u32*)HLEMemory_Get_Pointer(sec_params.dest_addr+4) = Common::swap32((x22 << 16) | x23);
|
|
||||||
|
|
||||||
// Done!
|
|
||||||
DEBUG_LOG(DSPHLE, "\n%08x -> key: %08x, len: %08x, dest_addr: %08x, unk1: %08x, unk2: %08x"
|
|
||||||
" 22: %04x, 23: %04x",
|
|
||||||
mramaddr,
|
|
||||||
*(u32*)sec_params.key, sec_params.length, sec_params.dest_addr,
|
|
||||||
*(u32*)sec_params.unk1, *(u32*)sec_params.unk2,
|
|
||||||
x22, x23);
|
|
||||||
|
|
||||||
calc_done = true;
|
calc_done = true;
|
||||||
m_mail_handler.PushMail(DSP_DONE);
|
m_mail_handler.PushMail(DSP_DONE);
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||||
|
|
||||||
|
// Computes two 32 bit integers to be returned to the game, based on the
|
||||||
|
// provided crypto parameters at the provided MRAM address. The integers are
|
||||||
|
// written back to RAM at the dest address provided in the crypto parameters.
|
||||||
|
void ProcessGBACrypto(u32 address);
|
||||||
|
|
||||||
struct GBAUCode : public UCodeInterface
|
struct GBAUCode : public UCodeInterface
|
||||||
{
|
{
|
||||||
GBAUCode(DSPHLE *dsphle, u32 crc);
|
GBAUCode(DSPHLE *dsphle, u32 crc);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/HW/DSPHLE/MailHandler.h"
|
#include "Core/HW/DSPHLE/MailHandler.h"
|
||||||
|
#include "Core/HW/DSPHLE/UCodes/GBA.h"
|
||||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||||
#include "Core/HW/DSPHLE/UCodes/Zelda.h"
|
#include "Core/HW/DSPHLE/UCodes/Zelda.h"
|
||||||
|
|
||||||
|
@ -474,8 +475,7 @@ void ZeldaUCode::RunPendingCommands()
|
||||||
case 0x0C:
|
case 0x0C:
|
||||||
if (m_flags & SUPPORTS_GBA_CRYPTO)
|
if (m_flags & SUPPORTS_GBA_CRYPTO)
|
||||||
{
|
{
|
||||||
// TODO
|
ProcessGBACrypto(Read32());
|
||||||
NOTICE_LOG(DSPHLE, "Received an unhandled GBA crypto command, param: %08x", Read32());
|
|
||||||
}
|
}
|
||||||
else if (m_flags & WEIRD_CMD_0C)
|
else if (m_flags & WEIRD_CMD_0C)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue