mirror of
https://github.com/open-goal/jak-project
synced 2026-07-07 22:22:21 -04:00
[graphics] MERC (#1124)
* merc dma generation * wip very early version of merc * small fixes * fix * fix more merc bugs * derp fixed min * oops we did need something weird on max * merc for everything * program optimization 1 * more optimization * windows * windows 2 * clean up * fix test * BLERC
This commit is contained in:
+2
-3
@@ -53,7 +53,7 @@ std::string VifCode::print() {
|
||||
result = "FLUSHA";
|
||||
break;
|
||||
case Kind::MSCAL:
|
||||
result = "MSCAL";
|
||||
result = fmt::format("MSCAL 0x{:x}", immediate);
|
||||
break;
|
||||
case Kind::MSCNT:
|
||||
result = "MSCNT";
|
||||
@@ -109,10 +109,9 @@ std::string VifCode::print() {
|
||||
|
||||
default:
|
||||
fmt::print("Unhandled vif code {}\n", (int)kind);
|
||||
assert(false);
|
||||
|
||||
result = "???";
|
||||
// assert(false);
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
// TODO: the rest of the VIF code.
|
||||
|
||||
@@ -52,6 +52,48 @@ struct DmaTag {
|
||||
std::string print();
|
||||
};
|
||||
|
||||
inline void emulate_dma(const void* source_base, void* dest_base, u32 tadr, u32 dadr) {
|
||||
const u8* src = (const u8*)source_base;
|
||||
u8* dst = (u8*)dest_base;
|
||||
|
||||
u32 dest_offset = dadr;
|
||||
while (true) {
|
||||
u64 tag_data;
|
||||
memcpy(&tag_data, src + tadr, 8);
|
||||
DmaTag tag(tag_data);
|
||||
|
||||
switch (tag.kind) {
|
||||
case DmaTag::Kind::CNT:
|
||||
memcpy(dst + dest_offset, src + tadr, (1 + tag.qwc) * 16);
|
||||
dest_offset += (1 + tag.qwc) * 16;
|
||||
tadr += 16 + tag.qwc * 16;
|
||||
break;
|
||||
case DmaTag::Kind::REF: {
|
||||
// tte
|
||||
memcpy(dst + dest_offset, src + tadr, 16);
|
||||
dest_offset += 16;
|
||||
|
||||
memcpy(dst + dest_offset, src + tag.addr, tag.qwc * 16);
|
||||
dest_offset += tag.qwc * 16;
|
||||
tadr += 16;
|
||||
} break;
|
||||
case DmaTag::Kind::REFE: {
|
||||
// tte
|
||||
memcpy(dst + dest_offset, src + tadr, 16);
|
||||
dest_offset += 16;
|
||||
|
||||
memcpy(dst + dest_offset, src + tag.addr, tag.qwc * 16);
|
||||
dest_offset += tag.qwc * 16;
|
||||
tadr += 16;
|
||||
return;
|
||||
} break;
|
||||
default:
|
||||
printf("bad tag: %d\n", (int)tag.kind);
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct VifCode {
|
||||
enum class Kind : u8 {
|
||||
NOP = 0b0,
|
||||
|
||||
@@ -575,8 +575,286 @@ char bc_to_part(int x) {
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
std::string mask_to_string(u8 val) {
|
||||
std::string result;
|
||||
if (val & 8) {
|
||||
result += 'x';
|
||||
}
|
||||
if (val & 4) {
|
||||
result += 'y';
|
||||
}
|
||||
if (val & 2) {
|
||||
result += 'z';
|
||||
}
|
||||
if (val & 1) {
|
||||
result += 'w';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int unk = 0;
|
||||
std::string VuDisassembler::to_cpp(const VuInstruction& instr) const {
|
||||
switch (instr.kind) {
|
||||
case VuInstrK::NOP:
|
||||
case VuInstrK::LOWER_NOP:
|
||||
return "/* nop */";
|
||||
case VuInstrK::LQ:
|
||||
if (instr.src.at(1).is_int_reg(0)) {
|
||||
return fmt::format("lq_buffer(Mask::{}, vu.{}, {});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
} else if (instr.src.at(0).value() == 0) {
|
||||
return fmt::format("lq_buffer(Mask::{}, vu.{}, vu.{});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
} else {
|
||||
return fmt::format("lq_buffer(Mask::{}, vu.{}, vu.{} + {});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
}
|
||||
goto unknown;
|
||||
case VuInstrK::LQI:
|
||||
return fmt::format("lq_buffer(Mask::{}, vu.{}, vu.{}++);", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
case VuInstrK::SQI:
|
||||
return fmt::format("sq_buffer(Mask::{}, vu.{}, vu.{}++);", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
case VuInstrK::SQ:
|
||||
if (instr.src.at(1).is_int_reg(0)) {
|
||||
return fmt::format("sq_buffer(Mask::{}, vu.{}, {});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
} else if (instr.src.at(0).value() == 0) {
|
||||
return fmt::format("sq_buffer(Mask::{}, vu.{}, vu.{});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
} else {
|
||||
return fmt::format("sq_buffer(Mask::{}, vu.{}, vu.{} + {});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
}
|
||||
goto unknown;
|
||||
case VuInstrK::IADDI:
|
||||
if (instr.src.at(0).is_int_reg(0)) {
|
||||
return fmt::format("vu.{} = {};", instr.dst->to_string(m_label_names),
|
||||
(s16)instr.src.at(1).value());
|
||||
} else {
|
||||
return fmt::format("vu.{} = vu.{} + {};", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names), (s16)instr.src.at(1).value());
|
||||
}
|
||||
|
||||
case VuInstrK::IADDIU:
|
||||
if (instr.src.at(0).is_int_reg(0)) {
|
||||
return fmt::format("vu.{} = 0x{:x}; /* {} */\n", instr.dst->to_string(m_label_names),
|
||||
(u16)instr.src.at(1).value(), instr.src.at(1).value());
|
||||
} else {
|
||||
return fmt::format("vu.{} = vu.{} + 0x{:x}; /* {} */", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names), (u16)instr.src.at(1).value(),
|
||||
instr.src.at(1).value());
|
||||
}
|
||||
|
||||
case VuInstrK::ISW:
|
||||
if (instr.src.at(2).is_int_reg(0)) {
|
||||
return fmt::format("isw_buffer(Mask::{}, vu.{}, {});", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
} else {
|
||||
return fmt::format("isw_buffer(Mask::{}, vu.{}, vu.{} + {});", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(2).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
}
|
||||
goto unknown;
|
||||
|
||||
case VuInstrK::ISWR:
|
||||
return fmt::format("isw_buffer(Mask::{}, vu.{}, vu.{});", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::ILWR:
|
||||
return fmt::format("ilw_buffer(Mask::{}, vu.{}, vu.{});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::ILW:
|
||||
if (instr.src.at(1).is_int_reg(0)) {
|
||||
return fmt::format("ilw_buffer(Mask::{}, vu.{}, {});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
} else {
|
||||
return fmt::format("ilw_buffer(Mask::{}, vu.{}, vu.{} + {});", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
}
|
||||
|
||||
case VuInstrK::ISUBIU:
|
||||
if (instr.src.at(0).is_int_reg(0)) {
|
||||
return fmt::format("vu.{} = -{};\n", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(1).value());
|
||||
} else {
|
||||
return fmt::format("vu.{} = vu.{} - 0x{:x}; /* {} */", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names), (u16)instr.src.at(1).value(),
|
||||
instr.src.at(1).value());
|
||||
}
|
||||
|
||||
case VuInstrK::MTIR:
|
||||
return fmt::format("vu.{} = vu.{}.{}_as_u16();", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
bc_to_part(*instr.first_src_field));
|
||||
|
||||
case VuInstrK::MFIR:
|
||||
return fmt::format("vu.{}.mfir(Mask::{}, vu.{});", instr.dst->to_string(m_label_names),
|
||||
mask_to_string(*instr.mask), instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::B:
|
||||
return fmt::format("bc = true;", instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::IBGTZ:
|
||||
return fmt::format("bc = ((s16)vu.{}) > 0;", instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::IBGEZ:
|
||||
return fmt::format("bc = ((s16)vu.{}) >= 0;", instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::IBEQ:
|
||||
if (instr.src.at(0).is_int_reg(0)) {
|
||||
return fmt::format("bc = (vu.{} == 0);", instr.src.at(1).to_string(m_label_names));
|
||||
} else {
|
||||
return fmt::format("bc = (vu.{} == vu.{});", instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
}
|
||||
|
||||
case VuInstrK::IBNE:
|
||||
if (instr.src.at(0).is_int_reg(0)) {
|
||||
return fmt::format("bc = (vu.{} != 0);", instr.src.at(1).to_string(m_label_names));
|
||||
} else {
|
||||
return fmt::format("bc = (vu.{} != vu.{});", instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
}
|
||||
|
||||
case VuInstrK::IADD:
|
||||
return fmt::format("vu.{} = vu.{} + vu.{};", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
case VuInstrK::ISUB:
|
||||
return fmt::format("vu.{} = vu.{} - vu.{};", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
case VuInstrK::IAND:
|
||||
return fmt::format("vu.{} = vu.{} & vu.{};", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
case VuInstrK::IOR:
|
||||
if (instr.src.at(1).is_int_reg(0)) {
|
||||
return fmt::format("vu.{} = vu.{};", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
} else {
|
||||
goto unknown;
|
||||
}
|
||||
|
||||
case VuInstrK::MFP:
|
||||
return fmt::format("vu.{}.mfp(Mask::{}, vu.P);", instr.dst->to_string(m_label_names),
|
||||
mask_to_string(*instr.mask));
|
||||
|
||||
case VuInstrK::MULq:
|
||||
return fmt::format("vu.{}.mul(Mask::{}, vu.{}, vu.Q); /* TODO mulq */",
|
||||
instr.dst->to_string(m_label_names), mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
case VuInstrK::DIV:
|
||||
return fmt::format(
|
||||
"vu.Q = vu.{}.{}() / vu.{}.{}();\n", instr.src.at(0).to_string(m_label_names),
|
||||
bc_to_part(*instr.first_src_field), instr.src.at(1).to_string(m_label_names),
|
||||
bc_to_part(*instr.second_src_field));
|
||||
|
||||
case VuInstrK::ERLENG:
|
||||
return fmt::format("vu.P = erleng(Mask::{}, vu.{}); /* TODO erleng */",
|
||||
mask_to_string(*instr.mask), instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::MR32:
|
||||
case VuInstrK::MOVE:
|
||||
case VuInstrK::ITOF0:
|
||||
case VuInstrK::ITOF15:
|
||||
case VuInstrK::FTOI0:
|
||||
case VuInstrK::FTOI4:
|
||||
return fmt::format("vu.{}.{}(Mask::{}, vu.{});", instr.dst->to_string(m_label_names),
|
||||
info(instr.kind).name, mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::ADDbc:
|
||||
case VuInstrK::MULbc:
|
||||
case VuInstrK::MINIbc:
|
||||
case VuInstrK::MAXbc:
|
||||
return fmt::format("vu.{}.{}(Mask::{}, vu.{}, vu.{}.{}());",
|
||||
instr.dst->to_string(m_label_names), info(instr.kind).name,
|
||||
mask_to_string(*instr.mask), instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names), bc_to_part(*instr.bc));
|
||||
|
||||
case VuInstrK::FP_CONSTANT:
|
||||
return fmt::format("vu.I = {};", float_to_string(instr.fp));
|
||||
|
||||
case VuInstrK::MINIi:
|
||||
case VuInstrK::MAXi:
|
||||
return fmt::format("vu.{}.{}(Mask::{}, vu.{}, vu.I);", instr.dst->to_string(m_label_names),
|
||||
info(instr.kind).name, mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::MUL:
|
||||
case VuInstrK::ADD:
|
||||
case VuInstrK::MAX:
|
||||
case VuInstrK::MINI:
|
||||
return fmt::format("vu.{}.{}(Mask::{}, vu.{}, vu.{});", instr.dst->to_string(m_label_names),
|
||||
info(instr.kind).name, mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::ADDAbc:
|
||||
return fmt::format("vu.acc.adda(Mask::{}, vu.{}, vu.{}.{}());", mask_to_string(*instr.mask),
|
||||
instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names), bc_to_part(*instr.bc));
|
||||
case VuInstrK::MADDA:
|
||||
return fmt::format("vu.acc.madda(Mask::{}, vu.{}, vu.{});", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
case VuInstrK::MADDAbc:
|
||||
return fmt::format("vu.acc.madda(Mask::{}, vu.{}, vu.{}.{}());", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names), bc_to_part(*instr.bc));
|
||||
case VuInstrK::MADDbc:
|
||||
return fmt::format("vu.acc.madd(Mask::{}, vu.{}, vu.{}, vu.{}.{}());",
|
||||
mask_to_string(*instr.mask), instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names), bc_to_part(*instr.bc));
|
||||
case VuInstrK::MULA:
|
||||
return fmt::format("vu.acc.mula(Mask::{}, vu.{}, vu.{});", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
case VuInstrK::MULAbc:
|
||||
return fmt::format("vu.acc.mula(Mask::{}, vu.{}, vu.{}.{}());", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names), bc_to_part(*instr.bc));
|
||||
|
||||
case VuInstrK::XGKICK:
|
||||
return fmt::format("xgkick(vu.{});", instr.src.at(0).to_string(m_label_names));
|
||||
|
||||
case VuInstrK::XTOP:
|
||||
return fmt::format("vu.{} = xtop();", instr.src.at(0).to_string(m_label_names));
|
||||
default:
|
||||
unk++;
|
||||
return "???";
|
||||
}
|
||||
|
||||
unknown:
|
||||
|
||||
unk++;
|
||||
return "???";
|
||||
}
|
||||
|
||||
std::string VuDisassembler::to_string(const VuInstruction& instr) const {
|
||||
if (instr.kind == VuInstrK::FP_CONSTANT) {
|
||||
return float_to_string(instr.fp);
|
||||
@@ -719,6 +997,11 @@ int VuDisassembler::add_label(int instr) {
|
||||
}
|
||||
}
|
||||
|
||||
void VuDisassembler::add_label_with_name(int instr, const std::string& name) {
|
||||
add_label(instr);
|
||||
m_user_named_instructions[instr] = name;
|
||||
}
|
||||
|
||||
void VuDisassembler::name_labels() {
|
||||
std::vector<int> instrs_with_labels;
|
||||
for (auto [instr, label_idx] : m_labels) {
|
||||
@@ -732,5 +1015,91 @@ void VuDisassembler::name_labels() {
|
||||
auto label_idx = m_labels.at(instr);
|
||||
m_label_names.at(label_idx) = fmt::format("L{}", idx++);
|
||||
}
|
||||
|
||||
for (auto& kv : m_user_named_instructions) {
|
||||
m_label_names.at(m_labels.at(kv.first)) = kv.second;
|
||||
}
|
||||
}
|
||||
|
||||
bool has_branch_delay(const VuInstructionPair& pair) {
|
||||
switch (pair.lower.kind) {
|
||||
case VuInstrK::JALR:
|
||||
// case VuInstrK::JR: it does, but it's not supported
|
||||
case VuInstrK::IBGTZ:
|
||||
case VuInstrK::IBNE:
|
||||
case VuInstrK::IBEQ:
|
||||
case VuInstrK::B:
|
||||
case VuInstrK::BAL:
|
||||
case VuInstrK::IBLTZ:
|
||||
case VuInstrK::IBLEZ:
|
||||
case VuInstrK::IBGEZ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_label_name(const VuInstructionPair& pair,
|
||||
const std::vector<std::string>& label_names) {
|
||||
for (auto& arg : pair.lower.src) {
|
||||
if (arg.kind() == VuInstructionAtom::Kind::LABEL) {
|
||||
return arg.to_string(label_names);
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
std::string VuDisassembler::to_string_with_cpp(const VuProgram& prog) const {
|
||||
std::string result;
|
||||
for (int i = 0; i < (int)prog.instructions().size(); i++) {
|
||||
auto lab = m_labels.find(i);
|
||||
if (lab != m_labels.end()) {
|
||||
result += m_label_names.at(lab->second);
|
||||
result += ':';
|
||||
result += '\n';
|
||||
}
|
||||
auto& pair = prog.instructions().at(i);
|
||||
if (has_branch_delay(pair)) {
|
||||
result += "// BRANCH!\n";
|
||||
// set bc
|
||||
result += to_string_with_cpp(prog.instructions().at(i));
|
||||
result += "\n";
|
||||
result += to_string_with_cpp(prog.instructions().at(i + 1));
|
||||
result += "\n";
|
||||
result += fmt::format("if (bc) {{ goto {}; }}\n", get_label_name(pair, m_label_names));
|
||||
result += "\n\n";
|
||||
i++;
|
||||
} else {
|
||||
result += to_string_with_cpp(prog.instructions().at(i));
|
||||
result += '\n';
|
||||
}
|
||||
}
|
||||
fmt::print("TOTAL unk: {}\n", unk);
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool is_nop(const VuInstruction& i) {
|
||||
return i.kind == VuInstrK::NOP || i.kind == VuInstrK::LOWER_NOP;
|
||||
}
|
||||
} // namespace
|
||||
std::string VuDisassembler::to_string_with_cpp(const VuInstructionPair& pair) const {
|
||||
std::string result;
|
||||
result += fmt::format(" // {:25s} | {:30s}\n", to_string(pair.lower), to_string(pair.upper));
|
||||
|
||||
if (!is_nop(pair.lower) && !is_nop(pair.upper) && pair.lower.kind == VuInstrK::FP_CONSTANT) {
|
||||
result += fmt::format(" {:25s}", to_cpp(pair.upper));
|
||||
result += fmt::format(" {:25s}", to_cpp(pair.lower));
|
||||
} else {
|
||||
if (!is_nop(pair.upper)) {
|
||||
result += fmt::format(" {:25s}", to_cpp(pair.upper));
|
||||
}
|
||||
|
||||
if (!is_nop(pair.lower)) {
|
||||
result += fmt::format(" {:25s}", to_cpp(pair.lower));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -57,8 +57,13 @@ class VuDisassembler {
|
||||
VuDisassembler(VuKind kind);
|
||||
VuProgram disassemble(void* data, int size_bytes, bool debug_print = false);
|
||||
std::string to_string(const VuInstruction& instr) const;
|
||||
std::string to_cpp(const VuInstruction& instr) const;
|
||||
std::string to_string(const VuInstructionPair& pair) const;
|
||||
std::string to_string_with_cpp(const VuInstructionPair& pair) const;
|
||||
std::string to_string(const VuProgram& prog) const;
|
||||
std::string to_string_with_cpp(const VuProgram& prog) const;
|
||||
int add_label(int instr);
|
||||
void add_label_with_name(int instr, const std::string& name);
|
||||
|
||||
private:
|
||||
VuKind m_kind;
|
||||
@@ -66,6 +71,7 @@ class VuDisassembler {
|
||||
VuInstrK lower_kind(u32 in);
|
||||
VuInstruction decode(VuInstrK kind, u32 data, int instr_idx);
|
||||
s32 get_instruction_index_mask();
|
||||
std::unordered_map<int, std::string> m_user_named_instructions;
|
||||
|
||||
struct VuUpperOp6 {
|
||||
bool goto_11 = false;
|
||||
@@ -225,7 +231,6 @@ class VuDisassembler {
|
||||
std::unordered_map<int, int> m_labels;
|
||||
std::vector<std::string> m_label_names;
|
||||
|
||||
int add_label(int instr);
|
||||
void name_labels();
|
||||
|
||||
OpInfo& add_op(VuInstrK kind, const std::string& name);
|
||||
|
||||
@@ -45,6 +45,10 @@ VuInstructionAtom VuInstructionAtom::make_r() {
|
||||
return {Kind::R};
|
||||
}
|
||||
|
||||
bool VuInstructionAtom::is_int_reg(int idx) const {
|
||||
return m_kind == Kind::VI && m_value == idx;
|
||||
}
|
||||
|
||||
std::string VuInstructionAtom::to_string(const std::vector<std::string>& labels) const {
|
||||
switch (m_kind) {
|
||||
case Kind::VF:
|
||||
|
||||
@@ -178,8 +178,11 @@ class VuInstructionAtom {
|
||||
static VuInstructionAtom make_p();
|
||||
static VuInstructionAtom make_r();
|
||||
|
||||
bool is_int_reg(int idx) const;
|
||||
|
||||
std::string to_string(const std::vector<std::string>& labels) const;
|
||||
Kind kind() const { return m_kind; }
|
||||
s64 value() const { return m_value; }
|
||||
|
||||
private:
|
||||
VuInstructionAtom(Kind kind, s64 idx = -1) : m_kind(kind), m_value(idx) {}
|
||||
|
||||
@@ -976,6 +976,7 @@ Mips2C_Line handle_normal_instr(Mips2C_Output& output,
|
||||
case InstructionKind::DSRL:
|
||||
case InstructionKind::SRL:
|
||||
case InstructionKind::PSRAW:
|
||||
case InstructionKind::PSRAH:
|
||||
case InstructionKind::PSRLH:
|
||||
return handle_generic_op2_u16(i0, instr_str);
|
||||
case InstructionKind::SLL:
|
||||
@@ -1002,8 +1003,10 @@ Mips2C_Line handle_normal_instr(Mips2C_Output& output,
|
||||
case InstructionKind::PMINH:
|
||||
case InstructionKind::MOVZ:
|
||||
case InstructionKind::MULT3:
|
||||
case InstructionKind::MULTU3:
|
||||
case InstructionKind::PMINW:
|
||||
case InstructionKind::PMAXW:
|
||||
case InstructionKind::PMAXH:
|
||||
case InstructionKind::SUBU:
|
||||
case InstructionKind::DSRAV:
|
||||
return handle_generic_op3(i0, instr_str, {});
|
||||
@@ -1073,6 +1076,8 @@ Mips2C_Line handle_normal_instr(Mips2C_Output& output,
|
||||
return handle_generic_op2(i0, instr_str, "sqrts");
|
||||
case InstructionKind::PLZCW:
|
||||
return handle_generic_op2(i0, instr_str, "plzcw");
|
||||
case InstructionKind::PCPYH:
|
||||
return handle_generic_op2(i0, instr_str, "pcpyh");
|
||||
case InstructionKind::LUI:
|
||||
return handle_lui(i0, instr_str);
|
||||
case InstructionKind::CLTS:
|
||||
|
||||
@@ -8040,7 +8040,7 @@
|
||||
(defenum draw-status
|
||||
:type uint8
|
||||
:bitfield #t
|
||||
(drwf00 0)
|
||||
(needs-clip 0)
|
||||
(drwf01 1)
|
||||
(drwf02 2)
|
||||
(drwf03 3)
|
||||
@@ -8347,7 +8347,9 @@
|
||||
)
|
||||
|
||||
;;effect-bits:
|
||||
;; 1 - swap with last effect.
|
||||
;; 0 - texture scroll
|
||||
;; 1 - swap with last effect,
|
||||
;; 2 - ripple
|
||||
|
||||
(deftype merc-effect (structure)
|
||||
((frag-geo merc-fragment :offset-assert 0) ;; ?
|
||||
@@ -16423,7 +16425,7 @@
|
||||
|
||||
;; - Functions
|
||||
|
||||
(define-extern setup-blerc-chains-for-one-fragment function)
|
||||
(define-extern setup-blerc-chains-for-one-fragment (function object object object object object object object))
|
||||
(define-extern setup-blerc-chains (function merc-ctrl (pointer int16) dma-buffer none))
|
||||
(define-extern blerc-stats-init (function none))
|
||||
(define-extern blerc-init (function none))
|
||||
@@ -16448,7 +16450,7 @@
|
||||
;; - Functions
|
||||
|
||||
(define-extern merc-vu1-init-buffer (function bucket-id gs-test int none))
|
||||
(define-extern merc-vu1-initialize-chain (function dma-gif-packet none))
|
||||
(define-extern merc-vu1-initialize-chain (function dma-gif-packet dma-packet))
|
||||
(define-extern merc-vu1-add-vu-function (function dma-packet vu-function int dma-gif-packet))
|
||||
(define-extern get-eye-block (function int int int))
|
||||
(define-extern merc-stats-display (function merc-ctrl none))
|
||||
@@ -16619,7 +16621,7 @@
|
||||
(define-extern draw-bones-generic-merc (function draw-control object object int pointer))
|
||||
(define-extern draw-bones-merc (function draw-control object object int int pointer))
|
||||
(define-extern draw-bones-check-longest-edge (function draw-control float none))
|
||||
(define-extern draw-bones-check-longest-edge-asm (function draw-control float none))
|
||||
(define-extern draw-bones-check-longest-edge-asm (function draw-control float symbol))
|
||||
(define-extern draw-bones (function draw-control dma-buffer float none))
|
||||
(define-extern draw-bones-hud (function draw-control dma-buffer none))
|
||||
|
||||
|
||||
@@ -127,8 +127,6 @@
|
||||
"ripple-execute-init",
|
||||
|
||||
// bones
|
||||
"draw-bones-check-longest-edge-asm",
|
||||
"draw-bones-merc",
|
||||
"bones-mtx-calc",
|
||||
|
||||
// generic-effect
|
||||
@@ -499,7 +497,8 @@
|
||||
"(anon-function 21 plant-boss)": [0, 1, 3, 4],
|
||||
"(method 55 ram-boss)": [5],
|
||||
"(method 60 ice-cube)": [8],
|
||||
"(anon-function 2 snow-ball)": [22]
|
||||
"(anon-function 2 snow-ball)": [22],
|
||||
"draw-bones-merc": [1, 3, 5, 7, 8, 10, 11, 12, 13]
|
||||
},
|
||||
|
||||
// Sometimes the game might use format strings that are fetched dynamically,
|
||||
@@ -578,7 +577,11 @@
|
||||
"calc-animation-from-spr",
|
||||
"clear-frame-accumulator",
|
||||
"bones-mtx-calc",
|
||||
"cspace<-parented-transformq-joint!"
|
||||
"cspace<-parented-transformq-joint!",
|
||||
"draw-bones-merc",
|
||||
"draw-bones-check-longest-edge-asm",
|
||||
"setup-blerc-chains-for-one-fragment",
|
||||
"blerc-execute"
|
||||
],
|
||||
|
||||
"mips2c_jump_table_functions": {
|
||||
|
||||
@@ -7083,7 +7083,9 @@
|
||||
[545, "s2", "int"],
|
||||
[49, "a1", "bone-calculation"],
|
||||
[262, "s2", "(pointer uint32)"],
|
||||
[89, "at", "terrain-context"]
|
||||
[89, "at", "terrain-context"],
|
||||
[[312,334], "v1", "mei-envmap-tint"],
|
||||
[363, "a0", "(pointer uint8)"]
|
||||
],
|
||||
|
||||
"draw-bones-hud": [
|
||||
@@ -7897,5 +7899,24 @@
|
||||
[20, "a0", "process-drawable"]
|
||||
],
|
||||
|
||||
"setup-blerc-chains": [
|
||||
[43, "v1", "int"],
|
||||
[80, "s0", "int"],
|
||||
[83, "a0", "int"],
|
||||
[[30,40], "s1", "merc-fragment-control"],
|
||||
[41, "v1", "merc-fragment"],
|
||||
[46, "v1", "(pointer uint8)"],
|
||||
[59, "a0", "merc-blend-ctrl"],
|
||||
[[64,76], "s1", "merc-fragment-control"],
|
||||
[77, "a1", "merc-blend-ctrl"]
|
||||
],
|
||||
|
||||
"blerc-execute": [
|
||||
[20, "a0", "(pointer int32)"],
|
||||
[26, "v1", "(pointer int32)"],
|
||||
[59, "a2", "(pointer int32)"],
|
||||
[65, "a1", "(pointer int32)"]
|
||||
],
|
||||
|
||||
"placeholder-do-not-add-below": []
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ set(RUNTIME_SOURCE
|
||||
mips2c/functions/collide_probe.cpp
|
||||
mips2c/functions/draw_string.cpp
|
||||
mips2c/functions/joint.cpp
|
||||
mips2c/functions/merc_blend_shape.cpp
|
||||
mips2c/functions/sky_tng.cpp
|
||||
mips2c/functions/sparticle.cpp
|
||||
mips2c/functions/sparticle_launcher.cpp
|
||||
@@ -97,6 +98,8 @@ set(RUNTIME_SOURCE
|
||||
graphics/opengl_renderer/DirectRenderer.cpp
|
||||
graphics/opengl_renderer/dma_helpers.cpp
|
||||
graphics/opengl_renderer/Loader.cpp
|
||||
graphics/opengl_renderer/MercProgram.cpp
|
||||
graphics/opengl_renderer/MercRenderer.cpp
|
||||
graphics/opengl_renderer/OpenGLRenderer.cpp
|
||||
graphics/opengl_renderer/Profiler.cpp
|
||||
graphics/opengl_renderer/Shader.cpp
|
||||
|
||||
@@ -18,9 +18,11 @@ enum class BucketId {
|
||||
TFRAG_TEX_LEVEL0 = 5,
|
||||
TFRAG_LEVEL0 = 6,
|
||||
TIE_LEVEL0 = 9,
|
||||
MERC_TFRAG_TEX_LEVEL0 = 10,
|
||||
TFRAG_TEX_LEVEL1 = 12,
|
||||
TFRAG_LEVEL1 = 13,
|
||||
TIE_LEVEL1 = 16,
|
||||
MERC_TFRAG_TEX_LEVEL1 = 17,
|
||||
SHRUB_TEX_LEVEL0 = 19,
|
||||
SHRUB_TEX_LEVEL1 = 25,
|
||||
ALPHA_TEX_LEVEL0 = 31,
|
||||
@@ -31,10 +33,16 @@ enum class BucketId {
|
||||
TFRAG_TRANS1_AND_SKY_BLEND_LEVEL1 = 39,
|
||||
TFRAG_DIRT_LEVEL1 = 41,
|
||||
TFRAG_ICE_LEVEL1 = 43,
|
||||
MERC_AFTER_ALPHA = 45,
|
||||
PRIS_TEX_LEVEL0 = 48,
|
||||
MERC_PRIS_LEVEL0 = 49,
|
||||
PRIS_TEX_LEVEL1 = 51,
|
||||
MERC_PRIS_LEVEL1 = 52,
|
||||
MERC_AFTER_PRIS = 55,
|
||||
WATER_TEX_LEVEL0 = 57,
|
||||
MERC_WATER_LEVEL0 = 58,
|
||||
WATER_TEX_LEVEL1 = 60,
|
||||
MERC_WATER_LEVEL1 = 61,
|
||||
// ...
|
||||
PRE_SPRITE_TEX = 65, // maybe it's just common textures?
|
||||
SPRITE = 66,
|
||||
@@ -69,6 +77,7 @@ struct SharedRenderState {
|
||||
|
||||
bool use_sky_cpu = true;
|
||||
bool use_occlusion_culling = true;
|
||||
bool render_debug = false;
|
||||
|
||||
void reset();
|
||||
bool has_camera_planes = false;
|
||||
|
||||
@@ -244,7 +244,7 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
|
||||
// currently gouraud is handled in setup.
|
||||
const auto& state = m_prim_gl_state;
|
||||
if (state.texture_enable) {
|
||||
float alpha_reject = 0.;
|
||||
float alpha_reject = 0.0;
|
||||
if (m_test_state.alpha_test_enable) {
|
||||
switch (m_test_state.alpha_test) {
|
||||
case GsTest::AlphaTest::ALWAYS:
|
||||
@@ -310,10 +310,11 @@ void DirectRenderer::update_gl_texture(SharedRenderState* render_state, int unit
|
||||
|
||||
if (!tex) {
|
||||
// TODO Add back
|
||||
fmt::print("Failed to find texture at {}, using random\n", state.texture_base_ptr);
|
||||
tex = render_state->texture_pool->get_random_texture();
|
||||
if (tex) {
|
||||
// fmt::print("Successful texture lookup! {} {}\n", tex->page_name, tex->name);
|
||||
if (state.texture_base_ptr >= 8160 && state.texture_base_ptr <= 8600) {
|
||||
tex = render_state->texture_pool->get_random_texture();
|
||||
} else {
|
||||
fmt::print("Failed to find texture at {}, using random\n", state.texture_base_ptr);
|
||||
tex = render_state->texture_pool->get_random_texture();
|
||||
}
|
||||
}
|
||||
assert(tex);
|
||||
@@ -367,6 +368,7 @@ void DirectRenderer::update_gl_blend() {
|
||||
// (Cs - 0) * As + Cd
|
||||
// Cs * As + (1) * Cd
|
||||
// s, d
|
||||
assert(state.fix == 0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
} else if (state.a == GsAlpha::BlendMode::ZERO_OR_FIXED &&
|
||||
@@ -377,11 +379,19 @@ void DirectRenderer::update_gl_blend() {
|
||||
// s, d
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
} else if (state.a == GsAlpha::BlendMode::SOURCE && state.b == GsAlpha::BlendMode::DEST &&
|
||||
state.c == GsAlpha::BlendMode::ZERO_OR_FIXED &&
|
||||
state.d == GsAlpha::BlendMode::DEST) {
|
||||
// (Cs - Cd) * fix + Cd
|
||||
// Cs * fix + (1 - fx) * Cd
|
||||
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
|
||||
glBlendColor(0, 0, 0, state.fix / 127.f);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
} else {
|
||||
// unsupported blend: a 0 b 2 c 2 d 1
|
||||
lg::error("unsupported blend: a {} b {} c {} d {} NOTE THIS DOWN IMMEDIATELY!!", (int)state.a,
|
||||
(int)state.b, (int)state.c, (int)state.d);
|
||||
assert(false);
|
||||
lg::error("unsupported blend: a {} b {} c {} d {}", (int)state.a, (int)state.b, (int)state.c,
|
||||
(int)state.d);
|
||||
// assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,6 +418,7 @@ void DirectRenderer::update_gl_test() {
|
||||
assert(false);
|
||||
}
|
||||
} else {
|
||||
// you aren't supposed to turn off z test enable, the GS had some bugs
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -699,7 +710,6 @@ void DirectRenderer::handle_tex0_1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
GsTex0 reg(val);
|
||||
|
||||
// update tbp
|
||||
if (current_texture_state()->current_register != reg) {
|
||||
if (current_texture_state()->used) {
|
||||
@@ -726,7 +736,8 @@ void DirectRenderer::handle_tex0_1(u64 val,
|
||||
// tw: assume they got it right
|
||||
// th: assume they got it right
|
||||
|
||||
assert(reg.tfx() == GsTex0::TextureFunction::MODULATE);
|
||||
// MERC hack
|
||||
// assert(reg.tfx() == GsTex0::TextureFunction::MODULATE);
|
||||
|
||||
// cbp: assume they got it right
|
||||
// cpsm: assume they got it right
|
||||
@@ -832,8 +843,8 @@ void DirectRenderer::handle_clamp1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
if (!(val == 0b101 || val == 0 || val == 1 || val == 0b100)) {
|
||||
fmt::print("clamp: 0x{:x}\n", val);
|
||||
assert(false);
|
||||
// fmt::print("clamp: 0x{:x}\n", val);
|
||||
// assert(false);
|
||||
}
|
||||
|
||||
if (current_texture_state()->m_clamp_state.current_register != val) {
|
||||
@@ -1089,8 +1100,6 @@ void DirectRenderer::BlendState::from_register(GsAlpha reg) {
|
||||
c = reg.c_mode();
|
||||
d = reg.d_mode();
|
||||
fix = reg.fix();
|
||||
|
||||
assert(fix == 0);
|
||||
}
|
||||
|
||||
void DirectRenderer::PrimGlState::from_register(GsPrim reg) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,346 @@
|
||||
#include "MercRenderer.h"
|
||||
|
||||
#include "third-party/imgui/imgui.h"
|
||||
|
||||
MercRenderer::MercRenderer(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id),
|
||||
m_direct(fmt::format("{}-dir", name), my_id, 0x30000, DirectRenderer::Mode::NORMAL) {
|
||||
memset(m_buffer.data, 0, sizeof(m_buffer.data));
|
||||
}
|
||||
|
||||
void MercRenderer::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
m_stats = Stats();
|
||||
|
||||
// skip if disabled
|
||||
if (!m_enabled) {
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// process the first tag. this is just jumping to the merc-specific dma.
|
||||
auto data0 = dma.read_and_advance();
|
||||
assert(data0.vif1() == 0);
|
||||
assert(data0.vif0() == 0);
|
||||
assert(data0.size_bytes == 0);
|
||||
if (dma.current_tag().kind == DmaTag::Kind::CALL) {
|
||||
// renderer didn't run, let's just get out of here.
|
||||
for (int i = 0; i < 4; i++) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
assert(dma.current_tag_offset() == render_state->next_bucket);
|
||||
return;
|
||||
}
|
||||
m_stats.had_data = true;
|
||||
assert(data0.size_bytes == 0);
|
||||
assert(data0.vif0() == 0);
|
||||
assert(data0.vif1() == 0);
|
||||
|
||||
// if we reach here, there's stuff to draw
|
||||
handle_setup(dma, render_state, prof);
|
||||
|
||||
m_direct.reset_state();
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
handle_merc_chain(dma, render_state, prof);
|
||||
}
|
||||
assert(dma.current_tag_offset() == render_state->next_bucket);
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
}
|
||||
|
||||
bool tag_is_nothing_next(const DmaFollower& dma) {
|
||||
return dma.current_tag().kind == DmaTag::Kind::NEXT && dma.current_tag().qwc == 0 &&
|
||||
dma.current_tag_vif0() == 0 && dma.current_tag_vif1() == 0;
|
||||
}
|
||||
|
||||
void MercRenderer::unpack32(const VifCodeUnpack& up, const u8* data, u32 imm) {
|
||||
assert(!up.is_unsigned);
|
||||
u32 addr = up.addr_qw;
|
||||
assert(imm != 0);
|
||||
assert(!m_vif.stmod);
|
||||
if (up.use_tops_flag) {
|
||||
addr += xitop();
|
||||
}
|
||||
|
||||
u32 start_in_buff = (addr)*16;
|
||||
u32 end_in_buff = start_in_buff + imm * 16;
|
||||
assert(start_in_buff < sizeof(m_buffer.data));
|
||||
assert(end_in_buff <= sizeof(m_buffer.data));
|
||||
memcpy(m_buffer.data + start_in_buff, data, imm * 16);
|
||||
}
|
||||
|
||||
void MercRenderer::unpack8(const VifCodeUnpack& up, const u8* data, u32 imm) {
|
||||
// assert(m_vif.stmod);
|
||||
|
||||
assert(up.is_unsigned);
|
||||
u32 addr = up.addr_qw;
|
||||
if (up.use_tops_flag) {
|
||||
addr += xitop();
|
||||
}
|
||||
assert(imm != 0);
|
||||
|
||||
u32 start_in_buff = (addr)*16;
|
||||
u32 end_in_buff = start_in_buff + imm * 16;
|
||||
assert(start_in_buff < sizeof(m_buffer.data));
|
||||
assert(end_in_buff <= sizeof(m_buffer.data));
|
||||
|
||||
u8* out_ptr = m_buffer.data + start_in_buff;
|
||||
|
||||
if (m_vif.stmod) {
|
||||
// use row
|
||||
auto row = _mm_loadu_si128((const __m128i*)m_vif.row);
|
||||
for (u32 qw = 0; qw < imm; qw++) {
|
||||
_mm_storeu_si128((__m128i*)out_ptr,
|
||||
_mm_add_epi32(row, _mm_cvtepu8_epi32(_mm_loadu_si64(data))));
|
||||
data += 4;
|
||||
out_ptr += 16;
|
||||
}
|
||||
} else {
|
||||
// no row
|
||||
for (u32 qw = 0; qw < imm; qw++) {
|
||||
_mm_storeu_si128((__m128i*)out_ptr, _mm_cvtepu8_epi32(_mm_loadu_si64(data)));
|
||||
data += 4;
|
||||
out_ptr += 16;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
u32 row[4];
|
||||
if (m_vif.stmod) {
|
||||
memcpy(row, m_vif.row, 16);
|
||||
} else {
|
||||
memset(row, 0, 16);
|
||||
}
|
||||
|
||||
u32 temp[4];
|
||||
for (u32 i = 0; i < imm; i++) {
|
||||
for (u32 j = 0; j < 4; j++) {
|
||||
temp[j] = row[j] + data[4 * i + j];
|
||||
}
|
||||
memcpy(m_buffer.data + start_in_buff + i * 16, temp, 16);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void MercRenderer::handle_merc_chain(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// fmt::print("DMA: {}\n", dma.current_tag().print());
|
||||
while (tag_is_nothing_next(dma)) {
|
||||
auto nothing = dma.read_and_advance();
|
||||
assert(nothing.size_bytes == 0);
|
||||
}
|
||||
if (dma.current_tag().kind == DmaTag::Kind::CALL) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto init = dma.read_and_advance();
|
||||
|
||||
assert(init.vifcode0().kind == VifCode::Kind::STROW);
|
||||
assert(init.size_bytes == 16);
|
||||
m_vif.row[0] = init.vif1();
|
||||
memcpy(m_vif.row + 1, init.data, 12);
|
||||
u32 extra;
|
||||
memcpy(&extra, init.data + 12, 4);
|
||||
assert(extra == 0);
|
||||
DmaTransfer next;
|
||||
|
||||
bool setting_up = true;
|
||||
u32 mscal_addr = -1;
|
||||
while (setting_up) {
|
||||
next = dma.read_and_advance();
|
||||
u32 offset_in_data = 0;
|
||||
// fmt::print("START {} : {} {}\n", next.size_bytes, next.vifcode0().print(),
|
||||
// next.vifcode1().print());
|
||||
auto vif0 = next.vifcode0();
|
||||
switch (vif0.kind) {
|
||||
case VifCode::Kind::NOP:
|
||||
case VifCode::Kind::FLUSHE:
|
||||
break;
|
||||
case VifCode::Kind::STMOD:
|
||||
assert(vif0.immediate == 0 || vif0.immediate == 1);
|
||||
m_vif.stmod = vif0.immediate;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto vif1 = next.vifcode1();
|
||||
switch (vif1.kind) {
|
||||
case VifCode::Kind::UNPACK_V4_8: {
|
||||
// todo unpack
|
||||
m_stats.unpack_count++;
|
||||
m_stats.unpack_bytes += vif1.num * 4;
|
||||
VifCodeUnpack up(vif1);
|
||||
unpack8(up, next.data, vif1.num);
|
||||
offset_in_data += 4 * vif1.num;
|
||||
} break;
|
||||
case VifCode::Kind::UNPACK_V4_32: {
|
||||
// todo unpack
|
||||
VifCodeUnpack up(vif1);
|
||||
unpack32(up, next.data, vif1.num);
|
||||
m_stats.unpack_bytes += vif1.num * 16;
|
||||
offset_in_data += 16 * vif1.num;
|
||||
} break;
|
||||
case VifCode::Kind::MSCAL:
|
||||
mscal_addr = vif1.immediate;
|
||||
assert(next.size_bytes == 0);
|
||||
setting_up = false;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(offset_in_data <= next.size_bytes);
|
||||
if (offset_in_data < next.size_bytes) {
|
||||
assert((offset_in_data % 4) == 0);
|
||||
u32 leftover = next.size_bytes - offset_in_data;
|
||||
if (leftover < 16) {
|
||||
for (u32 i = 0; i < leftover; i++) {
|
||||
assert(next.data[offset_in_data + i] == 0);
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_dbf = !m_dbf;
|
||||
switch (mscal_addr) {
|
||||
case 17:
|
||||
m_stats.mscal_17++;
|
||||
if (m_enable_prime_mscals) {
|
||||
mscal(17, render_state, prof);
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
m_stats.mscal_32++;
|
||||
if (m_enable_prime_mscals) {
|
||||
mscal(32, render_state, prof);
|
||||
}
|
||||
break;
|
||||
|
||||
case 20:
|
||||
m_stats.mscal_20++;
|
||||
if (m_enable_normal_mscals) {
|
||||
mscal(20, render_state, prof);
|
||||
}
|
||||
break;
|
||||
case 35:
|
||||
m_stats.mscal_35++;
|
||||
if (m_enable_normal_mscals) {
|
||||
mscal(35, render_state, prof);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fmt::print("unknown mscal: {}\n", mscal_addr);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// while (true) {
|
||||
// next = dma.read_and_advance();
|
||||
// if (next.vif0() == 0 && next.vifcode1().kind == VifCode::Kind::UNPACK_V4_8) {
|
||||
//
|
||||
// } else {
|
||||
// fmt::print("{} : {} {}\n", next.size_bytes, next.vifcode0().print(),
|
||||
// next.vifcode1().print()); assert(false);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/*!
|
||||
* Handle the setup DMA data prepared by merc-vu1-init-buffer in GOAL
|
||||
*/
|
||||
void MercRenderer::handle_setup(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
auto first = dma.read_and_advance();
|
||||
|
||||
// 10 quadword setup packet
|
||||
assert(first.size_bytes == 10 * 16);
|
||||
// m_stats.str += fmt::format("Setup 0: {} {} {}", first.size_bytes / 16,
|
||||
// first.vifcode0().print(), first.vifcode1().print());
|
||||
|
||||
// transferred vifcodes
|
||||
{
|
||||
auto vif0 = first.vifcode0();
|
||||
auto vif1 = first.vifcode1();
|
||||
// STCYCL 4, 4
|
||||
assert(vif0.kind == VifCode::Kind::STCYCL);
|
||||
auto vif0_st = VifCodeStcycl(vif0);
|
||||
assert(vif0_st.cl == 4 && vif0_st.wl == 4);
|
||||
// STMOD
|
||||
assert(vif1.kind == VifCode::Kind::STMOD);
|
||||
assert(vif1.immediate == 0);
|
||||
}
|
||||
|
||||
// 1 qw with 4 vifcodes.
|
||||
u32 vifcode_data[4];
|
||||
memcpy(vifcode_data, first.data, 16);
|
||||
{
|
||||
auto vif0 = VifCode(vifcode_data[0]);
|
||||
assert(vif0.kind == VifCode::Kind::BASE);
|
||||
assert(vif0.immediate == MercDataMemory::BUFFER_BASE);
|
||||
auto vif1 = VifCode(vifcode_data[1]);
|
||||
assert(vif1.kind == VifCode::Kind::OFFSET);
|
||||
assert((s16)vif1.immediate == MercDataMemory::BUFFER_OFFSET);
|
||||
auto vif2 = VifCode(vifcode_data[2]);
|
||||
assert(vif2.kind == VifCode::Kind::NOP);
|
||||
auto vif3 = VifCode(vifcode_data[3]);
|
||||
assert(vif3.kind == VifCode::Kind::UNPACK_V4_32);
|
||||
VifCodeUnpack up(vif3);
|
||||
assert(up.addr_qw == MercDataMemory::LOW_MEMORY);
|
||||
assert(!up.use_tops_flag);
|
||||
assert(vif3.num == 8);
|
||||
}
|
||||
|
||||
// 8 qw's of low memory data
|
||||
memcpy(&m_low_memory, first.data + 16, sizeof(LowMemory));
|
||||
m_stats.str += fmt::format("Fog: {}\n", m_low_memory.fog.to_string_aligned());
|
||||
|
||||
// 1 qw with another 4 vifcodes.
|
||||
u32 vifcode_final_data[4];
|
||||
memcpy(vifcode_final_data, first.data + 16 + sizeof(LowMemory), 16);
|
||||
{
|
||||
assert(VifCode(vifcode_final_data[0]).kind == VifCode::Kind::FLUSHE);
|
||||
assert(vifcode_final_data[1] == 0);
|
||||
assert(vifcode_final_data[2] == 0);
|
||||
VifCode mscal(vifcode_final_data[3]);
|
||||
assert(mscal.kind == VifCode::Kind::MSCAL);
|
||||
assert(mscal.immediate == 0);
|
||||
}
|
||||
|
||||
// copy low memory into the VU "emulation" RAM.
|
||||
memcpy(m_buffer.data, &m_low_memory, sizeof(LowMemory));
|
||||
mscal(0, render_state, prof);
|
||||
|
||||
auto second = dma.read_and_advance();
|
||||
assert(second.size_bytes == 32); // setting up test register.
|
||||
m_direct.render_gif(second.data, 32, render_state, prof);
|
||||
auto nothing = dma.read_and_advance();
|
||||
assert(nothing.size_bytes == 0);
|
||||
assert(nothing.vif0() == 0);
|
||||
assert(nothing.vif1() == 0);
|
||||
}
|
||||
|
||||
void MercRenderer::draw_debug_window() {
|
||||
ImGui::Text("Ran? %d\n", m_stats.had_data);
|
||||
ImGui::Text("%d unpacks, %d bytes\n", m_stats.unpack_count, m_stats.unpack_bytes);
|
||||
ImGui::Text("MSCAL: [17] %d [20] %d [32] %d [35] %d \n", m_stats.mscal_17, m_stats.mscal_20,
|
||||
m_stats.mscal_32, m_stats.mscal_35);
|
||||
ImGui::Text("Debug:\n%s\n", m_stats.str.c_str());
|
||||
ImGui::Checkbox("Normal MSCAL enable", &m_enable_normal_mscals);
|
||||
ImGui::Checkbox("Prime MSCAL enable", &m_enable_prime_mscals);
|
||||
ImGui::Checkbox("Send to direct", &m_enable_send_to_direct);
|
||||
}
|
||||
|
||||
void MercRenderer::xgkick(u16 addr, SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
if (m_enable_send_to_direct) {
|
||||
m_direct.render_gif(m_buffer.data + (16 * addr), UINT32_MAX, render_state, prof);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,539 @@
|
||||
#pragma once
|
||||
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "common/math/Vector.h"
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
|
||||
#include "immintrin.h"
|
||||
|
||||
enum class Mask {
|
||||
NONE = 0,
|
||||
x = 1,
|
||||
y = 2,
|
||||
xy = 3,
|
||||
z = 4,
|
||||
xz = 5,
|
||||
yz = 6,
|
||||
xyz = 7,
|
||||
w = 8,
|
||||
xw = 9,
|
||||
yw = 10,
|
||||
xyw = 11,
|
||||
zw = 12,
|
||||
xzw = 13,
|
||||
yzw = 14,
|
||||
xyzw = 15
|
||||
};
|
||||
|
||||
#ifdef __linux__
|
||||
#define REALLY_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define REALLY_INLINE __forceinline
|
||||
#endif
|
||||
|
||||
// note: must be aligned.
|
||||
static inline REALLY_INLINE void copy_vector(void* dest, const void* src) {
|
||||
__m128 val = _mm_load_ps((const float*)src);
|
||||
_mm_store_ps((float*)dest, val);
|
||||
}
|
||||
|
||||
inline float vu_max(float a, float b) {
|
||||
return std::max(b, a);
|
||||
// s32 ai, bi;
|
||||
// memcpy(&ai, &a, 4);
|
||||
// memcpy(&bi, &b, 4);
|
||||
// bool flip = ai < 0 && bi < 0;
|
||||
// if (ai > bi) {
|
||||
// return flip ? b : a;
|
||||
// } else {
|
||||
// return flip ? a : b;
|
||||
// }
|
||||
}
|
||||
|
||||
inline float vu_min(float a, float b) {
|
||||
s32 ai, bi;
|
||||
memcpy(&ai, &a, 4);
|
||||
memcpy(&bi, &b, 4);
|
||||
bool flip = ai < 0 && bi < 0;
|
||||
if (ai > bi) {
|
||||
return flip ? a : b;
|
||||
} else {
|
||||
return flip ? b : a;
|
||||
}
|
||||
}
|
||||
|
||||
struct alignas(16) Vf {
|
||||
REALLY_INLINE __m128 load() const { return _mm_load_ps(data); }
|
||||
|
||||
REALLY_INLINE void move_xyzw(const Vf& src) { copy_vector(data, src.data); }
|
||||
|
||||
float data[4];
|
||||
float& x() { return data[0]; }
|
||||
float& y() { return data[1]; }
|
||||
float& z() { return data[2]; }
|
||||
float& w() { return data[3]; }
|
||||
|
||||
const float& x() const { return data[0]; }
|
||||
const float& y() const { return data[1]; }
|
||||
const float& z() const { return data[2]; }
|
||||
const float& w() const { return data[3]; }
|
||||
|
||||
u16 x_as_u16() const {
|
||||
u16 result;
|
||||
memcpy(&result, &data[0], 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
u16 y_as_u16() const {
|
||||
u16 result;
|
||||
memcpy(&result, &data[1], 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
u16 z_as_u16() const {
|
||||
u16 result;
|
||||
memcpy(&result, &data[2], 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
u16 w_as_u16() const {
|
||||
u16 result;
|
||||
memcpy(&result, &data[3], 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 x_as_u32() const {
|
||||
u32 result;
|
||||
memcpy(&result, &data[0], 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 y_as_u32() const {
|
||||
u32 result;
|
||||
memcpy(&result, &data[1], 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 z_as_u32() const {
|
||||
u32 result;
|
||||
memcpy(&result, &data[2], 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 w_as_u32() const {
|
||||
u32 result;
|
||||
memcpy(&result, &data[3], 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
Vf() = default;
|
||||
Vf(const math::Vector4f& vec) { memcpy(data, vec.data(), 16); }
|
||||
Vf(float a, float b, float c, float d) {
|
||||
data[0] = a;
|
||||
data[1] = b;
|
||||
data[2] = c;
|
||||
data[3] = d;
|
||||
}
|
||||
|
||||
std::string str_float() const { return fmt::format("{} {} {} {}", x(), y(), z(), w()); }
|
||||
|
||||
float& operator[](int i) { return data[i]; }
|
||||
float operator[](int i) const { return data[i]; }
|
||||
|
||||
void mr32(Mask mask, const Vf& other) {
|
||||
float temp[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
temp[i] = other[(i + 1) % 4];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = temp[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REALLY_INLINE void mr32_z(const Vf& other) { data[2] = other.data[3]; }
|
||||
|
||||
void mfir(Mask mask, s16 in) {
|
||||
s32 sext = in;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
memcpy(data + i, &sext, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void maxi(Mask mask, const Vf& other, float I) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = vu_max(other[i], I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void max(Mask mask, const Vf& other, float I) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = vu_max(other[i], I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void max(Mask mask, const Vf& other, const Vf& b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = vu_max(other[i], b[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REALLY_INLINE void max_xyzw(const Vf& a, const Vf& b) {
|
||||
_mm_store_ps(data, _mm_max_ps(_mm_load_ps(a.data), _mm_load_ps(b.data)));
|
||||
}
|
||||
|
||||
REALLY_INLINE void max_xyzw(const Vf& a, float b) {
|
||||
_mm_store_ps(data, _mm_max_ps(_mm_load_ps(a.data), _mm_set1_ps(b)));
|
||||
}
|
||||
|
||||
REALLY_INLINE void mini_xyzw(const Vf& a, const Vf& b) {
|
||||
_mm_store_ps(data, _mm_min_ps(_mm_load_ps(a.data), _mm_load_ps(b.data)));
|
||||
}
|
||||
|
||||
REALLY_INLINE void mini_xyzw(const Vf& a, float b) {
|
||||
_mm_store_ps(data, _mm_min_ps(_mm_load_ps(a.data), _mm_set1_ps(b)));
|
||||
}
|
||||
|
||||
void minii(Mask mask, const Vf& other, float I) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = vu_min(other[i], I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mini(Mask mask, const Vf& other, float I) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = vu_min(other[i], I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void move(Mask mask, const Vf& other) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = other[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mfp(Mask mask, float other) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = other;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add(Mask mask, const Vf& a, const Vf& b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = a[i] + b[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REALLY_INLINE void add_xyzw(const Vf& a, const Vf& b) {
|
||||
_mm_store_ps(data, _mm_add_ps(_mm_load_ps(a.data), _mm_load_ps(b.data)));
|
||||
}
|
||||
|
||||
void add(Mask mask, const Vf& a, float b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = a[i] + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REALLY_INLINE void mul_xyzw(const Vf& a, const Vf& b) {
|
||||
_mm_store_ps(data, _mm_mul_ps(_mm_load_ps(a.data), _mm_load_ps(b.data)));
|
||||
}
|
||||
|
||||
REALLY_INLINE void mul_xyzw(const Vf& a, float b) {
|
||||
_mm_store_ps(data, _mm_mul_ps(_mm_load_ps(a.data), _mm_set1_ps(b)));
|
||||
}
|
||||
|
||||
void mul(Mask mask, const Vf& a, const Vf& b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = a[i] * b[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mul(Mask mask, const Vf& a, float b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = a[i] * b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void itof0(Mask mask, const Vf& a) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
s32 val;
|
||||
memcpy(&val, &a.data[i], 4);
|
||||
data[i] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void itof15(Mask mask, const Vf& a) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
s32 val;
|
||||
memcpy(&val, &a.data[i], 4);
|
||||
data[i] = ((float)val) * (1.f / 32768.f);
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ftoi4(Mask mask, const Vf& a) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
s32 val = a.data[i] * 16.f;
|
||||
memcpy(&data[i], &val, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ftoi0(Mask mask, const Vf& a) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
s32 val = a.data[i];
|
||||
memcpy(&data[i], &val, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct alignas(16) Accumulator {
|
||||
float data[4];
|
||||
|
||||
void adda(Mask mask, const Vf& a, float b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = a[i] + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void madda(Mask mask, const Vf& a, const Vf& b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] += a[i] * b[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void madda(Mask mask, const Vf& a, float b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] += a[i] * b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REALLY_INLINE void madda_xyzw(const Vf& _a, float _b) {
|
||||
auto b = _mm_set1_ps(_b);
|
||||
auto a = _mm_load_ps(_a.data);
|
||||
auto acc = _mm_load_ps(data);
|
||||
_mm_store_ps(data, _mm_fmadd_ps(a, b, acc));
|
||||
}
|
||||
|
||||
REALLY_INLINE void madda_xyzw(const Vf& _a, const Vf& _b) {
|
||||
auto b = _mm_load_ps(_b.data);
|
||||
auto a = _mm_load_ps(_a.data);
|
||||
auto acc = _mm_load_ps(data);
|
||||
_mm_store_ps(data, _mm_fmadd_ps(a, b, acc));
|
||||
}
|
||||
|
||||
void madd(Mask mask, Vf& dest, const Vf& a, const Vf& b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
dest[i] = data[i] + a[i] * b[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REALLY_INLINE void madd_xyzw(Vf& dest, const Vf& _a, float _b) {
|
||||
auto b = _mm_set1_ps(_b);
|
||||
auto a = _mm_load_ps(_a.data);
|
||||
auto acc = _mm_load_ps(data);
|
||||
_mm_store_ps(dest.data, _mm_fmadd_ps(a, b, acc));
|
||||
}
|
||||
|
||||
REALLY_INLINE void madd_xyz(Vf& dest, const Vf& _a, float _b) {
|
||||
auto b = _mm_set1_ps(_b);
|
||||
auto a = _mm_load_ps(_a.data);
|
||||
auto acc = _mm_load_ps(data);
|
||||
auto prod = _mm_fmadd_ps(a, b, acc);
|
||||
prod = _mm_blend_ps(prod, _mm_load_ps(dest.data), 0b1000);
|
||||
_mm_store_ps(dest.data, prod);
|
||||
}
|
||||
|
||||
void madd(Mask mask, Vf& dest, const Vf& a, float b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
dest[i] = data[i] + a[i] * b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mula(Mask mask, const Vf& a, const Vf& b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = a[i] * b[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mula(Mask mask, const Vf& a, float b) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
data[i] = a[i] * b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REALLY_INLINE void mula_xyzw(const Vf& _a, float _b) {
|
||||
auto b = _mm_set1_ps(_b);
|
||||
auto a = _mm_load_ps(_a.data);
|
||||
_mm_store_ps(data, _mm_mul_ps(a, b));
|
||||
}
|
||||
|
||||
REALLY_INLINE void mula_xyzw(const Vf& _a, const Vf& _b) {
|
||||
auto b = _mm_load_ps(_b.data);
|
||||
auto a = _mm_load_ps(_a.data);
|
||||
_mm_store_ps(data, _mm_mul_ps(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
class MercRenderer : public BucketRenderer {
|
||||
public:
|
||||
MercRenderer(const std::string& name, BucketId my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
|
||||
private:
|
||||
void handle_setup(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_merc_chain(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void unpack8(const VifCodeUnpack& up, const u8* data, u32 imm);
|
||||
void unpack32(const VifCodeUnpack& up, const u8* data, u32 imm);
|
||||
|
||||
void mscal(int enter_address, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
template <bool DEBUG>
|
||||
void mscal_impl(int enter_address, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
void xgkick(u16 addr, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
enum MercDataMemory {
|
||||
LOW_MEMORY = 0,
|
||||
BUFFER_BASE = 442,
|
||||
// this negative offset is what broke jak graphics in Dobiestation for a long time.
|
||||
BUFFER_OFFSET = -442
|
||||
};
|
||||
|
||||
struct LowMemory {
|
||||
u8 tri_strip_tag[16];
|
||||
u8 ad_gif_tag[16];
|
||||
math::Vector4f hvdf_offset;
|
||||
math::Vector4f perspective[4];
|
||||
math::Vector4f fog;
|
||||
} m_low_memory;
|
||||
static_assert(sizeof(LowMemory) == 0x80);
|
||||
|
||||
struct alignas(16) BufferMemory {
|
||||
u8 data[1024 * 16];
|
||||
} m_buffer;
|
||||
|
||||
void sq_buffer(Mask mask, const Vf& data, u32 qw) {
|
||||
// if (data.x_as_u32() == 0x80000000 && data.y_as_u32() == 0x80000000) {
|
||||
// fmt::print("big store line {}: {} : {} {} {} {}\n", line_number, qw, data.x(), data.y(),
|
||||
// data.z(), data.w());
|
||||
// }
|
||||
// sketchy...
|
||||
// qw &= 1023;
|
||||
assert(qw * 16 < sizeof(m_buffer.data));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
memcpy(m_buffer.data + qw * 16 + i * 4, data.data + i, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lq_buffer(Mask mask, Vf& dest, u16 addr);
|
||||
|
||||
template <bool DEBUG>
|
||||
void lq_buffer_xyzw(Vf& dest, u16 addr);
|
||||
|
||||
template <bool DEBUG>
|
||||
void lq_buffer_xyz(Vf& dest, u16 addr);
|
||||
|
||||
template <bool DEBUG>
|
||||
void sq_buffer_xyzw(const Vf& src, u16 addr);
|
||||
|
||||
void isw_buffer(Mask mask, u16 val, u16 addr);
|
||||
void ilw_buffer(Mask mask, u16& dest, u16 addr);
|
||||
|
||||
u16 xtop();
|
||||
u16 xitop();
|
||||
|
||||
DirectRenderer m_direct;
|
||||
|
||||
struct {
|
||||
u32 row[4] = {0, 0, 0, 0};
|
||||
bool stmod = false;
|
||||
} m_vif;
|
||||
|
||||
struct Stats {
|
||||
int unpack_count = 0;
|
||||
int unpack_bytes = 0;
|
||||
int mscal_35 = 0;
|
||||
int mscal_20 = 0;
|
||||
int mscal_17 = 0;
|
||||
int mscal_32 = 0;
|
||||
bool had_data = false;
|
||||
std::string str;
|
||||
} m_stats;
|
||||
|
||||
bool m_dbf = false;
|
||||
|
||||
bool m_enable_prime_mscals = true;
|
||||
bool m_enable_normal_mscals = true;
|
||||
bool m_enable_send_to_direct = true;
|
||||
|
||||
struct Vu {
|
||||
Vf vf01, vf02, vf03, vf04, vf05, vf06, vf07, vf08, vf09, vf10, vf11, vf12, vf13, vf14, vf15,
|
||||
vf16, vf17, vf18, vf19, vf20, vf21, vf22, vf23, vf24, vf25, vf26, vf27, vf28, vf29, vf30,
|
||||
vf31;
|
||||
const Vf vf00;
|
||||
u16 vi01, vi02, vi03, vi04, vi05, vi06, vi07, vi09, vi08, vi11, vi12, vi13, vi10, vi14, vi15;
|
||||
float I, P, Q;
|
||||
|
||||
Accumulator acc;
|
||||
const u16 vi00 = 0;
|
||||
|
||||
u16 hack_old_vi15 = 0;
|
||||
|
||||
Vu() : vf00(0, 0, 0, 1) {}
|
||||
} vu;
|
||||
};
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "game/graphics/opengl_renderer/Sprite3.h"
|
||||
#include "game/graphics/opengl_renderer/tfrag/TFragment.h"
|
||||
#include "game/graphics/opengl_renderer/tfrag/Tie3.h"
|
||||
#include "game/graphics/opengl_renderer/MercRenderer.h"
|
||||
|
||||
// for the vif callback
|
||||
#include "game/kernel/kmachine.h"
|
||||
@@ -68,44 +69,136 @@ void OpenGLRenderer::init_bucket_renderers() {
|
||||
tfrag3::TFragmentTreeKind::LOWRES};
|
||||
std::vector<tfrag3::TFragmentTreeKind> dirt_tfrags = {tfrag3::TFragmentTreeKind::DIRT};
|
||||
std::vector<tfrag3::TFragmentTreeKind> ice_tfrags = {tfrag3::TFragmentTreeKind::ICE};
|
||||
|
||||
init_bucket_renderer<EmptyBucketRenderer>("bucket0", BucketId::BUCKET0);
|
||||
init_bucket_renderer<SkyRenderer>("sky", BucketId::SKY_DRAW);
|
||||
|
||||
init_bucket_renderer<TextureUploadHandler>("tfrag-tex-0", BucketId::TFRAG_TEX_LEVEL0);
|
||||
init_bucket_renderer<TFragment>("tfrag-0", BucketId::TFRAG_LEVEL0, normal_tfrags, false, 0);
|
||||
init_bucket_renderer<Tie3>("tie-0", BucketId::TIE_LEVEL0, 0);
|
||||
init_bucket_renderer<TextureUploadHandler>("tfrag-tex-1", BucketId::TFRAG_TEX_LEVEL1);
|
||||
init_bucket_renderer<TFragment>("tfrag-1", BucketId::TFRAG_LEVEL1, normal_tfrags, false, 1);
|
||||
init_bucket_renderer<Tie3>("tie-1", BucketId::TIE_LEVEL1, 1);
|
||||
init_bucket_renderer<TextureUploadHandler>("shrub-tex-0", BucketId::SHRUB_TEX_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("shrub-tex-1", BucketId::SHRUB_TEX_LEVEL1);
|
||||
init_bucket_renderer<TextureUploadHandler>("alpha-tex-0", BucketId::ALPHA_TEX_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("alpha-tex-1", BucketId::ALPHA_TEX_LEVEL1);
|
||||
auto sky_gpu_blender = std::make_shared<SkyBlendGPU>();
|
||||
auto sky_cpu_blender = std::make_shared<SkyBlendCPU>();
|
||||
|
||||
//-------------
|
||||
// PRE TEXTURE
|
||||
//-------------
|
||||
// 0
|
||||
// 1
|
||||
// 2
|
||||
init_bucket_renderer<SkyRenderer>("sky", BucketId::SKY_DRAW); // 3
|
||||
// 4
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 0 tfrag texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("tfrag-tex-0", BucketId::TFRAG_TEX_LEVEL0); // 5
|
||||
init_bucket_renderer<TFragment>("tfrag-0", BucketId::TFRAG_LEVEL0, normal_tfrags, false, 0); // 6
|
||||
// 7
|
||||
// 8
|
||||
init_bucket_renderer<Tie3>("tie-0", BucketId::TIE_LEVEL0, 0); // 9
|
||||
init_bucket_renderer<MercRenderer>("merc-tf-0", BucketId::MERC_TFRAG_TEX_LEVEL0); // 10
|
||||
// 11
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 1 tfrag texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("tfrag-tex-1", BucketId::TFRAG_TEX_LEVEL1); // 12
|
||||
init_bucket_renderer<TFragment>("tfrag-1", BucketId::TFRAG_LEVEL1, normal_tfrags, false, 1);
|
||||
// 14
|
||||
// 15
|
||||
init_bucket_renderer<Tie3>("tie-1", BucketId::TIE_LEVEL1, 1);
|
||||
init_bucket_renderer<MercRenderer>("merc-tf-1", BucketId::MERC_TFRAG_TEX_LEVEL1); // 17
|
||||
// 18??
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 0 shrub texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("shrub-tex-0", BucketId::SHRUB_TEX_LEVEL0); // 19
|
||||
// 20
|
||||
// 21
|
||||
// 22
|
||||
// 23
|
||||
// 24
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 1 shrub texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("shrub-tex-1", BucketId::SHRUB_TEX_LEVEL1); // 25
|
||||
// 26
|
||||
// 27
|
||||
// 28
|
||||
// 29
|
||||
// 30
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 0 alpha texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("alpha-tex-0", BucketId::ALPHA_TEX_LEVEL0); // 31
|
||||
init_bucket_renderer<SkyBlendHandler>("sky-blend-and-tfrag-trans-0",
|
||||
BucketId::TFRAG_TRANS0_AND_SKY_BLEND_LEVEL0, 0,
|
||||
sky_gpu_blender, sky_cpu_blender);
|
||||
sky_gpu_blender, sky_cpu_blender); // 32
|
||||
// 33
|
||||
init_bucket_renderer<TFragment>("tfrag-dirt-0", BucketId::TFRAG_DIRT_LEVEL0, dirt_tfrags, false,
|
||||
0);
|
||||
0); // 34
|
||||
// 35
|
||||
init_bucket_renderer<TFragment>("tfrag-ice-0", BucketId::TFRAG_ICE_LEVEL0, ice_tfrags, false, 0);
|
||||
// 37
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 1 alpha texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("alpha-tex-1", BucketId::ALPHA_TEX_LEVEL1); // 38
|
||||
init_bucket_renderer<SkyBlendHandler>("sky-blend-and-tfrag-trans-1",
|
||||
BucketId::TFRAG_TRANS1_AND_SKY_BLEND_LEVEL1, 1,
|
||||
sky_gpu_blender, sky_cpu_blender);
|
||||
sky_gpu_blender, sky_cpu_blender); // 39
|
||||
// 40
|
||||
init_bucket_renderer<TFragment>("tfrag-dirt-1", BucketId::TFRAG_DIRT_LEVEL1, dirt_tfrags, false,
|
||||
1);
|
||||
1); // 41
|
||||
// 42
|
||||
init_bucket_renderer<TFragment>("tfrag-ice-1", BucketId::TFRAG_ICE_LEVEL1, ice_tfrags, false, 1);
|
||||
init_bucket_renderer<TextureUploadHandler>("pris-tex-0", BucketId::PRIS_TEX_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("pris-tex-1", BucketId::PRIS_TEX_LEVEL1);
|
||||
init_bucket_renderer<TextureUploadHandler>("water-tex-0", BucketId::WATER_TEX_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("water-tex-1", BucketId::WATER_TEX_LEVEL1);
|
||||
init_bucket_renderer<TextureUploadHandler>("pre-sprite-tex", BucketId::PRE_SPRITE_TEX);
|
||||
// 44
|
||||
init_bucket_renderer<MercRenderer>("merc-after-alpha", BucketId::MERC_AFTER_ALPHA);
|
||||
// 46?
|
||||
// 47?
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 0 pris texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("pris-tex-0", BucketId::PRIS_TEX_LEVEL0); // 48
|
||||
init_bucket_renderer<MercRenderer>("merc-pris-0", BucketId::MERC_PRIS_LEVEL0); // 49
|
||||
// 50
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 1 pris texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("pris-tex-1", BucketId::PRIS_TEX_LEVEL1); // 51
|
||||
init_bucket_renderer<MercRenderer>("merc-pris-1", BucketId::MERC_PRIS_LEVEL1); // 52
|
||||
// 53
|
||||
|
||||
// 54?
|
||||
init_bucket_renderer<MercRenderer>("merc-after-pris", BucketId::MERC_AFTER_PRIS); // 55
|
||||
// 56?
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 0 water texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("water-tex-0", BucketId::WATER_TEX_LEVEL0); // 57
|
||||
init_bucket_renderer<MercRenderer>("merc-water-0", BucketId::MERC_WATER_LEVEL0); // 58
|
||||
// 59
|
||||
|
||||
//-----------------------
|
||||
// LEVEL 1 water texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("water-tex-1", BucketId::WATER_TEX_LEVEL1); // 60
|
||||
init_bucket_renderer<MercRenderer>("merc-water-1", BucketId::MERC_WATER_LEVEL1); // 61
|
||||
// 62
|
||||
|
||||
// 63?
|
||||
// 64?
|
||||
|
||||
//-----------------------
|
||||
// COMMON texture
|
||||
//-----------------------
|
||||
init_bucket_renderer<TextureUploadHandler>("pre-sprite-tex", BucketId::PRE_SPRITE_TEX); // 65
|
||||
|
||||
std::vector<std::unique_ptr<BucketRenderer>> sprite_renderers;
|
||||
sprite_renderers.push_back(std::make_unique<SpriteRenderer>("sprite-renderer", BucketId::SPRITE));
|
||||
sprite_renderers.push_back(std::make_unique<Sprite3>("sprite-3", BucketId::SPRITE));
|
||||
init_bucket_renderer<RenderMux>("sprite", BucketId::SPRITE, std::move(sprite_renderers)); // 66
|
||||
|
||||
init_bucket_renderer<RenderMux>("sprite", BucketId::SPRITE, std::move(sprite_renderers));
|
||||
init_bucket_renderer<DirectRenderer>("debug-draw-0", BucketId::DEBUG_DRAW_0, 0x20000,
|
||||
DirectRenderer::Mode::NORMAL);
|
||||
init_bucket_renderer<DirectRenderer>("debug-draw-1", BucketId::DEBUG_DRAW_1, 0x8000,
|
||||
@@ -184,6 +277,7 @@ void OpenGLRenderer::draw_renderer_selection_window() {
|
||||
|
||||
ImGui::Checkbox("Sky CPU", &m_render_state.use_sky_cpu);
|
||||
ImGui::Checkbox("Occlusion Cull", &m_render_state.use_occlusion_culling);
|
||||
ImGui::Checkbox("Render Debug (slower)", &m_render_state.render_debug);
|
||||
|
||||
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
|
||||
auto renderer = m_bucket_renderers[i].get();
|
||||
|
||||
@@ -12,5 +12,5 @@ void main() {
|
||||
gl_Position = vec4((position_in.x - 0.5) * 16., -(position_in.y - 0.5) * 32, position_in.z * 2 - 1., 1.0);
|
||||
// scissoring area adjust
|
||||
gl_Position.y *= 512.0/448.0;
|
||||
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.w + 0.5);
|
||||
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.w * 2.);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ void main() {
|
||||
T0.w = 1.0;
|
||||
}
|
||||
color = fragment_color * T0 * 2.0;
|
||||
if (color.a <= alpha_reject) {
|
||||
if (color.a < alpha_reject) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ DoubleDraw setup_opengl_from_draw_mode(DrawMode mode, u32 tex_unit, bool mipmap)
|
||||
}
|
||||
}
|
||||
|
||||
if (mode.get_depth_write_enable()) {
|
||||
if (mode.get_depth_write_enable() && !alpha_hack_to_disable_z_write) {
|
||||
glDepthMask(GL_TRUE);
|
||||
} else {
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
@@ -689,3 +689,590 @@ void link() {
|
||||
} // namespace bones_mtx_calc
|
||||
} // namespace Mips2C
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
#include "game/kernel/kscheme.h"
|
||||
namespace Mips2C {
|
||||
namespace draw_bones_merc {
|
||||
struct Cache {
|
||||
void* merc_bucket_info; // *merc-bucket-info*
|
||||
void* merc_global_stats; // *merc-global-stats*
|
||||
void* fake_scratchpad_data;
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
c->daddiu(sp, sp, -128); // daddiu sp, sp, -128
|
||||
c->sd(ra, 0, sp); // sd ra, 0(sp)
|
||||
c->sq(s0, 16, sp); // sq s0, 16(sp)
|
||||
c->sq(s1, 32, sp); // sq s1, 32(sp)
|
||||
c->sq(s2, 48, sp); // sq s2, 48(sp)
|
||||
c->sq(s3, 64, sp); // sq s3, 64(sp)
|
||||
c->sq(s4, 80, sp); // sq s4, 80(sp)
|
||||
c->sq(s5, 96, sp); // sq s5, 96(sp)
|
||||
c->sq(gp, 112, sp); // sq gp, 112(sp)
|
||||
c->mov64(t8, a3); // or t8, a3, r0
|
||||
c->mov64(v1, t0); // or v1, t0, r0
|
||||
c->lui(t0, 4096); // lui t0, 4096
|
||||
c->lui(t1, 18304); // lui t1, 18304
|
||||
c->daddiu(t0, t0, 1); // daddiu t0, t0, 1
|
||||
c->dsll32(t1, t1, 0); // dsll32 t1, t1, 0
|
||||
c->lui(a3, 12288); // lui a3, 12288
|
||||
c->lui(t7, 19201); // lui t7, 19201
|
||||
c->pcpyld(t0, a3, t0); // pcpyld t0, a3, t0
|
||||
c->lbu(a3, 58, a0); // lbu a3, 58(a0)
|
||||
c->pcpyld(t1, t7, t1); // pcpyld t1, t7, t1
|
||||
c->lui(t2, 28160); // lui t2, 28160
|
||||
c->addiu(t7, r0, 8); // addiu t7, r0, 8
|
||||
c->multu3(a3, a3, t7); // multu3 a3, a3, t7
|
||||
c->lui(t3, 1280); // lui t3, 1280
|
||||
c->lui(t4, 27648); // lui t4, 27648
|
||||
c->dsll32(t2, t2, 0); // dsll32 t2, t2, 0
|
||||
c->dsll32(t4, t4, 0); // dsll32 t4, t4, 0
|
||||
c->daddu(t4, t4, t3); // daddu t4, t4, t3
|
||||
c->daddu(t3, t2, t3); // daddu t3, t2, t3
|
||||
c->daddiu(t3, t3, 1); // daddiu t3, t3, 1
|
||||
c->daddu(a0, a3, a0); // daddu a0, a3, a0
|
||||
c->pcpyld(t2, t2, r0); // pcpyld t2, t2, r0
|
||||
c->lw(t7, 24, a0); // lw t7, 24(a0)
|
||||
c->pcpyld(t3, t3, r0); // pcpyld t3, t3, r0
|
||||
c->pcpyld(t4, t4, r0); // pcpyld t4, t4, r0
|
||||
c->mov64(a0, a2); // or a0, a2, r0
|
||||
c->lui(t5, 12288); // lui t5, 12288
|
||||
c->lui(t6, 4096); // lui t6, 4096
|
||||
c->daddiu(t5, t5, 7); // daddiu t5, t5, 7
|
||||
c->lui(t9, 5120); // lui t9, 5120
|
||||
c->lui(a3, 27655); // lui a3, 27655
|
||||
c->daddu(t8, t9, t8); // daddu t8, t9, t8
|
||||
c->dsll32(a3, a3, 0); // dsll32 a3, a3, 0
|
||||
c->dsll32(t9, t8, 0); // dsll32 t9, t8, 0
|
||||
c->pcpyld(t5, a3, t5); // pcpyld t5, a3, t5
|
||||
c->lwu(t8, 52, t7); // lwu t8, 52(t7)
|
||||
c->pcpyld(t6, t9, t6); // pcpyld t6, t9, t6
|
||||
c->daddiu(t9, t7, 108); // daddiu t9, t7, 108
|
||||
c->load_symbol(a3, cache.merc_bucket_info); // lw a3, *merc-bucket-info*(s7)
|
||||
c->daddiu(ra, a3, 124); // daddiu ra, a3, 124
|
||||
|
||||
block_1:
|
||||
c->lbu(gp, 4, ra); // lbu gp, 4(ra)
|
||||
c->load_symbol(a3, cache.merc_global_stats); // lw a3, *merc-global-stats*(s7)
|
||||
c->daddu(a3, r0, a3); // daddu a3, r0, a3
|
||||
bc = c->sgpr64(gp) != 0; // bne gp, r0, L77
|
||||
c->lhu(s4, 2, a3); // lhu s4, 2(a3)
|
||||
if (bc) {goto block_11;} // branch non-likely
|
||||
|
||||
c->lhu(s3, 18, t9); // lhu s3, 18(t9)
|
||||
c->lwu(gp, 4, a3); // lwu gp, 4(a3)
|
||||
c->lhu(s5, 22, t9); // lhu s5, 22(t9)
|
||||
c->daddu(s4, s4, s3); // daddu s4, s4, s3
|
||||
c->lwu(s3, 8, a3); // lwu s3, 8(a3)
|
||||
c->lhu(s2, 24, t9); // lhu s2, 24(t9)
|
||||
c->daddu(gp, gp, s5); // daddu gp, gp, s5
|
||||
c->sh(s4, 2, a3); // sh s4, 2(a3)
|
||||
c->sw(gp, 4, a3); // sw gp, 4(a3)
|
||||
c->daddu(s5, s3, s2); // daddu s5, s3, s2
|
||||
c->lwu(t2, 0, t9); // lwu t2, 0(t9)
|
||||
c->lwu(gp, 4, t9); // lwu gp, 4(t9)
|
||||
c->lui(s4, 12288); // lui s4, 12288
|
||||
c->dsll32(t2, t2, 0); // dsll32 t2, t2, 0
|
||||
c->sw(s5, 8, a3); // sw s5, 8(a3)
|
||||
c->or_(t2, t2, s4); // or t2, t2, s4
|
||||
c->addiu(s5, r0, 0); // addiu s5, r0, 0
|
||||
c->lhu(s4, 18, t9); // lhu s4, 18(t9)
|
||||
|
||||
block_3:
|
||||
c->lbu(s0, 0, gp); // lbu s0, 0(gp)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lbu(s2, 1, gp); // lbu s2, 1(gp)
|
||||
c->xori(s1, r0, 49292); // xori s1, r0, 49292
|
||||
c->lbu(s3, 2, gp); // lbu s3, 2(gp)
|
||||
c->daddiu(v0, s0, 3); // daddiu v0, s0, 3
|
||||
c->lw(a3, 44, t7); // lw a3, 44(t7)
|
||||
c->srl(v0, v0, 2); // srl v0, v0, 2
|
||||
c->sq(t0, 0, a2); // sq t0, 0(a2)
|
||||
c->xor_(t2, t2, v0); // xor t2, t2, v0
|
||||
c->sq(t2, 32, a2); // sq t2, 32(a2)
|
||||
c->xor_(t2, t2, v0); // xor t2, t2, v0
|
||||
c->sh(s1, 44, a2); // sh s1, 44(a2)
|
||||
c->daddu(s1, s1, s0); // daddu s1, s1, s0
|
||||
c->sb(s0, 46, a2); // sb s0, 46(a2)
|
||||
c->dsll32(s0, v0, 4); // dsll32 s0, v0, 4
|
||||
c->daddu(t3, t2, s0); // daddu t3, t2, s0
|
||||
c->daddiu(s0, s2, 3); // daddiu s0, s2, 3
|
||||
c->sw(a3, 12, a2); // sw a3, 12(a2)
|
||||
c->srl(s0, s0, 2); // srl s0, s0, 2
|
||||
c->sq(t1, 16, a2); // sq t1, 16(a2)
|
||||
c->xor_(t3, t3, s0); // xor t3, t3, s0
|
||||
c->sq(t3, 48, a2); // sq t3, 48(a2)
|
||||
c->xor_(t3, t3, s0); // xor t3, t3, s0
|
||||
c->sh(s1, 60, a2); // sh s1, 60(a2)
|
||||
c->daddu(s1, s1, s2); // daddu s1, s1, s2
|
||||
c->sb(s2, 62, a2); // sb s2, 62(a2)
|
||||
c->dsll32(s2, s0, 4); // dsll32 s2, s0, 4
|
||||
c->sw(a3, 16, a2); // sw a3, 16(a2)
|
||||
c->daddu(t4, t3, s2); // daddu t4, t3, s2
|
||||
c->xor_(t4, t4, s3); // xor t4, t4, s3
|
||||
c->xori(a3, s1, 16384); // xori a3, s1, 16384
|
||||
c->sq(t4, 64, a2); // sq t4, 64(a2)
|
||||
c->xor_(t4, t4, s3); // xor t4, t4, s3
|
||||
c->sb(s3, 78, a2); // sb s3, 78(a2)
|
||||
c->dsll32(s3, s3, 4); // dsll32 s3, s3, 4
|
||||
c->sh(a3, 76, a2); // sh a3, 76(a2)
|
||||
c->daddu(t2, t4, s3); // daddu t2, t4, s3
|
||||
c->lbu(s3, 3, gp); // lbu s3, 3(gp)
|
||||
c->daddiu(gp, gp, 4); // daddiu gp, gp, 4
|
||||
bc = c->sgpr64(s5) != 0; // bne s5, r0, L73
|
||||
c->daddiu(a2, a2, 80); // daddiu a2, a2, 80
|
||||
if (bc) {goto block_5;} // branch non-likely
|
||||
|
||||
c->sd(t6, 0, a2); // sd t6, 0(a2)
|
||||
c->addiu(s2, r0, 8); // addiu s2, r0, 8
|
||||
c->sd(t6, 8, a2); // sd t6, 8(a2)
|
||||
c->lui(a3, 27656); // lui a3, 27656
|
||||
c->sb(s2, 0, a2); // sb s2, 0(a2)
|
||||
c->daddiu(a3, a3, 132); // daddiu a3, a3, 132
|
||||
c->load_symbol(s2, cache.merc_bucket_info); // lw s2, *merc-bucket-info*(s7)
|
||||
c->daddu(s2, r0, s2); // daddu s2, r0, s2
|
||||
c->sw(a3, 12, a2); // sw a3, 12(a2)
|
||||
c->lq(a3, 0, s2); // lq a3, 0(s2)
|
||||
c->lq(s1, 16, s2); // lq s1, 16(s2)
|
||||
c->lq(s0, 32, s2); // lq s0, 32(s2)
|
||||
c->lq(v0, 48, s2); // lq v0, 48(s2)
|
||||
c->sq(a3, 16, a2); // sq a3, 16(a2)
|
||||
c->sq(s1, 32, a2); // sq s1, 32(a2)
|
||||
c->sq(s0, 48, a2); // sq s0, 48(a2)
|
||||
c->sq(v0, 64, a2); // sq v0, 64(a2)
|
||||
c->lq(a3, 64, s2); // lq a3, 64(s2)
|
||||
c->lq(s1, 80, s2); // lq s1, 80(s2)
|
||||
c->lq(s0, 96, s2); // lq s0, 96(s2)
|
||||
c->lui(v0, 16261); // lui v0, 16261
|
||||
c->lq(s2, 28, t7); // lq s2, 28(t7)
|
||||
c->daddiu(v0, v0, 619); // daddiu v0, v0, 619
|
||||
c->sq(a3, 80, a2); // sq a3, 80(a2)
|
||||
c->lbu(a3, 5, ra); // lbu a3, 5(ra)
|
||||
c->sq(s1, 96, a2); // sq s1, 96(a2)
|
||||
c->sq(s0, 112, a2); // sq s0, 112(a2)
|
||||
c->dsubu(a3, v0, a3); // dsubu a3, v0, a3
|
||||
c->sq(s2, 128, a2); // sq s2, 128(a2)
|
||||
c->sw(a3, 28, a2); // sw a3, 28(a2)
|
||||
c->daddiu(a2, a2, 144); // daddiu a2, a2, 144
|
||||
|
||||
block_5:
|
||||
bc = c->sgpr64(s3) == 0; // beq s3, r0, L75
|
||||
c->addiu(s2, r0, 128); // addiu s2, r0, 128
|
||||
if (bc) {goto block_8;} // branch non-likely
|
||||
|
||||
c->lbu(a3, 0, gp); // lbu a3, 0(gp)
|
||||
|
||||
block_7:
|
||||
c->multu3(s1, a3, s2); // multu3 s1, a3, s2
|
||||
c->sq(t5, 0, a2); // sq t5, 0(a2)
|
||||
c->lbu(s0, 1, gp); // lbu s0, 1(gp)
|
||||
c->daddiu(gp, gp, 2); // daddiu gp, gp, 2
|
||||
c->lbu(a3, 0, gp); // lbu a3, 0(gp)
|
||||
c->daddiu(s3, s3, -1); // daddiu s3, s3, -1
|
||||
c->sb(s0, 12, a2); // sb s0, 12(a2)
|
||||
c->daddiu(a2, a2, 16); // daddiu a2, a2, 16
|
||||
c->daddu(s1, s1, a1); // daddu s1, s1, a1
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(s3) != 0; // bne s3, r0, L74
|
||||
c->sw(s1, -12, a2); // sw s1, -12(a2)
|
||||
if (bc) {goto block_7;} // branch non-likely
|
||||
|
||||
|
||||
block_8:
|
||||
c->sq(t6, 0, a2); // sq t6, 0(a2)
|
||||
c->daddiu(a2, a2, 16); // daddiu a2, a2, 16
|
||||
bc = c->sgpr64(s5) != 0; // bne s5, r0, L76
|
||||
c->daddiu(s5, s5, 1); // daddiu s5, s5, 1
|
||||
if (bc) {goto block_10;} // branch non-likely
|
||||
|
||||
c->mov64(a3, v1); // or a3, v1, r0
|
||||
c->sb(a3, -4, a2); // sb a3, -4(a2)
|
||||
|
||||
block_10:
|
||||
bc = c->sgpr64(s5) != c->sgpr64(s4); // bne s5, s4, L72
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_3;} // branch non-likely
|
||||
|
||||
|
||||
block_11:
|
||||
c->daddiu(t9, t9, 32); // daddiu t9, t9, 32
|
||||
c->daddiu(ra, ra, 8); // daddiu ra, ra, 8
|
||||
c->daddiu(t8, t8, -1); // daddiu t8, t8, -1
|
||||
bc = c->sgpr64(t8) != 0; // bne t8, r0, L71
|
||||
// c->lui(a3, 28672); // lui a3, 28672
|
||||
get_fake_spad_addr(a3, cache.fake_scratchpad_data, 0, c);
|
||||
if (bc) {goto block_1;} // branch non-likely
|
||||
|
||||
c->lw(v1, 220, a3); // lw v1, 220(a3)
|
||||
bc = c->sgpr64(v1) != 0; // bne v1, r0, L78
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_15;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(a2) == c->sgpr64(a0); // beq a2, a0, L78
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_15;} // branch non-likely
|
||||
|
||||
c->sw(a0, 220, a3); // sw a0, 220(a3)
|
||||
|
||||
block_15:
|
||||
c->mov64(v0, a2); // or v0, a2, r0
|
||||
c->ld(ra, 0, sp); // ld ra, 0(sp)
|
||||
c->lq(gp, 112, sp); // lq gp, 112(sp)
|
||||
c->lq(s5, 96, sp); // lq s5, 96(sp)
|
||||
c->lq(s4, 80, sp); // lq s4, 80(sp)
|
||||
c->lq(s3, 64, sp); // lq s3, 64(sp)
|
||||
c->lq(s2, 48, sp); // lq s2, 48(sp)
|
||||
c->lq(s1, 32, sp); // lq s1, 32(sp)
|
||||
c->lq(s0, 16, sp); // lq s0, 16(sp)
|
||||
//jr ra // jr ra
|
||||
c->daddiu(sp, sp, 128); // daddiu sp, sp, 128
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
cache.merc_bucket_info = intern_from_c("*merc-bucket-info*").c();
|
||||
cache.merc_global_stats = intern_from_c("*merc-global-stats*").c();
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
gLinkedFunctionTable.reg("draw-bones-merc", execute, 512);
|
||||
}
|
||||
|
||||
} // namespace draw_bones_merc
|
||||
} // namespace Mips2C
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
#include "game/kernel/kscheme.h"
|
||||
namespace Mips2C {
|
||||
namespace draw_bones_check_longest_edge_asm {
|
||||
struct Cache {
|
||||
void* math_camera; // *math-camera*
|
||||
void* fake_scratchpad_data;
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
bool cop1_bc = false;
|
||||
float acc;
|
||||
c->daddiu(sp, sp, -16); // daddiu sp, sp, -16
|
||||
c->sd(fp, 8, sp); // sd fp, 8(sp)
|
||||
c->mov64(fp, t9); // or fp, t9, r0
|
||||
// c->lui(at, 28672); // lui at, 28672
|
||||
get_fake_spad_addr(at, cache.fake_scratchpad_data, 0, c);
|
||||
c->mov64(v0, s7); // or v0, s7, r0
|
||||
c->load_symbol(v1, cache.math_camera); // lw v1, *math-camera*(s7)
|
||||
c->lwc1(f0, 64, a0); // lwc1 f0, 64(a0)
|
||||
c->lwc1(f7, 176, at); // lwc1 f7, 176(at)
|
||||
c->lwc1(f3, 180, at); // lwc1 f3, 180(at)
|
||||
c->lwc1(f6, 184, at); // lwc1 f6, 184(at)
|
||||
c->lwc1(f4, 136, a0); // lwc1 f4, 136(a0)
|
||||
c->lwc1(f12, 0, v1); // lwc1 f12, 0(v1)
|
||||
c->lwc1(f11, 64, v1); // lwc1 f11, 64(v1)
|
||||
c->mtc1(f1, a1); // mtc1 f1, a1
|
||||
c->mtc1(f9, r0); // mtc1 f9, r0
|
||||
c->mtc1(f10, r0); // mtc1 f10, r0
|
||||
c->mtc1(f2, r0); // mtc1 f2, r0
|
||||
c->mtc1(f2, r0); // mtc1 f2, r0
|
||||
c->mtc1(f5, r0); // mtc1 f5, r0
|
||||
c->mtc1(f8, r0); // mtc1 f8, r0
|
||||
c->lw_float_constant(a0, 0x3f800000); // lw a0, L168(fp) 1.0
|
||||
c->mtc1(f5, a0); // mtc1 f5, a0
|
||||
cop1_bc = c->fprs[f1] < c->fprs[f11]; // c.lt.s f1, f11
|
||||
bc = cop1_bc; // bc1t L69
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_37;} // branch non-likely
|
||||
|
||||
c->lwc1(f11, 12, v1); // lwc1 f11, 12(v1)
|
||||
c->lwc1(f13, 16, v1); // lwc1 f13, 16(v1)
|
||||
c->muls(f11, f11, f12); // mul.s f11, f11, f12
|
||||
c->muls(f13, f13, f12); // mul.s f13, f13, f12
|
||||
c->subs(f14, f6, f4); // sub.s f14, f6, f4
|
||||
cop1_bc = c->fprs[f12] < c->fprs[f14]; // c.lt.s f12, f14
|
||||
bc = !cop1_bc; // bc1f L53
|
||||
c->lwc1(f12, 60, v1); // lwc1 f12, 60(v1)
|
||||
if (bc) {goto block_3;} // branch non-likely
|
||||
|
||||
c->muls(f12, f14, f12); // mul.s f12, f14, f12
|
||||
cop1_bc = c->fprs[f0] < c->fprs[f12]; // c.lt.s f0, f12
|
||||
bc = cop1_bc; // bc1t L68
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {
|
||||
// fmt::print("pass 1 due to {} {}\n", c->fprs[f0], c->fprs[f12]);
|
||||
goto block_36;} // branch non-likely
|
||||
|
||||
|
||||
block_3:
|
||||
c->subs(f14, f3, f4); // sub.s f14, f3, f4
|
||||
cop1_bc = c->fprs[f13] < c->fprs[f14]; // c.lt.s f13, f14
|
||||
bc = !cop1_bc; // bc1f L54
|
||||
c->lwc1(f12, 56, v1); // lwc1 f12, 56(v1)
|
||||
if (bc) {goto block_5;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L55 // beq r0, r0, L55
|
||||
c->muls(f10, f14, f12); // mul.s f10, f14, f12
|
||||
goto block_7; // branch always
|
||||
|
||||
|
||||
block_5:
|
||||
c->adds(f14, f3, f4); // add.s f14, f3, f4
|
||||
c->negs(f13, f13); // neg.s f13, f13
|
||||
cop1_bc = c->fprs[f14] < c->fprs[f13]; // c.lt.s f14, f13
|
||||
bc = !cop1_bc; // bc1f L55
|
||||
c->negs(f13, f14); // neg.s f13, f14
|
||||
if (bc) {goto block_7;} // branch non-likely
|
||||
|
||||
c->muls(f10, f13, f12); // mul.s f10, f13, f12
|
||||
|
||||
block_7:
|
||||
cop1_bc = c->fprs[f0] < c->fprs[f10]; // c.lt.s f0, f10
|
||||
bc = cop1_bc; // bc1t L68
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {
|
||||
// fmt::print("pass 2 due to {} {}\n", c->fprs[f0], c->fprs[f10]);
|
||||
goto block_36;} // branch non-likely
|
||||
|
||||
c->subs(f12, f7, f4); // sub.s f12, f7, f4
|
||||
cop1_bc = c->fprs[f11] < c->fprs[f12]; // c.lt.s f11, f12
|
||||
bc = !cop1_bc; // bc1f L56
|
||||
c->lwc1(f10, 52, v1); // lwc1 f10, 52(v1)
|
||||
if (bc) {goto block_10;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L57 // beq r0, r0, L57
|
||||
c->muls(f9, f12, f10); // mul.s f9, f12, f10
|
||||
goto block_12; // branch always
|
||||
|
||||
|
||||
block_10:
|
||||
c->adds(f12, f7, f4); // add.s f12, f7, f4
|
||||
c->negs(f11, f11); // neg.s f11, f11
|
||||
cop1_bc = c->fprs[f12] < c->fprs[f11]; // c.lt.s f12, f11
|
||||
bc = !cop1_bc; // bc1f L57
|
||||
c->negs(f11, f12); // neg.s f11, f12
|
||||
if (bc) {goto block_12;} // branch non-likely
|
||||
|
||||
c->muls(f9, f11, f10); // mul.s f9, f11, f10
|
||||
|
||||
block_12:
|
||||
cop1_bc = c->fprs[f0] < c->fprs[f9]; // c.lt.s f0, f9
|
||||
bc = cop1_bc; // bc1t L68
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {
|
||||
// fmt::print("pass 3 due to {} {}\n", c->fprs[f0], c->fprs[f9]);
|
||||
goto block_36;} // branch non-likely
|
||||
|
||||
|
||||
c->abss(f14, f7);// Unknown instr: abs.s f14, f7
|
||||
c->movs(f12, f6); // mov.s f12, f6
|
||||
acc = c->fprs[f14] * c->fprs[f14]; // Unknown instr: mula.s f14, f14
|
||||
c->fprs[f15] = acc + c->fprs[f12] * c->fprs[f12]; // Unknown instr: madd.s f15, f12, f12
|
||||
c->lwc1(f9, 76, v1); // lwc1 f9, 76(v1)
|
||||
c->lwc1(f13, 80, v1); // lwc1 f13, 80(v1)
|
||||
c->lwc1(f10, 84, v1); // lwc1 f10, 84(v1)
|
||||
c->lwc1(f11, 88, v1); // lwc1 f11, 88(v1)
|
||||
c->fprs[f16] = c->fprs[f5] / (std::sqrt(std::abs(c->fprs[f15]))); // Unknown instr: rsqrt.s f16, f5, f15
|
||||
c->muls(f15, f14, f16); // mul.s f15, f14, f16
|
||||
c->muls(f16, f12, f16); // mul.s f16, f12, f16
|
||||
acc = c->fprs[f9] * c->fprs[f16]; // Unknown instr: mula.s f9, f16
|
||||
c->fprs[f12] = acc - c->fprs[f13] * c->fprs[f15]; // Unknown instr: msub.s f12, f13, f15
|
||||
acc = c->fprs[f10] * c->fprs[f16]; // Unknown instr: mula.s f10, f16
|
||||
c->fprs[f14] = acc - c->fprs[f11] * c->fprs[f15];// Unknown instr: msub.s f14, f11, f15
|
||||
acc = c->fprs[f9] * c->fprs[f15];// Unknown instr: mula.s f9, f15
|
||||
c->fprs[f9] = acc + c->fprs[f13] * c->fprs[f16];// Unknown instr: madd.s f9, f13, f16
|
||||
acc = c->fprs[f10] * c->fprs[f15];// Unknown instr: mula.s f10, f15
|
||||
c->fprs[f10] = acc + c->fprs[f11] * c->fprs[f16];// Unknown instr: madd.s f10, f11, f16
|
||||
cop1_bc = c->fprs[f8] < c->fprs[f12]; // c.lt.s f8, f12
|
||||
bc = cop1_bc; // bc1t L58
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_17;} // branch non-likely
|
||||
|
||||
cop1_bc = c->fprs[f8] < c->fprs[f14]; // c.lt.s f8, f14
|
||||
bc = cop1_bc; // bc1t L59
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_18;} // branch non-likely
|
||||
|
||||
cop1_bc = c->fprs[f8] < c->fprs[f9]; // c.lt.s f8, f9
|
||||
bc = cop1_bc; // bc1t L60
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_19;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L62 // beq r0, r0, L62
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_23; // branch always
|
||||
|
||||
|
||||
block_17:
|
||||
//beq r0, r0, L62 // beq r0, r0, L62
|
||||
c->divs(f2, f1, f10); // div.s f2, f1, f10
|
||||
goto block_23; // branch always
|
||||
|
||||
|
||||
block_18:
|
||||
c->negs(f2, f12); // neg.s f2, f12
|
||||
c->divs(f2, f2, f9); // div.s f2, f2, f9
|
||||
c->divs(f7, f14, f10); // div.s f7, f14, f10
|
||||
c->adds(f2, f7, f2); // add.s f2, f7, f2
|
||||
//beq r0, r0, L62 // beq r0, r0, L62
|
||||
c->muls(f2, f2, f1); // mul.s f2, f2, f1
|
||||
goto block_23; // branch always
|
||||
|
||||
|
||||
block_19:
|
||||
c->subs(f8, f7, f4); // sub.s f8, f7, f4
|
||||
c->adds(f10, f7, f4); // add.s f10, f7, f4
|
||||
c->negs(f11, f7); // neg.s f11, f7
|
||||
cop1_bc = c->fprs[f7] < c->fprs[f8]; // c.lt.s f7, f8
|
||||
bc = cop1_bc; // bc1t L61
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_22;} // branch non-likely
|
||||
|
||||
cop1_bc = c->fprs[f10] < c->fprs[f11]; // c.lt.s f10, f11
|
||||
bc = cop1_bc; // bc1t L61
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_22;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L62 // beq r0, r0, L62
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_23; // branch always
|
||||
|
||||
|
||||
block_22:
|
||||
c->negs(f2, f12); // neg.s f2, f12
|
||||
c->muls(f2, f1, f2); // mul.s f2, f1, f2
|
||||
c->divs(f2, f2, f9); // div.s f2, f2, f9
|
||||
|
||||
block_23:
|
||||
cop1_bc = c->fprs[f0] < c->fprs[f2]; // c.lt.s f0, f2
|
||||
bc = cop1_bc; // bc1t L68
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {
|
||||
// fmt::print("pass 4 due to {} {}\n", c->fprs[f0], c->fprs[f2]);
|
||||
goto block_36;} // branch non-likely
|
||||
|
||||
c->abss(f10, f3);// Unknown instr: abs.s f10, f3
|
||||
c->movs(f12, f6); // mov.s f12, f6
|
||||
acc = c->fprs[f10] * c->fprs[f10];// Unknown instr: mula.s f10, f10
|
||||
c->fprs[f9] = acc + c->fprs[f12] * c->fprs[f12];// Unknown instr: madd.s f9, f12, f12
|
||||
c->lwc1(f7, 96, v1); // lwc1 f7, 96(v1)
|
||||
c->lwc1(f8, 100, v1); // lwc1 f8, 100(v1)
|
||||
c->lwc1(f6, 104, v1); // lwc1 f6, 104(v1)
|
||||
c->fprs[f5] = c->fprs[f5] / std::sqrt(std::abs(c->fprs[f9])); // Unknown instr: rsqrt.s f5, f5, f9
|
||||
c->lwc1(f11, 108, v1); // lwc1 f11, 108(v1)
|
||||
c->mtc1(f9, r0); // mtc1 f9, r0
|
||||
c->muls(f13, f10, f5); // mul.s f13, f10, f5
|
||||
c->muls(f14, f12, f5); // mul.s f14, f12, f5
|
||||
acc = c->fprs[f7] * c->fprs[f14];// Unknown instr: mula.s f7, f14
|
||||
c->fprs[f10] = acc - c->fprs[f8] * c->fprs[f13];// Unknown instr: msub.s f10, f8, f13
|
||||
acc = c->fprs[f6] * c->fprs[f14];// Unknown instr: mula.s f6, f14
|
||||
c->fprs[f12] = acc - c->fprs[f11] * c->fprs[f13];// Unknown instr: msub.s f12, f11, f13
|
||||
acc = c->fprs[f7] * c->fprs[f13];// Unknown instr: mula.s f7, f13
|
||||
c->fprs[f5] = acc + c->fprs[f8] * c->fprs[f14];// Unknown instr: madd.s f5, f8, f14
|
||||
acc = c->fprs[f6] * c->fprs[f13];// Unknown instr: mula.s f6, f13
|
||||
c->fprs[f6] = acc + c->fprs[f11] * c->fprs[f14];// Unknown instr: madd.s f6, f11, f14
|
||||
cop1_bc = c->fprs[f9] < c->fprs[f10]; // c.lt.s f9, f10
|
||||
bc = cop1_bc; // bc1t L63
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_28;} // branch non-likely
|
||||
|
||||
cop1_bc = c->fprs[f9] < c->fprs[f12]; // c.lt.s f9, f12
|
||||
bc = cop1_bc; // bc1t L64
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_29;} // branch non-likely
|
||||
|
||||
cop1_bc = c->fprs[f9] < c->fprs[f5]; // c.lt.s f9, f5
|
||||
bc = cop1_bc; // bc1t L65
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_30;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L67 // beq r0, r0, L67
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_34; // branch always
|
||||
|
||||
|
||||
block_28:
|
||||
//beq r0, r0, L67 // beq r0, r0, L67
|
||||
c->divs(f1, f1, f6); // div.s f1, f1, f6
|
||||
goto block_34; // branch always
|
||||
|
||||
|
||||
block_29:
|
||||
c->negs(f3, f10); // neg.s f3, f10
|
||||
c->divs(f3, f3, f5); // div.s f3, f3, f5
|
||||
c->divs(f4, f12, f6); // div.s f4, f12, f6
|
||||
c->adds(f3, f4, f3); // add.s f3, f4, f3
|
||||
//beq r0, r0, L67 // beq r0, r0, L67
|
||||
c->muls(f1, f3, f1); // mul.s f1, f3, f1
|
||||
goto block_34; // branch always
|
||||
|
||||
|
||||
block_30:
|
||||
c->subs(f6, f3, f4); // sub.s f6, f3, f4
|
||||
c->adds(f4, f3, f4); // add.s f4, f3, f4
|
||||
c->negs(f7, f3); // neg.s f7, f3
|
||||
cop1_bc = c->fprs[f3] < c->fprs[f6]; // c.lt.s f3, f6
|
||||
bc = cop1_bc; // bc1t L66
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_33;} // branch non-likely
|
||||
|
||||
cop1_bc = c->fprs[f4] < c->fprs[f7]; // c.lt.s f4, f7
|
||||
bc = cop1_bc; // bc1t L66
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_33;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L67 // beq r0, r0, L67
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_34; // branch always
|
||||
|
||||
|
||||
block_33:
|
||||
c->negs(f3, f10); // neg.s f3, f10
|
||||
c->muls(f1, f1, f3); // mul.s f1, f1, f3
|
||||
c->divs(f1, f1, f5); // div.s f1, f1, f5
|
||||
|
||||
block_34:
|
||||
//fmt::print("check: {} {}\n", c->fprs[f0], c->fprs[f2]);
|
||||
cop1_bc = c->fprs[f0] < c->fprs[f2]; // c.lt.s f0, f2
|
||||
bc = cop1_bc; // bc1t L68
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {
|
||||
// fmt::print("pass 5 due to {} {}\n", c->fprs[f0], c->fprs[f2]);
|
||||
goto block_36;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L69 // beq r0, r0, L69
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_37; // branch always
|
||||
|
||||
|
||||
block_36:
|
||||
// fmt::print("pass!\n");
|
||||
c->daddiu(v0, s7, 8); // daddiu v0, s7, #t
|
||||
|
||||
block_37:
|
||||
c->ld(fp, 8, sp); // ld fp, 8(sp)
|
||||
//jr ra // jr ra
|
||||
c->daddiu(sp, sp, 16); // daddiu sp, sp, 16
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
cache.math_camera = intern_from_c("*math-camera*").c();
|
||||
gLinkedFunctionTable.reg("draw-bones-check-longest-edge-asm", execute, 128);
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
}
|
||||
|
||||
} // namespace draw_bones_check_longest_edge_asm
|
||||
} // namespace Mips2C
|
||||
|
||||
|
||||
@@ -0,0 +1,588 @@
|
||||
|
||||
// clang-format off
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
#include "game/kernel/kscheme.h"
|
||||
namespace Mips2C {
|
||||
namespace blerc_execute {
|
||||
struct Cache {
|
||||
void* blerc_globals; // *blerc-globals*
|
||||
void* gsf_buffer; // *gsf-buffer*
|
||||
void* stats_blerc; // *stats-blerc*
|
||||
void* flush_cache; // flush-cache
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
u32 madr, sadr, qwc, tadr;
|
||||
c->daddiu(sp, sp, -96); // daddiu sp, sp, -96
|
||||
c->sd(ra, 0, sp); // sd ra, 0(sp)
|
||||
c->sq(s2, 16, sp); // sq s2, 16(sp)
|
||||
c->sq(s3, 32, sp); // sq s3, 32(sp)
|
||||
c->sq(s4, 48, sp); // sq s4, 48(sp)
|
||||
c->sq(s5, 64, sp); // sq s5, 64(sp)
|
||||
c->sq(gp, 80, sp); // sq gp, 80(sp)
|
||||
c->load_symbol(v1, cache.blerc_globals); // lw v1, *blerc-globals*(s7)
|
||||
c->lwu(s5, 0, v1); // lwu s5, 0(v1)
|
||||
bc = c->sgpr64(s5) == 0; // beq s5, r0, L46
|
||||
c->mov64(v1, s7); // or v1, s7, r0
|
||||
if (bc) {goto block_33;} // branch non-likely
|
||||
|
||||
c->addiu(v1, r0, 0); // addiu v1, r0, 0
|
||||
c->addiu(gp, r0, 0); // addiu gp, r0, 0
|
||||
c->addiu(v1, r0, 0); // addiu v1, r0, 0
|
||||
c->load_symbol(v1, cache.gsf_buffer); // lw v1, *gsf-buffer*(s7)
|
||||
c->load_symbol(t9, cache.flush_cache); // lw t9, flush-cache(s7)
|
||||
c->addiu(a0, r0, 0); // addiu a0, r0, 0
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->sll(v0, ra, 0); // sll v0, ra, 0
|
||||
c->jalr(call_addr); // jalr ra, t9
|
||||
c->addiu(v1, r0, 848); // addiu v1, r0, 848
|
||||
// c->lui(a0, 28672); // lui a0, 28672
|
||||
get_fake_spad_addr(a0, cache.fake_scratchpad_data, 0, c);
|
||||
c->daddu(a1, v1, a0); // daddu a1, v1, a0
|
||||
c->load_symbol(v1, cache.blerc_globals); // lw v1, *blerc-globals*(s7)
|
||||
c->daddu(v1, r0, v1); // daddu v1, r0, v1
|
||||
// nop // sll r0, r0, 0
|
||||
c->lui(a0, 4096); // lui a0, 4096
|
||||
// nop // sll r0, r0, 0
|
||||
c->ori(a0, a0, 54272); // ori a0, a0, 54272 // spr to
|
||||
c->andi(a1, a1, 16383); // andi a1, a1, 16383
|
||||
/*
|
||||
block_2:
|
||||
c->lw(a2, 0, a0); // lw a2, 0(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(a2, a2, 256); // andi a2, a2, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(a2) != 0; // bne a2, r0, L28
|
||||
c->lw(a2, 0, v1); // lw a2, 0(v1)
|
||||
if (bc) {goto block_2;} // branch non-likely
|
||||
*/
|
||||
c->lw(a2, 0, v1);
|
||||
|
||||
bc = c->sgpr64(a2) == 0; // beq a2, r0, L29
|
||||
//c->sw(a1, 128, a0); // sw a1, 128(a0)
|
||||
sadr = c->sgpr64(a1);
|
||||
if (bc) {goto block_5;} // branch non-likely
|
||||
|
||||
c->addiu(v1, r0, 324); // addiu v1, r0, 324
|
||||
//c->sw(a2, 48, a0); // sw a2, 48(a0)
|
||||
tadr = c->sgpr64(a2);
|
||||
//c->sw(r0, 32, a0); // sw r0, 32(a0)
|
||||
// Unknown instr: sync.l
|
||||
//c->sw(v1, 0, a0); // sw v1, 0(a0)
|
||||
spad_to_dma_blerc_chain(cache.fake_scratchpad_data, sadr, tadr);
|
||||
// Unknown instr: sync.l
|
||||
|
||||
block_5:
|
||||
c->gprs[v1].du64[0] = 0; // or v1, r0, r0
|
||||
//beq r0, r0, L45 // beq r0, r0, L45
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_31; // branch always
|
||||
|
||||
|
||||
block_6:
|
||||
bc = c->sgpr64(gp) != 0; // bne gp, r0, L31
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_8;} // branch non-likely
|
||||
|
||||
//c->lui(v1, 28672); // lui v1, 28672
|
||||
get_fake_spad_addr(v1, cache.fake_scratchpad_data, 0, c);
|
||||
c->daddu(a0, r0, v1); // daddu a0, r0, v1
|
||||
//beq r0, r0, L32 // beq r0, r0, L32
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_9; // branch always
|
||||
|
||||
|
||||
block_8:
|
||||
c->addiu(v1, r0, 8192); // addiu v1, r0, 8192
|
||||
// c->lui(a0, 28672); // lui a0, 28672
|
||||
get_fake_spad_addr(a0, cache.fake_scratchpad_data, 0, c);
|
||||
c->daddu(a0, v1, a0); // daddu a0, v1, a0
|
||||
|
||||
block_9:
|
||||
bc = c->sgpr64(gp) != 0; // bne gp, r0, L33
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_11;} // branch non-likely
|
||||
|
||||
c->addiu(v1, r0, 8192); // addiu v1, r0, 8192
|
||||
// c->lui(a1, 28672); // lui a1, 28672
|
||||
get_fake_spad_addr(a1, cache.fake_scratchpad_data, 0, c);
|
||||
c->daddu(a1, v1, a1); // daddu a1, v1, a1
|
||||
//beq r0, r0, L34 // beq r0, r0, L34
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_12; // branch always
|
||||
|
||||
|
||||
block_11:
|
||||
// c->lui(v1, 28672); // lui v1, 28672
|
||||
get_fake_spad_addr(v1, cache.fake_scratchpad_data, 0, c);
|
||||
c->daddu(a1, r0, v1); // daddu a1, r0, v1
|
||||
|
||||
block_12:
|
||||
c->daddiu(v1, a0, 848); // daddiu v1, a0, 848
|
||||
c->daddu(a2, r0, a0); // daddu a2, r0, a0
|
||||
c->daddiu(a3, a1, 848); // daddiu a3, a1, 848
|
||||
c->daddiu(a1, v1, 12); // daddiu a1, v1, 12
|
||||
// nop // sll r0, r0, 0
|
||||
c->lui(a2, 4096); // lui a2, 4096
|
||||
// nop // sll r0, r0, 0
|
||||
c->ori(a2, a2, 54272); // ori a2, a2, 54272
|
||||
c->andi(a3, a3, 16383); // andi a3, a3, 16383
|
||||
|
||||
|
||||
/*
|
||||
block_13:
|
||||
c->lw(t0, 0, a2); // lw t0, 0(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(t0, t0, 256); // andi t0, t0, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t0) != 0; // bne t0, r0, L35
|
||||
c->lw(t0, 0, a1); // lw t0, 0(a1)
|
||||
if (bc) {goto block_13;} // branch non-likely
|
||||
*/
|
||||
|
||||
c->lw(t0, 0, a1);
|
||||
|
||||
|
||||
bc = c->sgpr64(t0) == 0; // beq t0, r0, L36
|
||||
// c->sw(a3, 128, a2); // sw a3, 128(a2)
|
||||
sadr = c->sgpr64(a3);
|
||||
if (bc) {goto block_16;} // branch non-likely
|
||||
|
||||
c->addiu(a1, r0, 324); // addiu a1, r0, 324
|
||||
// c->sw(t0, 48, a2); // sw t0, 48(a2)
|
||||
tadr = c->sgpr64(t0);
|
||||
// c->sw(r0, 32, a2); // sw r0, 32(a2)
|
||||
// Unknown instr: sync.l
|
||||
//c->sw(a1, 0, a2); // sw a1, 0(a2)
|
||||
// tadr here is bogus, it's reading something uploaded by the other transfer.
|
||||
spad_to_dma_blerc_chain(cache.fake_scratchpad_data, sadr, tadr);
|
||||
|
||||
// Unknown instr: sync.l
|
||||
|
||||
block_16:
|
||||
c->gprs[a1].du64[0] = 0; // or a1, r0, r0
|
||||
c->mov64(a2, a0); // or a2, a0, r0
|
||||
c->load_symbol(a3, cache.gsf_buffer); // lw a3, *gsf-buffer*(s7)
|
||||
c->daddiu(t2, a2, 880); // daddiu t2, a2, 880
|
||||
c->lb(t1, 0, t2); // lb t1, 0(t2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov64(t0, a2); // or t0, a2, r0
|
||||
c->lw(a1, 868, a2); // lw a1, 868(a2)
|
||||
c->daddiu(t3, t1, 1); // daddiu t3, t1, 1
|
||||
|
||||
c->mov64(t1, a3); // or t1, a3, r0
|
||||
c->sll(t8, t3, 4); // sll t8, t3, 4
|
||||
c->sll(t3, a1, 4); // sll t3, a1, 4
|
||||
c->daddu(t9, t3, a3); // daddu t9, t3, a3
|
||||
c->daddu(t3, t2, t8); // daddu t3, t2, t8
|
||||
bc = c->sgpr64(a1) == 0; // beq a1, r0, L39
|
||||
c->daddiu(ra, t2, 16); // daddiu ra, t2, 16
|
||||
if (bc) {goto block_21;} // branch non-likely
|
||||
|
||||
c->lh(t5, 12, t3); // lh t5, 12(t3)
|
||||
c->daddu(t2, t3, t8); // daddu t2, t3, t8
|
||||
//beq r0, r0, L38 // beq r0, r0, L38
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_19; // branch always
|
||||
|
||||
|
||||
block_18:
|
||||
c->lh(t5, 12, t2); // lh t5, 12(t2)
|
||||
c->daddu(t2, t2, t8); // daddu t2, t2, t8
|
||||
c->sq(t6, 0, t1); // sq t6, 0(t1)
|
||||
c->daddiu(t1, t1, 16); // daddiu t1, t1, 16
|
||||
|
||||
block_19:
|
||||
c->pcpyh(t5, t5); // pcpyh t5, t5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
//fmt::print("loop: {:x} {:x}\n", c->sgpr64(t1), c->sgpr64(t9));
|
||||
bc = c->sgpr64(t1) != c->sgpr64(t9); // bne t1, t9, L37
|
||||
c->pcpyld(t6, t5, t5); // pcpyld t6, t5, t5
|
||||
if (bc) {goto block_18;} // branch non-likely
|
||||
|
||||
c->dsubu(t3, t2, t8); // dsubu t3, t2, t8
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_21:
|
||||
c->addiu(t1, r0, 255); // addiu t1, r0, 255
|
||||
c->addiu(t2, r0, 8192); // addiu t2, r0, 8192
|
||||
c->lb(s5, 0, t3); // lb s5, 0(t3)
|
||||
c->daddiu(s4, t3, 16); // daddiu s4, t3, 16
|
||||
c->pcpyh(t1, t1); // pcpyh t1, t1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(t1, t1, t1); // pcpyld t1, t1, t1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyh(t2, t2); // pcpyh t2, t2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(t2, t2, t2); // pcpyld t2, t2, t2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->mov128_gpr_gpr(t3, t1); // por t3, t1, r0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->mov128_gpr_gpr(t4, r0); // por t4, r0, r0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
|
||||
block_22:
|
||||
c->ld(t6, 0, ra); // ld t6, 0(ra)
|
||||
c->daddu(s2, ra, t8); // daddu s2, ra, t8
|
||||
c->daddiu(ra, ra, 8); // daddiu ra, ra, 8
|
||||
c->mov64(s3, a3); // or s3, a3, r0
|
||||
c->pextlb(t6, r0, t6); // pextlb t6, r0, t6
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pmulth(t7, t6, t2); // pmulth t7, t6, t2
|
||||
c->ld(t5, 0, s2); // ld t5, 0(s2)
|
||||
c->daddiu(s5, s5, -1); // daddiu s5, s5, -1
|
||||
// nop // sll r0, r0, 0
|
||||
//beq r0, r0, L42 // beq r0, r0, L42
|
||||
c->daddu(s2, s2, t8); // daddu s2, s2, t8
|
||||
goto block_24; // branch always
|
||||
|
||||
|
||||
block_23:
|
||||
c->pmaddh(t7, t5, t6); // pmaddh t7, t5, t6
|
||||
c->ld(t5, 0, s2); // ld t5, 0(s2)
|
||||
c->daddu(s2, s2, t8); // daddu s2, s2, t8
|
||||
c->daddiu(s3, s3, 16); // daddiu s3, s3, 16
|
||||
|
||||
block_24:
|
||||
c->lq(t6, 0, s3); // lq t6, 0(s3)
|
||||
c->pextlb(t5, t5, r0); // pextlb t5, t5, r0
|
||||
bc = c->sgpr64(s3) != c->sgpr64(t9); // bne s3, t9, L41
|
||||
c->psrah(t5, t5, 8); // psrah t5, t5, 8
|
||||
if (bc) {goto block_23;} // branch non-likely
|
||||
|
||||
//todo // Unknown instr: pmfhl.uw t5
|
||||
c->gprs[t5].du32[0] = c->lo.du32[1];
|
||||
c->gprs[t5].du32[1] = c->hi.du32[1];
|
||||
c->gprs[t5].du32[2] = c->lo.du32[3];
|
||||
c->gprs[t5].du32[3] = c->hi.du32[3];
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->psraw(t7, t7, 13); // psraw t7, t7, 13
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->psraw(t5, t5, 13); // psraw t5, t5, 13
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pinteh(t5, t5, t7); // pinteh t5, t5, t7
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pminh(t3, t3, t5); // pminh t3, t3, t5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pmaxh(t4, t4, t5); // pmaxh t4, t4, t5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pminh(t5, t5, t1); // pminh t5, t5, t1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pmaxh(t5, t5, r0); // pmaxh t5, t5, r0
|
||||
c->lq(t7, 0, s4); // lq t7, 0(s4)
|
||||
c->ppacb(t5, r0, t5); // ppacb t5, r0, t5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->ppach(t7, r0, t7); // ppach t7, r0, t7
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlh(t5, t5, t7); // pextlh t5, t5, t7
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->sq(t5, 0, t0); // sq t5, 0(t0)
|
||||
c->daddiu(t0, t0, 16); // daddiu t0, t0, 16
|
||||
bc = c->sgpr64(s5) != 0; // bne s5, r0, L40
|
||||
c->daddiu(s4, s4, 16); // daddiu s4, s4, 16
|
||||
if (bc) {goto block_22;} // branch non-likely
|
||||
|
||||
c->load_symbol(a3, cache.stats_blerc); // lw a3, *stats-blerc*(s7)
|
||||
bc = c->sgpr64(a3) == c->sgpr64(s7); // beq a3, s7, L43
|
||||
c->load_symbol(a3, cache.blerc_globals); // lw a3, *blerc-globals*(s7)
|
||||
if (bc) {goto block_28;} // branch non-likely
|
||||
|
||||
c->lw(t2, 12, a3); // lw t2, 12(a3)
|
||||
c->lw(t1, 16, a3); // lw t1, 16(a3)
|
||||
c->lw(t0, 20, a3); // lw t0, 20(a3)
|
||||
c->lw(a2, 864, a2); // lw a2, 864(a2)
|
||||
c->multu3(a1, a1, a2); // multu3 a1, a1, a2
|
||||
c->daddiu(t2, t2, 1); // daddiu t2, t2, 1
|
||||
c->daddu(a2, t1, a2); // daddu a2, t1, a2
|
||||
c->daddu(a1, t0, a1); // daddu a1, t0, a1
|
||||
c->sw(t2, 12, a3); // sw t2, 12(a3)
|
||||
c->sw(a2, 16, a3); // sw a2, 16(a3)
|
||||
c->sw(a1, 20, a3); // sw a1, 20(a3)
|
||||
c->pcpyud(a1, t3, r0); // pcpyud a1, t3, r0
|
||||
c->pminh(t3, t3, a1); // pminh t3, t3, a1
|
||||
c->dsrl32(a1, t3, 0); // dsrl32 a1, t3, 0
|
||||
c->pminh(t3, t3, a1); // pminh t3, t3, a1
|
||||
c->dsrl(t3, t3, 16); // dsrl t3, t3, 16
|
||||
c->lh(a1, 8, a3); // lh a1, 8(a3)
|
||||
c->pminh(t3, t3, a1); // pminh t3, t3, a1
|
||||
c->sh(t3, 8, a3); // sh t3, 8(a3)
|
||||
c->pcpyud(a1, t4, r0); // pcpyud a1, t4, r0
|
||||
c->pmaxh(t4, t4, a1); // pmaxh t4, t4, a1
|
||||
c->dsrl32(a1, t4, 0); // dsrl32 a1, t4, 0
|
||||
c->pmaxh(t4, t4, a1); // pmaxh t4, t4, a1
|
||||
c->dsrl(t4, t4, 16); // dsrl t4, t4, 16
|
||||
c->lh(a1, 10, a3); // lh a1, 10(a3)
|
||||
c->pmaxh(t4, t4, a1); // pmaxh t4, t4, a1
|
||||
c->sh(t4, 10, a3); // sh t4, 10(a3)
|
||||
|
||||
block_28:
|
||||
c->gprs[a1].du64[0] = 0; // or a1, r0, r0
|
||||
c->lwu(a1, 872, a0); // lwu a1, 872(a0)
|
||||
c->mov64(a3, a0); // or a3, a0, r0
|
||||
c->lwu(a0, 876, a0); // lwu a0, 876(a0)
|
||||
c->lui(a2, 4096); // lui a2, 4096
|
||||
// nop // sll r0, r0, 0
|
||||
c->ori(a2, a2, 53248); // ori a2, a2, 53248
|
||||
c->andi(a3, a3, 16383); // andi a3, a3, 16383
|
||||
|
||||
/*
|
||||
block_29:
|
||||
c->lw(t0, 0, a2); // lw t0, 0(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(t0, t0, 256); // andi t0, t0, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t0) != 0; // bne t0, r0, L44
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_29;} // branch non-likely
|
||||
*/
|
||||
|
||||
// c->sw(a3, 128, a2); // sw a3, 128(a2)
|
||||
sadr = c->sgpr64(a3);
|
||||
c->addiu(a3, r0, 256); // addiu a3, r0, 256
|
||||
// c->sw(a1, 16, a2); // sw a1, 16(a2)
|
||||
madr = c->sgpr64(a1);
|
||||
// nop // sll r0, r0, 0
|
||||
// c->sw(a0, 32, a2); // sw a0, 32(a2)
|
||||
qwc = c->sgpr64(a0);
|
||||
// Unknown instr: sync.l
|
||||
// c->sw(a3, 0, a2); // sw a3, 0(a2)
|
||||
spad_from_dma_no_sadr_off(cache.fake_scratchpad_data, madr, sadr, qwc);
|
||||
// Unknown instr: sync.l
|
||||
c->gprs[a0].du64[0] = 0; // or a0, r0, r0
|
||||
c->addiu(a0, r0, 1); // addiu a0, r0, 1
|
||||
c->dsubu(gp, a0, gp); // dsubu gp, a0, gp
|
||||
c->lwu(s5, 12, v1); // lwu s5, 12(v1)
|
||||
c->mov64(v1, s5); // or v1, s5, r0
|
||||
|
||||
block_31:
|
||||
bc = c->sgpr64(s5) != 0; // bne s5, r0, L30
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_6;} // branch non-likely
|
||||
|
||||
c->mov64(v1, s7); // or v1, s7, r0
|
||||
|
||||
block_33:
|
||||
c->gprs[v0].du64[0] = 0; // or v0, r0, r0
|
||||
c->ld(ra, 0, sp); // ld ra, 0(sp)
|
||||
c->lq(gp, 80, sp); // lq gp, 80(sp)
|
||||
c->lq(s5, 64, sp); // lq s5, 64(sp)
|
||||
c->lq(s4, 48, sp); // lq s4, 48(sp)
|
||||
c->lq(s3, 32, sp); // lq s3, 32(sp)
|
||||
c->lq(s2, 16, sp); // lq s2, 16(sp)
|
||||
//jr ra // jr ra
|
||||
c->daddiu(sp, sp, 96); // daddiu sp, sp, 96
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
cache.blerc_globals = intern_from_c("*blerc-globals*").c();
|
||||
cache.gsf_buffer = intern_from_c("*gsf-buffer*").c();
|
||||
cache.stats_blerc = intern_from_c("*stats-blerc*").c();
|
||||
cache.flush_cache = intern_from_c("flush-cache").c();
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
gLinkedFunctionTable.reg("blerc-execute", execute, 256);
|
||||
}
|
||||
|
||||
} // namespace blerc_execute
|
||||
} // namespace Mips2C
|
||||
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
#include "game/kernel/kscheme.h"
|
||||
namespace Mips2C {
|
||||
namespace setup_blerc_chains_for_one_fragment {
|
||||
struct Cache {
|
||||
void* blerc_globals; // *blerc-globals*
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
c->daddiu(sp, sp, -128); // daddiu sp, sp, -128
|
||||
c->sd(ra, 0, sp); // sd ra, 0(sp)
|
||||
c->sq(s0, 16, sp); // sq s0, 16(sp)
|
||||
c->sq(s1, 32, sp); // sq s1, 32(sp)
|
||||
c->sq(s2, 48, sp); // sq s2, 48(sp)
|
||||
c->sq(s3, 64, sp); // sq s3, 64(sp)
|
||||
c->sq(s4, 80, sp); // sq s4, 80(sp)
|
||||
c->sq(s5, 96, sp); // sq s5, 96(sp)
|
||||
c->sq(gp, 112, sp); // sq gp, 112(sp)
|
||||
c->lb(v1, 0, t0); // lb v1, 0(t0)
|
||||
c->addiu(t2, r0, 0); // addiu t2, r0, 0
|
||||
c->mov128_gpr_gpr(t7, r0); // por t7, r0, r0
|
||||
c->load_symbol(t3, cache.blerc_globals); // lw t3, *blerc-globals*(s7)
|
||||
c->lw(t3, 4, t3); // lw t3, 4(t3)
|
||||
c->mov64(t4, v1); // or t4, v1, r0
|
||||
|
||||
block_1:
|
||||
c->lui(t7, 4096); // lui t7, 4096
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(t7, t7, 1); // daddiu t7, t7, 1
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t3) == 0; // beq t3, r0, L11
|
||||
c->sq(t7, 0, a2); // sq t7, 0(a2)
|
||||
if (bc) {goto block_3;} // branch non-likely
|
||||
|
||||
c->sw(a2, 12, t3); // sw a2, 12(t3)
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_3:
|
||||
c->mov64(t3, a2); // or t3, a2, r0
|
||||
c->daddu(t6, t4, t4); // daddu t6, t4, t4
|
||||
c->daddu(t5, v1, v1); // daddu t5, v1, v1
|
||||
c->daddu(t6, t6, t4); // daddu t6, t6, t4
|
||||
c->daddu(t7, t5, v1); // daddu t7, t5, v1
|
||||
c->daddu(t5, t6, t6); // daddu t5, t6, t6
|
||||
c->daddu(t6, t7, t7); // daddu t6, t7, t7
|
||||
c->daddu(t7, t5, t5); // daddu t7, t5, t5
|
||||
c->daddiu(t6, t6, 15); // daddiu t6, t6, 15
|
||||
c->daddiu(t5, t5, 15); // daddiu t5, t5, 15
|
||||
c->andi(t6, t6, 65520); // andi t6, t6, 65520
|
||||
c->dsrl(t5, t5, 4); // dsrl t5, t5, 4
|
||||
c->daddu(t8, t2, t2); // daddu t8, t2, t2
|
||||
c->daddiu(t7, t7, 15); // daddiu t7, t7, 15
|
||||
c->daddu(t9, t8, t2); // daddu t9, t8, t2
|
||||
c->dsrl(t8, t7, 4); // dsrl t8, t7, 4
|
||||
c->daddu(ra, t9, t9); // daddu ra, t9, t9
|
||||
c->addiu(t9, r0, 0); // addiu t9, r0, 0
|
||||
c->daddu(t7, ra, ra); // daddu t7, ra, ra
|
||||
c->daddiu(s3, a2, 32); // daddiu s3, a2, 32
|
||||
c->daddu(s2, ra, a3); // daddu s2, ra, a3
|
||||
c->daddu(ra, t7, t1); // daddu ra, t7, t1
|
||||
c->lui(t7, 12288); // lui t7, 12288
|
||||
c->daddiu(gp, a0, -1); // daddiu gp, a0, -1
|
||||
c->daddu(t7, t7, t5); // daddu t7, t7, t5
|
||||
c->mov64(s5, a1); // or s5, a1, r0
|
||||
c->sq(t7, 0, s3); // sq t7, 0(s3)
|
||||
c->daddiu(s4, t0, 2); // daddiu s4, t0, 2
|
||||
c->sw(s2, 4, s3); // sw s2, 4(s3)
|
||||
c->daddu(s2, s2, t6); // daddu s2, s2, t6
|
||||
c->daddiu(s3, s3, 16); // daddiu s3, s3, 16
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_4:
|
||||
c->lb(s1, 0, s4); // lb s1, 0(s4)
|
||||
c->daddiu(s4, s4, 1); // daddiu s4, s4, 1
|
||||
c->lh(s0, 0, s5); // lh s0, 0(s5)
|
||||
c->daddiu(s5, s5, 2); // daddiu s5, s5, 2
|
||||
bc = c->sgpr64(s1) == 0; // beq s1, r0, L13
|
||||
c->sq(t7, 0, s3); // sq t7, 0(s3)
|
||||
if (bc) {goto block_7;} // branch non-likely
|
||||
|
||||
c->sw(s2, 4, s3); // sw s2, 4(s3)
|
||||
c->daddu(s2, s2, t6); // daddu s2, s2, t6
|
||||
bc = c->sgpr64(s0) == 0; // beq s0, r0, L13
|
||||
c->sw(s0, 12, s3); // sw s0, 12(s3) no
|
||||
if (bc) {goto block_7;} // branch non-likely
|
||||
|
||||
c->daddiu(s3, s3, 16); // daddiu s3, s3, 16
|
||||
c->daddiu(t9, t9, 1); // daddiu t9, t9, 1
|
||||
|
||||
block_7:
|
||||
bc = c->sgpr64(gp) != 0; // bne gp, r0, L12
|
||||
c->daddiu(gp, gp, -1); // daddiu gp, gp, -1
|
||||
if (bc) {goto block_4;} // branch non-likely
|
||||
|
||||
c->sq(t7, 0, s3); // sq t7, 0(s3)
|
||||
c->mov128_gpr_gpr(t6, r0); // por t6, r0, r0
|
||||
c->sw(ra, 4, s3); // sw ra, 4(s3)
|
||||
// c->lui(t6, 28672); // lui t6, 28672
|
||||
get_fake_spad_addr(t6, cache.fake_scratchpad_data, 0, c);
|
||||
c->sb(t8, 0, s3); // sb t8, 0(s3)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sq(t6, 16, s3); // sq t6, 16(s3)
|
||||
c->daddiu(t6, s3, 32); // daddiu t6, s3, 32
|
||||
c->sw(t9, 20, a2); // sw t9, 20(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t4, 16, a2); // sw t4, 16(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(ra, 24, a2); // sw ra, 24(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t8, 28, a2); // sw t8, 28(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t4) != c->sgpr64(v1); // bne t4, v1, L14
|
||||
c->daddiu(t5, t5, 1); // daddiu t5, t5, 1
|
||||
if (bc) {goto block_11;} // branch non-likely
|
||||
|
||||
c->daddiu(t7, t9, 3); // daddiu t7, t9, 3
|
||||
c->multu3(t5, t5, t7); // multu3 t5, t5, t7
|
||||
c->daddiu(t5, t5, -457); // daddiu t5, t5, -457
|
||||
// nop // sll r0, r0, 0
|
||||
bc = ((s64)c->sgpr64(t5)) <= 0; // blez t5, L14
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_11;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L10 // beq r0, r0, L10
|
||||
c->addiu(t4, r0, 24); // addiu t4, r0, 24
|
||||
goto block_1; // branch always
|
||||
|
||||
|
||||
block_11:
|
||||
c->mov64(a2, t6); // or a2, t6, r0
|
||||
c->daddu(t2, t2, t4); // daddu t2, t2, t4
|
||||
bc = c->sgpr64(t2) == c->sgpr64(v1); // beq t2, v1, L15
|
||||
c->daddu(t5, t2, t4); // daddu t5, t2, t4
|
||||
if (bc) {goto block_14;} // branch non-likely
|
||||
|
||||
c->dsubu(t5, t5, v1); // dsubu t5, t5, v1
|
||||
// nop // sll r0, r0, 0
|
||||
bc = ((s64)c->sgpr64(t5)) <= 0; // blez t5, L10
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_1;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L10 // beq r0, r0, L10
|
||||
c->dsubu(t4, v1, t2); // dsubu t4, v1, t2
|
||||
goto block_1; // branch always
|
||||
|
||||
|
||||
block_14:
|
||||
c->load_symbol(v1, cache.blerc_globals); // lw v1, *blerc-globals*(s7)
|
||||
c->sw(t3, 4, v1); // sw t3, 4(v1)
|
||||
c->mov64(v0, a2); // or v0, a2, r0
|
||||
c->ld(ra, 0, sp); // ld ra, 0(sp)
|
||||
c->lq(gp, 112, sp); // lq gp, 112(sp)
|
||||
c->lq(s5, 96, sp); // lq s5, 96(sp)
|
||||
c->lq(s4, 80, sp); // lq s4, 80(sp)
|
||||
c->lq(s3, 64, sp); // lq s3, 64(sp)
|
||||
c->lq(s2, 48, sp); // lq s2, 48(sp)
|
||||
c->lq(s1, 32, sp); // lq s1, 32(sp)
|
||||
c->lq(s0, 16, sp); // lq s0, 16(sp)
|
||||
//jr ra // jr ra
|
||||
c->daddiu(sp, sp, 128); // daddiu sp, sp, 128
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
cache.blerc_globals = intern_from_c("*blerc-globals*").c();
|
||||
gLinkedFunctionTable.reg("setup-blerc-chains-for-one-fragment", execute, 256);
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
}
|
||||
|
||||
} // namespace setup_blerc_chains_for_one_fragment
|
||||
} // namespace Mips2C
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "common/util/BitUtils.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "common/util/assert.h"
|
||||
#include "common/dma/dma.h"
|
||||
|
||||
// This file contains utility functions for code generated by the mips2c pass.
|
||||
// This is only useful for
|
||||
@@ -485,7 +486,7 @@ struct ExecutionContext {
|
||||
}
|
||||
|
||||
void pmulth(int rd, int rs, int rt) {
|
||||
assert(rd == 0);
|
||||
// assert(rd == 0);
|
||||
s32 temp;
|
||||
|
||||
auto s = gpr_src(rs);
|
||||
@@ -493,59 +494,70 @@ struct ExecutionContext {
|
||||
|
||||
temp = (s32)s.ds16[0] * (s32)t.ds16[0];
|
||||
lo.du32[0] = temp;
|
||||
/*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/
|
||||
if (rd)
|
||||
gprs[rd].du32[0] = temp;
|
||||
|
||||
temp = (s32)s.ds16[1] * (s32)t.ds16[1];
|
||||
lo.du32[1] = temp;
|
||||
|
||||
temp = (s32)s.ds16[2] * (s32)t.ds16[2];
|
||||
hi.du32[0] = temp;
|
||||
/*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/
|
||||
if (rd)
|
||||
gprs[rd].du32[1] = temp;
|
||||
|
||||
temp = (s32)s.ds16[3] * (s32)t.ds16[3];
|
||||
hi.du32[1] = temp;
|
||||
|
||||
temp = (s32)s.ds16[4] * (s32)t.ds16[4];
|
||||
lo.du32[2] = temp;
|
||||
/*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/
|
||||
if (rd)
|
||||
gprs[rd].du32[2] = temp;
|
||||
|
||||
temp = (s32)s.ds16[5] * (s32)t.ds16[5];
|
||||
lo.du32[3] = temp;
|
||||
|
||||
temp = (s32)s.ds16[6] * (s32)t.ds16[6];
|
||||
hi.du32[2] = temp;
|
||||
/*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/
|
||||
if (rd)
|
||||
gprs[rd].du32[3] = temp;
|
||||
|
||||
temp = (s32)s.ds16[7] * (s32)t.ds16[7];
|
||||
hi.du32[3] = temp;
|
||||
}
|
||||
|
||||
void pmaddh(int rd, int rs, int rt) {
|
||||
assert(rd == 0);
|
||||
s32 temp;
|
||||
|
||||
auto s = gpr_src(rs);
|
||||
auto t = gpr_src(rt);
|
||||
temp = lo.du32[0] + (s32)s.ds16[0] * (s32)t.ds16[0];
|
||||
lo.du32[0] = temp;
|
||||
if (rd)
|
||||
gprs[rd].du32[0] = temp;
|
||||
|
||||
temp = lo.du32[1] + (s32)s.ds16[1] * (s32)t.ds16[1];
|
||||
lo.du32[1] = temp;
|
||||
|
||||
temp = hi.du32[0] + (s32)s.ds16[2] * (s32)t.ds16[2];
|
||||
hi.du32[0] = temp;
|
||||
if (rd)
|
||||
gprs[rd].du32[1] = temp;
|
||||
|
||||
temp = hi.du32[1] + (s32)s.ds16[3] * (s32)t.ds16[3];
|
||||
hi.du32[1] = temp;
|
||||
|
||||
temp = lo.du32[2] + (s32)s.ds16[4] * (s32)t.ds16[4];
|
||||
lo.du32[2] = temp;
|
||||
if (rd)
|
||||
gprs[rd].du32[2] = temp;
|
||||
|
||||
temp = lo.du32[3] + (s32)s.ds16[5] * (s32)t.ds16[5];
|
||||
lo.du32[3] = temp;
|
||||
|
||||
temp = hi.du32[2] + (s32)s.ds16[6] * (s32)t.ds16[6];
|
||||
hi.du32[2] = temp;
|
||||
if (rd)
|
||||
gprs[rd].du32[3] = temp;
|
||||
|
||||
temp = hi.du32[3] + (s32)s.ds16[7] * (s32)t.ds16[7];
|
||||
hi.du32[3] = temp;
|
||||
@@ -858,6 +870,12 @@ struct ExecutionContext {
|
||||
}
|
||||
|
||||
void mult3(int dst, int src0, int src1) {
|
||||
u32 result = gpr_src(src0).ds32[0] * gpr_src(src1).ds32[0];
|
||||
s32 sresult = result;
|
||||
gprs[dst].ds64[0] = sresult;
|
||||
}
|
||||
|
||||
void multu3(int dst, int src0, int src1) {
|
||||
u32 result = gpr_src(src0).du32[0] * gpr_src(src1).du32[0];
|
||||
s32 sresult = result;
|
||||
gprs[dst].ds64[0] = sresult;
|
||||
@@ -942,6 +960,33 @@ struct ExecutionContext {
|
||||
}
|
||||
}
|
||||
|
||||
void pmaxh(int dst, int src0, int src1) {
|
||||
auto s0 = gpr_src(src0);
|
||||
auto s1 = gpr_src(src1);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
gprs[dst].ds16[i] = std::max(s0.ds16[i], s1.ds16[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void pcpyh(int dst, int src) {
|
||||
auto s0 = gpr_src(src);
|
||||
gprs[dst].du16[0] = s0.du16[0];
|
||||
gprs[dst].du16[1] = s0.du16[0];
|
||||
gprs[dst].du16[2] = s0.du16[0];
|
||||
gprs[dst].du16[3] = s0.du16[0];
|
||||
gprs[dst].du16[4] = s0.du16[4];
|
||||
gprs[dst].du16[5] = s0.du16[4];
|
||||
gprs[dst].du16[6] = s0.du16[4];
|
||||
gprs[dst].du16[7] = s0.du16[4];
|
||||
}
|
||||
|
||||
void psrah(int dest, int src, int sa) {
|
||||
auto s = gpr_src(src);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
gprs[dest].ds16[i] = s.ds16[i] >> (sa & 0xf);
|
||||
}
|
||||
}
|
||||
|
||||
void mov128_vf_gpr(int dst, int src) { vfs[dst] = gpr_src(src); }
|
||||
void mov128_gpr_vf(int dst, int src) { gprs[dst] = vf_src(src); }
|
||||
void mov128_gpr_gpr(int dst, int src) { gprs[dst] = gpr_src(src); }
|
||||
@@ -1026,6 +1071,7 @@ struct ExecutionContext {
|
||||
}
|
||||
|
||||
void movs(int dst, int src) { fprs[dst] = fprs[src]; }
|
||||
void abss(int dst, int src) { fprs[dst] = std::abs(fprs[src]); }
|
||||
|
||||
void cvtws(int dst, int src) {
|
||||
// float to int
|
||||
@@ -1167,4 +1213,11 @@ inline void load_vfs_from_tf_regs(const void* tf_regs_sym, ExecutionContext* c)
|
||||
u8* c_addr_of_vf1 = g_ee_main_mem + goal_addr_of_vf1;
|
||||
memcpy(&c->vfs[1], c_addr_of_vf1, 31 * 16);
|
||||
}
|
||||
|
||||
inline void spad_to_dma_blerc_chain(void* spad_sym_addr, u32 sadr, u32 tadr) {
|
||||
u32 spad_addr_goal;
|
||||
memcpy(&spad_addr_goal, spad_sym_addr, 4);
|
||||
void* spad_addr_c = g_ee_main_mem + spad_addr_goal;
|
||||
emulate_dma(g_ee_main_mem, spad_addr_c, tadr, sadr);
|
||||
}
|
||||
} // namespace Mips2C
|
||||
|
||||
@@ -212,6 +212,18 @@ extern void link();
|
||||
namespace cspace_parented_transformq_joint {
|
||||
extern void link();
|
||||
}
|
||||
namespace draw_bones_merc {
|
||||
extern void link();
|
||||
}
|
||||
namespace draw_bones_check_longest_edge_asm {
|
||||
extern void link();
|
||||
}
|
||||
namespace blerc_execute {
|
||||
extern void link();
|
||||
}
|
||||
namespace setup_blerc_chains_for_one_fragment {
|
||||
extern void link();
|
||||
}
|
||||
LinkedFunctionTable gLinkedFunctionTable;
|
||||
Rng gRng;
|
||||
std::unordered_map<std::string, std::vector<void (*)()>> gMips2CLinkCallbacks = {
|
||||
@@ -245,7 +257,9 @@ std::unordered_map<std::string, std::vector<void (*)()>> gMips2CLinkCallbacks =
|
||||
{method_16_collide_edge_work::link, method_15_collide_edge_work::link,
|
||||
method_10_collide_edge_hold_list::link, method_18_collide_edge_work::link}},
|
||||
{"joint", {calc_animation_from_spr::link, cspace_parented_transformq_joint::link}},
|
||||
{"bones", {bones_mtx_calc::link}}};
|
||||
{"bones",
|
||||
{bones_mtx_calc::link, draw_bones_merc::link, draw_bones_check_longest_edge_asm::link}},
|
||||
{"merc-blend-shape", {blerc_execute::link, setup_blerc_chains_for_one_fragment::link}}};
|
||||
|
||||
void LinkedFunctionTable::reg(const std::string& name, u64 (*exec)(void*), u32 stack_size) {
|
||||
const auto& it = m_executes.insert({name, {exec, Ptr<u8>()}});
|
||||
|
||||
@@ -656,10 +656,16 @@
|
||||
)
|
||||
)
|
||||
|
||||
(define-extern draw-bones (function draw-control dma-buffer float none))
|
||||
;; draw-bones-shadow
|
||||
;; draw-bones-generic-merc
|
||||
;; draw-boes-merc
|
||||
;; draw-bones-check-longest-edge
|
||||
;; draw-bones-check-longest-edgei-asm
|
||||
;; draw-bones
|
||||
;; draw-bones-hud
|
||||
|
||||
;; HACK incomplete:
|
||||
(defun draw-bones ((arg0 draw-control) (arg1 dma-buffer) (arg2 float))
|
||||
(defun draw-bones-hack ((arg0 draw-control) (arg1 dma-buffer) (arg2 float))
|
||||
(local-vars
|
||||
(at-0 object)
|
||||
(a0-16 int)
|
||||
@@ -749,8 +755,430 @@
|
||||
)))
|
||||
(none))
|
||||
|
||||
(def-mips2c draw-bones-merc (function draw-control object object int int pointer))
|
||||
(def-mips2c draw-bones-check-longest-edge-asm (function draw-control float symbol))
|
||||
|
||||
(defun draw-bones ((arg0 draw-control) (dma-buf dma-buffer) (arg2 float))
|
||||
"Main draw function for all bone-related renderers. Will set up merc, generic and shadow.
|
||||
and also add the bones to the calculation list."
|
||||
(local-vars (a0-16 int) (a0-17 int) (a0-62 int) (a2-10 int) (a2-12 int)
|
||||
(used-merc int) (used-mercneric int) (effect-idx int) (sv-144 ripple-control))
|
||||
(rlet ((vf1 :class vf) (vf2 :class vf) (vf3 :class vf) (vf4 :class vf) (vf5 :class vf) (vf6 :class vf)
|
||||
(vf7 :class vf) (vf8 :class vf) (vf9 :class vf) (acc :class vf))
|
||||
|
||||
;; compute the number of bones. I believe this num-joints doesn't count align/prejoint/main, so each needs a bone
|
||||
(let* ((num-bones (+ (-> arg0 mgeo num-joints) 3))
|
||||
;; we'll use 128-bytes/bone.
|
||||
(bone-data-size (* num-bones 128))
|
||||
;; temp work
|
||||
(spr-work (scratchpad-object terrain-context))
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; BONE CALC SETUP
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; next, grab some DMA data.
|
||||
;; we'll also use this for storing bone calculation entries.
|
||||
(let* ((dma-data-start (-> dma-buf base))
|
||||
;; first qw is the tag, stash the bone-calc-entry right after that.
|
||||
(bone-calc-entry (the-as bone-calculation (&+ dma-data-start 16)))
|
||||
;; after that we'll use the space for storing bone matrices.
|
||||
;; we won't calculate them now, but instead we'll tell the *bone-calculation-list* to put them here later.
|
||||
(matrix-data (the-as object (&+ dma-data-start 64)))
|
||||
)
|
||||
|
||||
;; align the matrix data to 64 bytes (we know it is at least 16 byte aligned)
|
||||
(let ((a2-1 (logand (the-as int matrix-data) 48)))
|
||||
(b! (zero? a2-1) cfg-2 :delay (nop!))
|
||||
(set! matrix-data (&- (&+ (the-as pointer matrix-data) 64) (the-as uint a2-1)))
|
||||
)
|
||||
(label cfg-2)
|
||||
|
||||
;; start recording perf stats.
|
||||
;; this just counts the stats for adding the calculation to the linked list.
|
||||
;; which is really fast and not worth profiling.
|
||||
;; I suspect the bone calculation originally was here,
|
||||
;; but they moved it and forgot to move the performance counters too.
|
||||
(reset! (-> *perf-stats* data (perf-stat-bucket bones)))
|
||||
|
||||
;; figure out where everything will be
|
||||
(let ((a2-6 (the-as bone-regs (+ 240 (scratchpad-object int)))))
|
||||
;; the joints are stored in the static art data
|
||||
(set! (-> a2-6 joint-ptr) (the-as (inline-array joint) (-> arg0 jgeo data 0)))
|
||||
;; the final bones output used by the rest of the engine is stored in
|
||||
;; the process-drawable's skeleton
|
||||
(set! (-> a2-6 bone-ptr) (-> arg0 skeleton bones))
|
||||
(set! (-> a2-6 num-bones) (the-as uint num-bones))
|
||||
)
|
||||
|
||||
;; Add the bone calculation to the list, to be done later.
|
||||
;; this will write to both the "matrix data" and the bones array.
|
||||
(let ((t0-2 matrix-data)
|
||||
(t1-0 0)
|
||||
(t4-0 (the-as bone-memory (+ 16 (scratchpad-object int))))
|
||||
(a2-8 *bone-calculation-list*)
|
||||
(a3-8 bone-calc-entry)
|
||||
)
|
||||
(let ((t2-0 (-> t4-0 work regs joint-ptr))
|
||||
(t3-0 (-> t4-0 work regs bone-ptr))
|
||||
(t4-1 (-> t4-0 work regs num-bones))
|
||||
(t5-0 a3-8)
|
||||
)
|
||||
(set! (-> t5-0 flags) (the-as bone-calc-flags t1-0))
|
||||
(set! (-> t5-0 num-bones) t4-1)
|
||||
(set! (-> t5-0 matrix-area) (the-as (inline-array matrix) t0-2))
|
||||
(set! (-> t5-0 joints) t2-0)
|
||||
(set! (-> t5-0 bones) t3-0)
|
||||
(set! (-> t5-0 next) (the-as bone-calculation 0))
|
||||
)
|
||||
(if (nonzero? (-> a2-8 next))
|
||||
(set! (-> a2-8 next next) a3-8)
|
||||
)
|
||||
(if (zero? (-> a2-8 first))
|
||||
(set! (-> a2-8 first) a3-8)
|
||||
)
|
||||
(set! (-> a2-8 next) a3-8)
|
||||
)
|
||||
(&+ bone-calc-entry 48)
|
||||
;; end stat collection
|
||||
(read! (-> *perf-stats* data (perf-stat-bucket bones)))
|
||||
|
||||
;; set up the dma buffer
|
||||
(let ((s2-0 (the-as object (+ (the-as uint matrix-data) bone-data-size))))
|
||||
(let ((a0-2 (shl (the-as int s2-0) 32)))
|
||||
(set! (-> (the-as (pointer uint128) dma-data-start))
|
||||
(logior (-> spr-work work foreground bone-mem work next-tag quad) a0-2)
|
||||
)
|
||||
;; NOTE: does this work correctly for the upper 64 bits??
|
||||
)
|
||||
|
||||
;; only data-format 1 is supported.
|
||||
(when (= (-> arg0 data-format) 1)
|
||||
;; lights should be converted to a single vu-lights already, by the drawing code.
|
||||
;; it stashes lights on the scratchpad. We'll load these here and transform them.
|
||||
;; the result goes in the merc-bucke-info.
|
||||
(let ((v1-6 (the-as vu-lights (+ 64 (scratchpad-object int))))
|
||||
(a0-7 (-> *merc-bucket-info* light))
|
||||
)
|
||||
(let ((a1-8 (-> *math-camera* inv-camera-rot)))
|
||||
(.lvf vf4 (&-> a1-8 vector 0 quad))
|
||||
(.lvf vf5 (&-> a1-8 vector 1 quad))
|
||||
(.lvf vf6 (&-> a1-8 vector 2 quad))
|
||||
)
|
||||
(.lvf vf1 (&-> v1-6 direction 0 quad))
|
||||
(.lvf vf2 (&-> v1-6 direction 1 quad))
|
||||
(.lvf vf3 (&-> v1-6 direction 2 quad))
|
||||
;;(.vcallms 54)
|
||||
;; TODO!
|
||||
|
||||
;mulax.xyzw ACC, vf01, vf04
|
||||
(.mul.x.vf acc vf1 vf4)
|
||||
;madday.xyzw ACC, vf02, vf04
|
||||
(.add.mul.y.vf acc vf2 vf4 acc)
|
||||
;maddz.xyzw vf07, vf03, vf04
|
||||
(.add.mul.z.vf vf7 vf3 vf4 acc)
|
||||
|
||||
;mulax.xyzw ACC, vf01, vf05
|
||||
(.mul.x.vf acc vf1 vf5)
|
||||
;madday.xyzw ACC, vf02, vf05
|
||||
(.add.mul.y.vf acc vf2 vf5 acc)
|
||||
;maddz.xyzw vf08, vf03, vf05
|
||||
(.add.mul.z.vf vf8 vf3 vf5 acc)
|
||||
|
||||
;mulax.xyzw ACC, vf01, vf06
|
||||
(.mul.x.vf acc vf1 vf6)
|
||||
;madday.xyzw ACC, vf02, vf06 :e
|
||||
(.add.mul.y.vf acc vf2 vf6 acc)
|
||||
;maddz.xyzw vf09, vf03, vf06
|
||||
(.add.mul.z.vf vf9 vf3 vf6 acc)
|
||||
|
||||
(let ((a1-9 (-> v1-6 color 0 quad)))
|
||||
(let ((a2-14 (-> v1-6 color 1 quad)))
|
||||
(let ((a3-11 (-> v1-6 color 2 quad)))
|
||||
(let ((v1-7 (-> v1-6 ambient quad)))
|
||||
(set! (-> a0-7 color 0 quad) a1-9)
|
||||
(set! (-> a0-7 color 1 quad) a2-14)
|
||||
(set! (-> a0-7 color 2 quad) a3-11)
|
||||
(set! (-> a0-7 ambient quad) v1-7)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(.svf (&-> a0-7 direction 0 quad) vf7)
|
||||
(.svf (&-> a0-7 direction 1 quad) vf8)
|
||||
(.svf (&-> a0-7 direction 2 quad) vf9)
|
||||
(set! (-> a0-7 direction 1 w) (the-as float 0))
|
||||
)
|
||||
|
||||
;; the drawable system's culling already knows if we need clipping or not,
|
||||
;; we just trust it.
|
||||
(set! (-> *merc-bucket-info* needs-clip)
|
||||
(if (logtest? (-> arg0 status) (draw-status needs-clip))
|
||||
1
|
||||
0
|
||||
)
|
||||
)
|
||||
|
||||
;; Now, we need to decide on merc settings. Default to nothing.
|
||||
(set! used-merc 0)
|
||||
(set! used-mercneric 0)
|
||||
(set! (-> *merc-bucket-info* need-mercprime-if-merc) 0)
|
||||
(set! (-> *merc-bucket-info* must-use-mercneric-for-clip) 0)
|
||||
|
||||
(when (logtest? (-> arg0 status) (draw-status needs-clip))
|
||||
;; we can either clip with "mercprime" (part of merc), or fall back to generic.
|
||||
;; the generic approach always works, but is slower, so we try to use mercprime.
|
||||
;; the user must provide a longest edge length, and we must pass an edge check (fails if close to camera)
|
||||
(cond
|
||||
((nonzero? (-> arg0 longest-edge))
|
||||
;; TODO this makes close up things bad...
|
||||
(if (draw-bones-check-longest-edge-asm arg0 arg2)
|
||||
(set! (-> *merc-bucket-info* need-mercprime-if-merc) 1) ;; clip with mercprime!
|
||||
(set! (-> *merc-bucket-info* must-use-mercneric-for-clip) 1) ;; failed, use generic
|
||||
)
|
||||
)
|
||||
(else
|
||||
(set! (-> *merc-bucket-info* must-use-mercneric-for-clip) 1) ;; no longest edge info, use generic.
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; grab the geometry at the appropriate level of detail.
|
||||
(let ((geom (-> arg0 lod-set lod (-> arg0 cur-lod) geo)))
|
||||
;; loop over effects, and set them up/pick renderers.
|
||||
(set! effect-idx 0)
|
||||
(while (< effect-idx (the-as int (-> geom header effect-count)))
|
||||
|
||||
;; try texture scroll
|
||||
(when (logtest? (-> geom effect effect-idx effect-bits) 1)
|
||||
(let* ((v1-35 (-> geom effect effect-idx extra-info))
|
||||
(v1-36 (the-as mei-texture-scroll (+ (the-as uint v1-35) (* (-> v1-35 texture-scroll-offset) 16))))
|
||||
)
|
||||
(if (< arg2 (-> v1-36 max-dist))
|
||||
;; just add to texscroll list.
|
||||
(texscroll-make-request (-> geom effect effect-idx))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; try ripple
|
||||
(when (logtest? (-> geom effect effect-idx effect-bits) 4)
|
||||
;; TODO.
|
||||
; (when (-> arg0 ripple)
|
||||
; (set! sv-144 (-> arg0 ripple))
|
||||
; (let* ((f1-4 (/ (- (-> sv-144 far-fade-dist) arg2) (- (-> sv-144 far-fade-dist) (-> sv-144 close-fade-dist))))
|
||||
; (f1-6 (fmax 0.0 (fmin 1.0 f1-4)))
|
||||
; (f0-4 f1-6)
|
||||
; (f30-0 (* f1-6 (-> sv-144 global-scale)))
|
||||
; )
|
||||
; (set! (-> sv-144 faded-scale) f30-0)
|
||||
; (let ((f1-9 (/ f30-0 (* 128.0 (-> geom header xyz-scale)))))
|
||||
; 0
|
||||
; (.sll a0-16 num-bones 7)
|
||||
; (let ((v1-56 #x20000000))
|
||||
; (.addu a0-17 a0-16 s2-0)
|
||||
; (s.q! s2-0 v1-56)
|
||||
; )
|
||||
; (let ((v1-57 (+ a0-17 16)))
|
||||
; (s.w! (+ s2-0 4) v1-57)
|
||||
; )
|
||||
; (.addiu matrix-data s2-0 16)
|
||||
; (let ((v1-59 (-> *bone-calculation-list* next)))
|
||||
; (logior! (-> v1-59 flags) (bone-calc-flags bncfl00))
|
||||
; (set! (-> v1-59 ripple-scale) f30-0)
|
||||
; (set! (-> v1-59 ripple-y-scale) f1-9)
|
||||
; (set! (-> v1-59 ripple-normal-scale) (* f0-4 (-> sv-144 individual-normal-scale)))
|
||||
; (set! (-> v1-59 ripple-area) (the-as (inline-array vector) matrix-data))
|
||||
; )
|
||||
; )
|
||||
; (set! (-> dma-buf base) (the-as pointer (-> (the-as (pointer uint32) s2-0) 1)))
|
||||
; (set! s2-0 (-> dma-buf base))
|
||||
; (if (not (and (= f30-0 0.0) (= (-> sv-144 last-frame-scale) 0.0)))
|
||||
; (ripple-make-request (the-as ripple-wave (-> sv-144 waveform)) (-> geom effect effect-idx))
|
||||
; )
|
||||
; (set! (-> sv-144 last-frame-scale) f30-0)
|
||||
; )
|
||||
; )
|
||||
)
|
||||
|
||||
|
||||
(cond
|
||||
((nonzero? (-> arg0 death-timer))
|
||||
;; if using hte death effect, use mercneric always!
|
||||
(set! (-> *merc-bucket-info* effect effect-idx use-mercneric) (the-as uint 1))
|
||||
(set! used-mercneric 1)
|
||||
used-mercneric
|
||||
)
|
||||
((nonzero? (-> geom effect effect-idx envmap-usage))
|
||||
;; if we need envmap, set it up.
|
||||
(let* ((v1-83 (-> geom effect effect-idx extra-info))
|
||||
;; pointer to envmap tint data
|
||||
(v1-84 (the-as structure (+ (the-as uint v1-83) (* (-> v1-83 envmap-tint-offset) 16))))
|
||||
;; the envmap effect fades away at a certain distance
|
||||
(f1-12 (-> (the-as mei-envmap-tint v1-84) fade0))
|
||||
(f0-8 (-> (the-as mei-envmap-tint v1-84) fade1))
|
||||
)
|
||||
;; compute and saturate the envmap effect strength
|
||||
(let ((f0-9 (+ (* f1-12 arg2) f0-8)))
|
||||
(if (< 1.0 f0-9)
|
||||
(set! f0-9 1.0)
|
||||
)
|
||||
(if (< f0-9 0.0)
|
||||
(set! f0-9 0.0)
|
||||
)
|
||||
|
||||
(cond
|
||||
;; do envmap stuff if we are using generic anyway, or our strength is > 0.
|
||||
((or (nonzero? (-> *merc-bucket-info* must-use-mercneric-for-clip)) (< 0.0 f0-9))
|
||||
;; multiply colors by sun tint.
|
||||
(let ((v1-85 (&-> (the-as merc-extra-info v1-84) dummy 4))
|
||||
(a0-36 (the-as object (-> *merc-bucket-info* effect effect-idx)))
|
||||
)
|
||||
(let ((a1-16 (-> *time-of-day-context* current-sun env-color))
|
||||
(f0-10 (* 0.0078125 f0-9))
|
||||
)
|
||||
(dotimes (a2-15 3)
|
||||
(set! (-> (the-as (pointer int8) a0-36) a2-15)
|
||||
(the int (* f0-10 (-> a1-16 data a2-15) (the float (-> v1-85 a2-15))))
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! (-> (the-as (pointer uint8) a0-36) 3) (the-as uint 0))
|
||||
)
|
||||
;; env mapping, so use mercneric.
|
||||
(set! (-> *merc-bucket-info* effect effect-idx use-mercneric) (the-as uint 1))
|
||||
(set! used-mercneric 1)
|
||||
used-mercneric
|
||||
)
|
||||
(else
|
||||
;; no env map, don't use mercneric.
|
||||
(set! (-> *merc-bucket-info* effect effect-idx use-mercneric) (the-as uint 0))
|
||||
(set! (-> *merc-bucket-info* effect effect-idx ignore-alpha) (the-as uint 1))
|
||||
(set! used-merc 1)
|
||||
;; note sure what this is exactly...
|
||||
(when (logtest? (-> geom effect effect-idx effect-bits) 2)
|
||||
(let ((v1-102 (-> *merc-bucket-info* light)))
|
||||
(set! (-> v1-102 direction 1 w) 0.000000000000000000000000000000000000011755039)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
;; final two cases are for all other effects that don't matter generic/normal
|
||||
((nonzero? (-> *merc-bucket-info* must-use-mercneric-for-clip))
|
||||
(set! (-> *merc-bucket-info* effect effect-idx use-mercneric) (the-as uint 1))
|
||||
(set! used-mercneric 1)
|
||||
used-mercneric
|
||||
)
|
||||
(else
|
||||
(set! (-> *merc-bucket-info* effect effect-idx use-mercneric) (the-as uint 0))
|
||||
(set! (-> *merc-bucket-info* effect effect-idx ignore-alpha) (the-as uint 0))
|
||||
(set! used-merc 1)
|
||||
used-merc
|
||||
)
|
||||
)
|
||||
|
||||
;; HACK just use merc.
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask generic))
|
||||
(unless (logtest? (-> arg0 status) (draw-status needs-clip))
|
||||
(set! (-> *merc-bucket-info* effect effect-idx use-mercneric) (the-as uint 0))
|
||||
)
|
||||
(when (and (logtest? (-> arg0 status) (draw-status needs-clip)) ;; we need to clip
|
||||
;;(nonzero? (-> arg0 longest-edge)) ;; we known the longest edge
|
||||
;;(draw-bones-check-longest-edge-asm arg0 arg2) ;; it's ok to use percprime.
|
||||
)
|
||||
(set! (-> *merc-bucket-info* effect effect-idx use-mercneric) (the-as uint 0))
|
||||
(set! (-> *merc-bucket-info* need-mercprime-if-merc) 1)
|
||||
)
|
||||
)
|
||||
(set! effect-idx (+ effect-idx 1))
|
||||
) ;; end effect loop
|
||||
|
||||
;; draw generic!
|
||||
;; note: this doesn't do the fully draw, there's some other stuff in process-drawable.gc to actually execute.
|
||||
;; TODO!!
|
||||
; (when (nonzero? used-mercneric)
|
||||
; (when (logtest? *vu1-enable-user* (vu1-renderer-mask generic))
|
||||
; (set! (-> dma-buf base) (draw-bones-generic-merc arg0 matrix-data s2-0 0))
|
||||
; (set! s2-0 (-> dma-buf base))
|
||||
; )
|
||||
; )
|
||||
|
||||
;; draw shadow!
|
||||
;; TODO
|
||||
; (when (-> arg0 shadow)
|
||||
; (when #t
|
||||
; (set! s2-0 (draw-bones-shadow arg0 matrix-data s2-0))
|
||||
; (set! (-> dma-buf base) (the-as pointer s2-0))
|
||||
; )
|
||||
; )
|
||||
|
||||
;; draw merc!
|
||||
|
||||
(set! used-merc 1)
|
||||
(when (nonzero? used-merc)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask merc))
|
||||
(when (= (-> arg0 cur-lod) (-> arg0 lod-set max-lod))
|
||||
(let ((f0-13 (- (-> arg0 lod-set lod (-> arg0 cur-lod) dist) arg2)))
|
||||
(when (< f0-13 81920.0)
|
||||
(when (zero? (logand (-> geom effect 0 effect-bits) 2))
|
||||
(let* ((a1-25 (the int (* 0.0015625 f0-13)))
|
||||
(v1-147 (min 128 (max 0 a1-25)))
|
||||
(a0-56 (-> *merc-bucket-info* light))
|
||||
)
|
||||
(set! (-> a0-56 direction 1 w) 0.000000000000000000000000000000000000011755084)
|
||||
(set! (-> a0-56 direction 2 w) (the-as float v1-147))
|
||||
)
|
||||
0
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if (nonzero? (-> *merc-bucket-info* need-mercprime-if-merc))
|
||||
(set! (-> dma-buf base) (draw-bones-merc arg0 matrix-data s2-0 32 17))
|
||||
(set! (-> dma-buf base) (draw-bones-merc arg0 matrix-data s2-0 35 20))
|
||||
)
|
||||
(set! s2-0 (-> dma-buf base))
|
||||
)
|
||||
)
|
||||
) ;; end geom processing
|
||||
|
||||
;; advance death timer.
|
||||
(when (nonzero? (-> arg0 death-timer))
|
||||
(when (not (paused?))
|
||||
(+! (-> arg0 death-timer) -1)
|
||||
(if (>= (the-as uint 1) (-> arg0 death-timer))
|
||||
(send-event (-> arg0 process) 'death-end arg0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((v1-164 (logand (the-as int s2-0) 48)))
|
||||
0
|
||||
(b! (zero? v1-164) cfg-83 :delay (set! a0-62 #x20000000))
|
||||
;;(s.q! s2-0 a0-62)
|
||||
(set! (-> (the (pointer uint128) s2-0) 0) (the uint128 a0-62))
|
||||
(let ((a0-63 s2-0))
|
||||
(set! s2-0 (+ (- (the-as int s2-0) v1-164) 64))
|
||||
;;(s.w! (+ a0-63 4) (the-as int s2-0))
|
||||
(set! (-> (the (pointer int32) (+ (the-as uint a0-63) 4))) (the-as int s2-0))
|
||||
)
|
||||
)
|
||||
(label cfg-83)
|
||||
(set! (-> dma-buf base) (the-as pointer (logand (the-as uint s2-0) (the-as uint #xfffffff))))
|
||||
)
|
||||
)
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
)
|
||||
|
||||
(defun draw-bones-hud ((arg0 draw-control) (arg1 dma-buffer))
|
||||
;; hack
|
||||
(none)
|
||||
)
|
||||
(define-extern draw-bones-hud (function draw-control dma-buffer none))
|
||||
|
||||
(define-extern draw-bones-hud (function draw-control dma-buffer none))
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
(defenum draw-status
|
||||
:type uint8
|
||||
:bitfield #t
|
||||
(drwf00 0)
|
||||
(needs-clip 0)
|
||||
(drwf01 1)
|
||||
(drwf02 2)
|
||||
(drwf03 3)
|
||||
|
||||
@@ -222,9 +222,7 @@
|
||||
(tfrag-near-0 7)
|
||||
(tie-near-0 8)
|
||||
(tie-0 9)
|
||||
;; merc0 10
|
||||
;; generic0 11
|
||||
(bucket-10 10)
|
||||
(bucket-10 10) ;; merc
|
||||
(bucket-11 11)
|
||||
|
||||
(tfrag-tex1 12)
|
||||
@@ -234,7 +232,7 @@
|
||||
(tie-1 16)
|
||||
;; merc1 17
|
||||
;; generic1 18
|
||||
(bucket-17 17)
|
||||
(bucket-17 17) ;; merc
|
||||
(bucket-18 18)
|
||||
|
||||
(shrub-tex0 19)
|
||||
@@ -259,31 +257,31 @@
|
||||
(tfrag-ice-near-1 44)
|
||||
|
||||
|
||||
(bucket-45 45)
|
||||
(bucket-45 45) ;; merc
|
||||
(bucket-46 46)
|
||||
|
||||
(pris-tex0 48)
|
||||
(bucket-49 49)
|
||||
(bucket-49 49) ;; merc
|
||||
(bucket-50 50)
|
||||
;; merc0 49
|
||||
;; generic0 50
|
||||
|
||||
(pris-tex1 51)
|
||||
(bucket-52 52)
|
||||
(bucket-52 52) ;; merc
|
||||
(bucket-53 53)
|
||||
;; merc1 52
|
||||
;; generic1 53
|
||||
|
||||
(bucket-55 55)
|
||||
(bucket-55 55) ;; merc
|
||||
(bucket-56 56)
|
||||
(water-tex0 57)
|
||||
(bucket-58 58)
|
||||
(bucket-58 58) ;; merc
|
||||
(bucket-59 59)
|
||||
;; merc0 58 (+ default)
|
||||
;; generic0 59 (+ default)
|
||||
|
||||
(water-tex1 60)
|
||||
(bucket-61 61)
|
||||
(bucket-61 61) ;; merc
|
||||
(bucket-62 62)
|
||||
(bucket-63 63) ; ocean
|
||||
;; merc1 61
|
||||
|
||||
@@ -11,8 +11,35 @@
|
||||
)
|
||||
|
||||
(defun guard-band-cull ((arg0 vector))
|
||||
#t
|
||||
;; todo
|
||||
(local-vars (v1-0 uint128) (v1-1 uint128) (v1-2 uint128))
|
||||
(rlet ((acc :class vf)
|
||||
(vf0 :class vf)
|
||||
(vf10 :class vf)
|
||||
(vf20 :class vf)
|
||||
(vf21 :class vf)
|
||||
(vf22 :class vf)
|
||||
(vf23 :class vf)
|
||||
(vf9 :class vf)
|
||||
)
|
||||
(init-vf0-vector)
|
||||
;; NOTE: manually added
|
||||
(let ((at-0 *math-camera*))
|
||||
(.lvf vf20 (&-> at-0 guard-plane 0 quad))
|
||||
(.lvf vf21 (&-> at-0 guard-plane 1 quad))
|
||||
(.lvf vf22 (&-> at-0 guard-plane 2 quad))
|
||||
(.lvf vf23 (&-> at-0 guard-plane 3 quad))
|
||||
)
|
||||
(.lvf vf10 (&-> arg0 quad))
|
||||
(.mul.x.vf acc vf20 vf10)
|
||||
(.add.mul.y.vf acc vf21 vf10 acc)
|
||||
(.add.mul.z.vf acc vf22 vf10 acc)
|
||||
(.sub.mul.w.vf vf9 vf23 vf0 acc)
|
||||
(.sub.w.vf vf9 vf9 vf10)
|
||||
(.mov v1-0 vf9)
|
||||
(.pcgtw v1-1 0 v1-0)
|
||||
(.ppach v1-2 (the-as uint128 0) v1-1)
|
||||
(nonzero? (the-as int v1-2))
|
||||
)
|
||||
)
|
||||
|
||||
(defun sphere-in-view-frustum? ((arg0 sphere))
|
||||
@@ -714,8 +741,8 @@
|
||||
)
|
||||
)
|
||||
(if (or (guard-band-cull s4-0) (< cam-dist (* 1.2 (-> *math-camera* d))))
|
||||
(logior! (-> arg1 status) (draw-status drwf00))
|
||||
(logclear! (-> arg1 status) (draw-status drwf00))
|
||||
(logior! (-> arg1 status) (draw-status needs-clip))
|
||||
(logclear! (-> arg1 status) (draw-status needs-clip))
|
||||
)
|
||||
(logior! (-> arg1 status) (draw-status drwf03))
|
||||
(if (logtest? (-> arg1 status) (draw-status drwf05))
|
||||
@@ -903,7 +930,7 @@
|
||||
|
||||
;; tfrag
|
||||
;; note: PC port uses preconverted tfrag textures.
|
||||
(#unless PC_PORT
|
||||
; (#unless PC_PORT
|
||||
(when (logtest? *texture-enable-user* 1)
|
||||
(dotimes (gp-1 (-> *level* length))
|
||||
(let ((a1-2 (-> *level* level gp-1)))
|
||||
@@ -913,7 +940,7 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
; )
|
||||
|
||||
;; pris
|
||||
|
||||
|
||||
@@ -361,7 +361,7 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(draw-bone-lines obj)
|
||||
; (draw-bone-lines obj)
|
||||
;; (draw-joint-spheres obj)
|
||||
|
||||
0
|
||||
@@ -949,9 +949,9 @@
|
||||
(logior! (-> obj draw status) (draw-status drwf02))
|
||||
)
|
||||
)
|
||||
; (if (logtest? (-> obj skel status) 72)
|
||||
; (merc-blend-shape obj)
|
||||
; )
|
||||
(if (logtest? (-> obj skel status) 72)
|
||||
(merc-blend-shape obj)
|
||||
)
|
||||
; (if (logtest? (-> obj skel status) 384)
|
||||
; (merc-eye-anim obj)
|
||||
; )
|
||||
|
||||
@@ -583,7 +583,7 @@
|
||||
(display-sync disp)
|
||||
(swap-display disp)
|
||||
(free-all-prim-nodes *touching-list*)
|
||||
;; bler init
|
||||
(blerc-init)
|
||||
;; collide dma
|
||||
(suspend)
|
||||
|
||||
@@ -592,9 +592,9 @@
|
||||
;; start immediately after all process updates finish.
|
||||
|
||||
;; drawing effects to be used in foreground drawing.
|
||||
; (blerc-execute)
|
||||
; (blerc-init)
|
||||
; (texscroll-execute)
|
||||
(blerc-execute)
|
||||
(blerc-init)
|
||||
(texscroll-execute)
|
||||
; (ripple-execute)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -116,10 +116,145 @@
|
||||
;; todo merc-dma-chain-to-spr (unused)
|
||||
|
||||
;; todo blerc-execute
|
||||
(def-mips2c blerc-execute (function none))
|
||||
|
||||
(define-extern setup-blerc-chains (function merc-ctrl (pointer int16) dma-buffer none))
|
||||
|
||||
;; todo merc-blend-shape
|
||||
(defun merc-blend-shape ((a process-drawable))
|
||||
(the object #f)
|
||||
(defun merc-blend-shape ((arg0 process-drawable))
|
||||
(let* ((v1-2 (-> arg0 skel root-channel 0))
|
||||
(a3-0 (-> v1-2 frame-group))
|
||||
)
|
||||
(when (and a3-0
|
||||
(> (-> arg0 skel active-channels) 0)
|
||||
(zero? (-> arg0 draw cur-lod))
|
||||
(logtest? (-> arg0 skel status) 8)
|
||||
)
|
||||
(let ((a1-4 (-> a3-0 blerc-data)))
|
||||
(when a1-4
|
||||
(let* ((a0-10 (-> arg0 draw mgeo))
|
||||
(a2-0 (-> a0-10 header blend-target-count))
|
||||
(t0-0 (-> v1-2 frame-num))
|
||||
(t1-0 (the int t0-0))
|
||||
(v1-4 (&+ a1-4 (* (the-as uint t1-0) a2-0)))
|
||||
(a1-5 (new 'stack-no-clear 'array 'int16 128))
|
||||
)
|
||||
(let ((a2-1 (-> a0-10 header blend-target-count)))
|
||||
(cond
|
||||
((< t1-0 (+ (-> a3-0 data 0 length) -1))
|
||||
(let* ((a3-5 (&+ v1-4 a2-1))
|
||||
(t0-1 (* 64.0 (- t0-0 (the float t1-0))))
|
||||
(t1-1 (- 64.0 t0-1))
|
||||
)
|
||||
(dotimes (t2-0 (the-as int a2-1))
|
||||
(set! (-> a1-5 t2-0)
|
||||
(the int (+ (* (the float (+ (-> v1-4 t2-0) -64)) t1-1) (* (the float (+ (-> a3-5 t2-0) -64)) t0-1)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(else
|
||||
(dotimes (a3-6 (the-as int a2-1))
|
||||
(set! (-> a1-5 a3-6) (the-as int (* (+ (-> v1-4 a3-6) -64) 64)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(setup-blerc-chains a0-10 a1-5 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
)
|
||||
(logior! (-> arg0 skel status) 64)
|
||||
(return (the-as object #f))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? (-> arg0 skel status) 64)
|
||||
(set! (-> arg0 skel status) (logand -65 (-> arg0 skel status)))
|
||||
(setup-blerc-chains
|
||||
(-> arg0 draw lod-set lod 0 geo)
|
||||
(new 'static 'array int16 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
|
||||
(-> *display* frames (-> *display* on-screen) frame global-buf)
|
||||
)
|
||||
)
|
||||
0
|
||||
)
|
||||
|
||||
;; todo setup-blerc-chains
|
||||
;; TODO setup-blerc-chains-for-one-fragment
|
||||
(def-mips2c setup-blerc-chains-for-one-fragment (function object object object object object object object))
|
||||
|
||||
(defun setup-blerc-chains ((arg0 merc-ctrl) (arg1 (pointer int16)) (arg2 dma-buffer))
|
||||
(local-vars
|
||||
(sv-16 uint)
|
||||
(sv-20 pointer)
|
||||
(sv-24 merc-effect)
|
||||
(sv-28 uint)
|
||||
(sv-32 object)
|
||||
(sv-48 int)
|
||||
(sv-64 int)
|
||||
)
|
||||
;; (format 0 "chain setup ctrl ~X array ~X~%" arg0 arg1)
|
||||
(set! sv-16 (-> arg0 header effect-count))
|
||||
(let ((s3-0 (-> arg0 header blend-target-count))
|
||||
(v1-1 (-> arg2 base))
|
||||
)
|
||||
(set! sv-20 (&+ v1-1 0))
|
||||
(let ((a2-1 (the-as object (&+ v1-1 16))))
|
||||
(if (zero? (-> *blerc-globals* first))
|
||||
(set! (-> *blerc-globals* first) (the-as uint a2-1))
|
||||
)
|
||||
(dotimes (s2-0 (the-as int sv-16))
|
||||
; (format 0 "BLERC CHAIN AT ~X~%" a2-1)
|
||||
|
||||
(set! sv-24 (-> arg0 effect s2-0))
|
||||
(set! sv-28 (-> sv-24 blend-frag-count))
|
||||
;; (format 0 " blend frags: ~D~%" sv-28)
|
||||
(when (nonzero? sv-28)
|
||||
(let ((v1-15 (the-as object (-> sv-24 frag-geo)))
|
||||
(s1-0 (the-as structure (-> sv-24 frag-ctrl)))
|
||||
(s0-0 (the-as object (-> sv-24 blend-data)))
|
||||
)
|
||||
(set! sv-32 (-> sv-24 blend-ctrl))
|
||||
(set! sv-48 0)
|
||||
(while (< sv-48 (the-as int sv-28))
|
||||
;; (format 0 " [~D] loc: ~X~%" sv-48 s0-0)
|
||||
|
||||
(set! sv-64 (+ (the-as int v1-15)
|
||||
(logand (* (+ (-> (the-as merc-fragment-control s1-0) unsigned-four-count) 3) 4) #xfff0)
|
||||
)
|
||||
)
|
||||
(if (nonzero? (-> (the-as (pointer uint8) sv-32) 0))
|
||||
(set! a2-1 (setup-blerc-chains-for-one-fragment s3-0 arg1 a2-1 s0-0 sv-32 sv-64))
|
||||
)
|
||||
(let ((a0-14 (logand (+ (* (the-as uint 6) (-> (the-as merc-blend-ctrl sv-32) blend-vtx-count)) 15) #xfff0)))
|
||||
(set! v1-15
|
||||
(+ sv-64
|
||||
(logand (* (+ (-> (the-as merc-fragment-control s1-0) lump-four-count) 3) 4) #xfff0)
|
||||
(* (-> (the-as merc-fragment-control s1-0) fp-qwc) 16)
|
||||
)
|
||||
)
|
||||
(set! s1-0 (&+ s1-0 (* (-> (the-as merc-fragment-control s1-0) mat-xfer-count) 2) 4))
|
||||
(set! s0-0
|
||||
(+ (the-as int s0-0) (* (the-as uint a0-14) (+ (-> (the-as merc-blend-ctrl sv-32) nonzero-index-count) 1)))
|
||||
)
|
||||
)
|
||||
(set! sv-32 (+ (the-as int sv-32) s3-0 2))
|
||||
(the-as int sv-32)
|
||||
(set! sv-48 (+ sv-48 1))
|
||||
;; (format 0 "~%")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! (-> (the-as (pointer int64) sv-20)) (logior #x20000000 (shr (shl (the-as int a2-1) 33) 1)))
|
||||
(let ((v1-33 (the-as (pointer uint32) sv-20)))
|
||||
(set! (-> (&+ v1-33 8)) 0)
|
||||
)
|
||||
(let ((v1-34 (the-as (pointer uint32) sv-20)))
|
||||
(set! (-> (&+ v1-34 12)) 0)
|
||||
)
|
||||
(set! (-> arg2 base) (the-as pointer a2-1))
|
||||
)
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
@@ -499,7 +499,6 @@
|
||||
(&+ v1-20 16)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
@@ -520,7 +519,7 @@
|
||||
)
|
||||
;; set the beginning to be the merc init stuff.
|
||||
(set! (-> dma-buf base)
|
||||
(the-as pointer (merc-vu1-initialize-chain (the-as dma-gif-packet (-> dma-buf base))) )
|
||||
(the-as pointer (merc-vu1-initialize-chain (the-as dma-gif-packet (-> dma-buf base))))
|
||||
)
|
||||
;; some other merc setup for the GS.
|
||||
(let* ((v1-8 dma-buf)
|
||||
|
||||
@@ -1065,6 +1065,13 @@
|
||||
(dma-buffer-add-gs-set dma-buf
|
||||
(texflush 1)
|
||||
)
|
||||
|
||||
(#when PC_PORT
|
||||
(dma-buffer-add-cnt-vif2 dma-buf 1 (new 'static 'vif-tag :cmd (vif-cmd pc-port)) (the-as vif-tag 3))
|
||||
(dma-buffer-add-uint64 dma-buf page)
|
||||
(dma-buffer-add-uint64 dma-buf -1)
|
||||
)
|
||||
|
||||
)
|
||||
(shl total-upload-size 14)
|
||||
)
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
(set! (-> arg0 sky) #f)
|
||||
(set! (-> arg0 target-interp) 0.0)
|
||||
;; TODO re-enable
|
||||
#|
|
||||
|
||||
(when *target*
|
||||
(set! (-> *target* draw light-index) (the-as uint 0))
|
||||
(when (-> *target* sidekick)
|
||||
@@ -295,7 +295,7 @@
|
||||
0
|
||||
)
|
||||
)
|
||||
|#
|
||||
|
||||
|
||||
;; see if either level gives us a sky.
|
||||
(dotimes (v1-12 (-> *level* length))
|
||||
@@ -573,7 +573,7 @@
|
||||
(set! (-> *math-camera* fog-min) (-> arg0 current-fog fog-dists w))
|
||||
|
||||
;; interp target lights.
|
||||
(let* ((v1-195 0 #|(-> *target* draw light-index)|#) ;; TODO
|
||||
(let* ((v1-195 0 (-> *target* draw light-index)) ;; TODO
|
||||
(f30-1 (-> arg0 target-interp))
|
||||
(s4-6 (-> arg0 light-group))
|
||||
(s5-2 (-> arg0 light-group v1-195))
|
||||
|
||||
@@ -2104,8 +2104,6 @@
|
||||
(set! *target* #f)
|
||||
)
|
||||
)
|
||||
;; hack added.
|
||||
(set! *display-target-marks* #t)
|
||||
*target*
|
||||
)
|
||||
|
||||
|
||||
@@ -208,9 +208,9 @@
|
||||
(TODO-RENAME-9 a0-26)
|
||||
)
|
||||
)
|
||||
; (if (logtest? (-> self skel status) 72)
|
||||
; (merc-blend-shape self)
|
||||
; )
|
||||
(if (logtest? (-> self skel status) 72)
|
||||
(merc-blend-shape self)
|
||||
)
|
||||
; (if (logtest? (-> self skel status) 384)
|
||||
; (merc-eye-anim self)
|
||||
; )
|
||||
|
||||
+2
-2
@@ -792,8 +792,8 @@
|
||||
)
|
||||
)
|
||||
(if (or (guard-band-cull s4-0) (< cam-dist (* 1.2 (-> *math-camera* d))))
|
||||
(logior! (-> arg1 status) (draw-status drwf00))
|
||||
(logclear! (-> arg1 status) (draw-status drwf00))
|
||||
(logior! (-> arg1 status) (draw-status needs-clip))
|
||||
(logclear! (-> arg1 status) (draw-status needs-clip))
|
||||
)
|
||||
(logior! (-> arg1 status) (draw-status drwf03))
|
||||
(if (logtest? (-> arg1 status) (draw-status drwf05))
|
||||
|
||||
+1
-1
@@ -1061,7 +1061,7 @@
|
||||
)
|
||||
)
|
||||
(when (and *display-actor-vis* *display-actor-anim*)
|
||||
(let ((s5-3 (entity-by-name (the-as string *display-actor-anim*))))
|
||||
(let ((s5-3 (entity-by-name *display-actor-anim*)))
|
||||
(when s5-3
|
||||
(let ((v0-35 (res-lump-data s5-3 'visvol pointer))
|
||||
(a1-31 (-> s5-3 extra vis-id))
|
||||
|
||||
+2
-2
@@ -193,8 +193,8 @@
|
||||
;; definition for symbol *display-water-marks*, type symbol
|
||||
(define *display-water-marks* #f)
|
||||
|
||||
;; definition for symbol *display-actor-anim*, type symbol
|
||||
(define *display-actor-anim* #f)
|
||||
;; definition for symbol *display-actor-anim*, type string
|
||||
(define *display-actor-anim* (the-as string #f))
|
||||
|
||||
;; definition for symbol *display-process-anim*, type (pointer process)
|
||||
(define *display-process-anim* (the-as (pointer process) #f))
|
||||
|
||||
-2
@@ -385,7 +385,6 @@
|
||||
)
|
||||
|
||||
;; definition for function merc-vu1-initialize-chain
|
||||
;; INFO: Return type mismatch dma-packet vs none.
|
||||
;; Used lq/sq
|
||||
(defun merc-vu1-initialize-chain ((arg0 dma-gif-packet))
|
||||
(let ((gp-0 (the-as object (merc-vu1-add-vu-function (the-as dma-packet arg0) merc-vu1-block 1))))
|
||||
@@ -421,7 +420,6 @@
|
||||
(&+ v1-20 16)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function merc-vu1-init-buffer
|
||||
|
||||
@@ -159,4 +159,18 @@ TEST(VuDisasm, Merc) {
|
||||
VuDisassembler disasm(VuDisassembler::VuKind::VU1);
|
||||
auto prog = disasm.disassemble(data.data(), data.size() * 4, false);
|
||||
EXPECT_EQ(disasm.to_string(prog), get_expected("merc"));
|
||||
}
|
||||
|
||||
TEST(VuDisasm, MercToC) {
|
||||
auto data = get_test_data("merc");
|
||||
VuDisassembler disasm(VuDisassembler::VuKind::VU1);
|
||||
disasm.add_label_with_name(0x1a1, "JUMP_1A1");
|
||||
disasm.add_label_with_name(0x48e, "JUMP_48E");
|
||||
disasm.add_label_with_name(0x539, "JUMP_539");
|
||||
disasm.add_label_with_name(0x243, "JUMP_243");
|
||||
disasm.add_label_with_name(20, "ENTER_20");
|
||||
disasm.add_label_with_name(35, "ENTER_35");
|
||||
auto prog = disasm.disassemble(data.data(), data.size() * 4, false);
|
||||
// fmt::print("{}\n", disasm.to_string_with_cpp(prog));
|
||||
// EXPECT_EQ(disasm.to_string_with_cpp(prog), get_expected("merc"));
|
||||
}
|
||||
Reference in New Issue
Block a user