Created
August 28, 2020 01:10
-
-
Save maxton/3e84bfea2f779f32a76d0fcde95cfd6d to your computer and use it in GitHub Desktop.
Xenia patch for TB:RB fun
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/xenia/cpu/backend/x64/x64_sequences.cc b/src/xenia/cpu/backend/x64/x64_sequences.cc | |
index f6a688b0..4cc82d2d 100644 | |
--- a/src/xenia/cpu/backend/x64/x64_sequences.cc | |
+++ b/src/xenia/cpu/backend/x64/x64_sequences.cc | |
@@ -54,6 +54,112 @@ using xe::cpu::hir::Instr; | |
typedef bool (*SequenceSelectFn)(X64Emitter&, const Instr*); | |
std::unordered_map<uint32_t, SequenceSelectFn> sequence_table; | |
+typedef struct { | |
+ xe::be<uint32_t> vtbl; | |
+ xe::be<uint32_t> criticalSection; | |
+ uint8_t pad_8[32]; | |
+ xe::be<uint32_t> unk_28; | |
+ xe::be<uint32_t> unk_2C; | |
+ xe::be<uint32_t> mFile; | |
+ xe::be<uint32_t> mHeadersRead; | |
+ xe::be<uint32_t> mDecryptBuffer; | |
+ uint8_t mReadsEnabled; | |
+ uint8_t pad_3d[3]; | |
+ xe::be<uint32_t> mDecryptBufferLength; | |
+ uint8_t mNeedToInitDspState; | |
+ uint8_t mDone; | |
+ uint8_t pad_46[6]; | |
+ xe::be<uint32_t> mStdStream; | |
+ xe::be<uint32_t> mCloakware72; | |
+ xe::be<uint32_t> mOggStreamState; | |
+ xe::be<uint32_t> mVorbisInfo; | |
+ xe::be<uint32_t> mVorbisComment; | |
+ xe::be<uint32_t> mVorbisDspState; | |
+ xe::be<uint32_t> mVorbisBlock; | |
+ xe::be<uint32_t> mSeed1; | |
+ xe::be<uint32_t> mSeed2; | |
+ xe::be<uint32_t> mKeyIndex; | |
+ xe::be<uint32_t> mHmxaXor1; | |
+ xe::be<uint32_t> mHmxaXor2; | |
+ xe::be<uint32_t> mCloakwareHeaderData; | |
+ xe::be<uint32_t> mCloakwareHeaderLength; | |
+ xe::be<uint32_t> pad4; | |
+ uint8_t ogg_packet[32]; | |
+ uint8_t pad_a8[24]; | |
+ uint8_t mUnkDecodeFlag; | |
+ uint8_t pad_c1[3]; | |
+ xe::be<uint32_t> unk_c4; | |
+ xe::be<uint32_t> unk_c8; | |
+ xe::be<uint32_t> mOggMap; | |
+ uint8_t pad_d0[16]; | |
+ xe::be<uint32_t> mHmxHeaderSize; | |
+ xe::be<uint32_t> m90kBuf; | |
+ xe::be<uint32_t> mDecryptBuf314; | |
+ uint8_t mAesCounter[16]; | |
+ uint8_t pad_fc[18]; | |
+ uint8_t mFailed; | |
+ uint8_t unk_10f; | |
+ uint8_t pad_110[28]; | |
+ uint8_t mBeatlesEncrypted; | |
+ uint8_t pad_12d[3]; | |
+ xe::be<uint32_t> LCG_counter; | |
+ xe::be<uint32_t> mWbContext; | |
+} VorbisReader; | |
+ | |
+static_assert_size(VorbisReader, 312); | |
+ | |
+typedef struct { | |
+ xe::be<uint32_t> header; | |
+ xe::be<uint32_t> unk_0x4; | |
+ xe::be<uint32_t> unk_0x8; | |
+ xe::be<uint32_t> unk_0xc; | |
+ xe::be<uint32_t> header_len; | |
+ xe::be<uint32_t> unk_0x14; | |
+ xe::be<uint32_t> body; | |
+ xe::be<uint32_t> unk_0x1C; | |
+ xe::be<uint32_t> unk_0x20; | |
+ xe::be<uint32_t> body_len; | |
+} ogg_page; | |
+ | |
+// This function is called when the `sc 19` instruction is hit. | |
+// Patch these instructions in the XEX: | |
+// 0x829A4D6C (0x9A7D6C) 2C030000 cmpwi r3, 0 -> 44000262 sc 19 | |
+// 0x829A5748 (0x9A8748) 2C030000 cmpwi r3, 0 -> 44000262 sc 19 | |
+ | |
+// This function gets called right after cw_ogg_sync_pageout, | |
+// when the ogg_page is on the stack and points to the page | |
+// data in plaintext. It then dumps using the address of the VorbisReader | |
+// object as a filename because I'm too lazy to follow more pointers to | |
+// get to the mogg filename. | |
+static uint64_t breakReadPacket(void* raw_context) { | |
+ auto thread_state = *reinterpret_cast<ThreadState**>(raw_context); | |
+ auto* context = thread_state->context(); | |
+ auto r3 = context->r[3]; | |
+ if (r3 == 1) { | |
+ auto* vorbis_reader = | |
+ thread_state->memory()->TranslateVirtual<VorbisReader*>( | |
+ (uint32_t)context->r[31]); | |
+ if (vorbis_reader->mBeatlesEncrypted) { | |
+ auto* page = thread_state->memory()->TranslateVirtual<ogg_page*>( | |
+ (uint32_t)context->r[1] + 0x50); | |
+ auto length = page->header_len = page->body_len; | |
+ auto file = std::ofstream("vorbis-" + std::to_string(context->r[31]) + ".ogg", | |
+ std::ofstream::app | std::ofstream::binary); | |
+ auto* header = | |
+ thread_state->memory()->TranslateVirtual<const char*>(page->header); | |
+ auto* body = | |
+ thread_state->memory()->TranslateVirtual<const char*>(page->body); | |
+ file.write(header, body - header); | |
+ file.write(body, page->body_len); | |
+ } | |
+ } | |
+ // implement cmpwi that we patched | |
+ context->cr0.cr0_eq = (int)r3 == 0 ? 1 : 0; | |
+ context->cr0.cr0_gt = (int)r3 > 0 ? 1 : 0; | |
+ context->cr0.cr0_lt = (int)r3 < 0 ? 1 : 0; | |
+ return context->r[3]; | |
+} | |
+ | |
// ============================================================================ | |
// OPCODE_COMMENT | |
// ============================================================================ | |
@@ -61,6 +167,11 @@ struct COMMENT : Sequence<COMMENT, I<OPCODE_COMMENT, VoidOp, OffsetOp>> { | |
static void Emit(X64Emitter& e, const EmitArgType& i) { | |
if (IsTracingInstr()) { | |
auto str = reinterpret_cast<const char*>(i.src1.value); | |
+ auto cppstr = std::string(str); | |
+ if (cppstr == "SC19") { | |
+ e.CallNative(breakReadPacket); | |
+ return; | |
+ } | |
// TODO(benvanik): pass through. | |
// TODO(benvanik): don't just leak this memory. | |
auto str_copy = strdup(str); | |
diff --git a/src/xenia/cpu/backend/x64/x64_tracers.cc b/src/xenia/cpu/backend/x64/x64_tracers.cc | |
index 404f4eca..1340bc9b 100644 | |
--- a/src/xenia/cpu/backend/x64/x64_tracers.cc | |
+++ b/src/xenia/cpu/backend/x64/x64_tracers.cc | |
@@ -22,7 +22,7 @@ namespace cpu { | |
namespace backend { | |
namespace x64 { | |
-#define ITRACE 0 | |
+#define ITRACE 1 | |
#define DTRACE 0 | |
#define TARGET_THREAD 0 | |
diff --git a/src/xenia/cpu/ppc/ppc_emit_control.cc b/src/xenia/cpu/ppc/ppc_emit_control.cc | |
index 4452c55e..d0b1e858 100644 | |
--- a/src/xenia/cpu/ppc/ppc_emit_control.cc | |
+++ b/src/xenia/cpu/ppc/ppc_emit_control.cc | |
@@ -430,6 +430,10 @@ int InstrEmit_sc(PPCHIRBuilder& f, const InstrData& i) { | |
f.CallExtern(f.function()); | |
return 0; | |
} | |
+ if (i.SC.LEV > 2) { | |
+ f.Comment("SC" + std::to_string(i.SC.LEV)); | |
+ return 0; | |
+ } | |
XEINSTRNOTIMPLEMENTED(); | |
return 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment