Skip to content

Instantly share code, notes, and snippets.

@maxton
Created August 28, 2020 01:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maxton/3e84bfea2f779f32a76d0fcde95cfd6d to your computer and use it in GitHub Desktop.
Save maxton/3e84bfea2f779f32a76d0fcde95cfd6d to your computer and use it in GitHub Desktop.
Xenia patch for TB:RB fun
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