Files
jak-project/game/system/vm/vm.cpp
T
Tyler Wilding 9c631e11fe offline-test: Partition by DGO and colorize/condense output (#2045)
This solves two main problems:
- the looming threat of running out of memory since every thread would
consume duplicate (and probably not needed) resources
- though I will point out, jak 2's offline tests seem to hardly use any
memory even with 400+ files, duplicated across many threads. Where as
jak 1 does indeed use tons more memory. So I think there is something
going on besides just the source files
- condense the output so it's much easier to see what is happening / how
close the test is to completing.
- one annoying thing about the multiple thread change was errors were
typically buried far in the middle of the output, this fixes that
- refactors the offline test code in general to be a lot more modular

The pretty printing is not enabled by default, run with `-p` or
`--pretty-print` if you want to use it


https://user-images.githubusercontent.com/13153231/205513212-a65c20d4-ce36-44f6-826a-cd475505dbf9.mp4
2022-12-22 13:41:33 -05:00

141 lines
3.3 KiB
C++

/*!
* @file vm.cpp
* Base "PS2 virtual machine" code.
* Simulates the existence of select PS2 components, for inspection & debugging.
* Not an emulator!
*/
#include "vm.h"
#include <condition_variable>
#include <mutex>
#include "dmac.h"
#include "common/log/log.h"
namespace VM {
bool use = true; // enable VM by default, since we're debugging right now
namespace {
Status status;
std::condition_variable vm_init_cv;
std::condition_variable vm_dead_cv;
std::mutex status_mutex;
int components = 0;
} // namespace
static void vm_change_status(Status new_status) {
std::unique_lock<std::mutex> lk(status_mutex);
status = new_status;
}
void wait_vm_init() {
std::unique_lock<std::mutex> lk(status_mutex);
vm_init_cv.wait(lk, [&] { return status == Status::Inited; });
}
void wait_vm_dead() {
if (status != Status::Kill && status != Status::Dead) {
lg::warn("[VM] Dying without being killed! There are {} component(s) running", components);
}
std::unique_lock<std::mutex> lk(status_mutex);
vm_dead_cv.wait(lk, [&] { return components == 0; });
}
bool vm_want_exit() {
return status == Status::Kill || status == Status::Dead;
}
void vm_prepare() {
lg::debug("[VM] Preparing...");
vm_change_status(Status::Uninited);
lg::debug("[VM] Prepared");
}
void vm_init() {
if (status != Status::Uninited) {
lg::warn("[VM] unexpected status {}", fmt::underlying(status));
}
lg::debug("[VM] Inited");
vm_change_status(Status::Inited);
vm_init_cv.notify_all();
}
void vm_kill() {
lg::debug("[VM] Killing");
vm_change_status(Status::Kill);
// stall caller until VM is done dying
wait_vm_dead();
vm_change_status(Status::Dead);
}
void subscribe_component() {
if (status == Status::Dead) {
throw std::runtime_error("[VM] Cannot add new components when VM is dead!");
}
status_mutex.lock();
++components;
status_mutex.unlock();
// stall component until VM is ready
if (status == Status::Uninited) {
wait_vm_init();
}
}
void unsubscribe_component() {
status_mutex.lock();
--components;
status_mutex.unlock();
vm_dead_cv.notify_all();
}
/*!
* Return the GOAL pointer to a specified PS2 VM component based on the EE address.
*/
u64 get_vm_ptr(u32 ptr) {
// currently, only DMAC and DMA channel banks are implemented. add more as necessary.
if (ptr == 0x10008000) {
return VM::dmac_ch[0].offset;
} else if (ptr == 0x10009000) {
return VM::dmac_ch[1].offset;
} else if (ptr == 0x1000a000) {
return VM::dmac_ch[2].offset;
} else if (ptr == 0x1000b000) {
return VM::dmac_ch[3].offset;
} else if (ptr == 0x1000b400) {
return VM::dmac_ch[4].offset;
} else if (ptr == 0x1000c000) {
return VM::dmac_ch[5].offset;
} else if (ptr == 0x1000c400) {
return VM::dmac_ch[6].offset;
} else if (ptr == 0x1000c800) {
return VM::dmac_ch[7].offset;
} else if (ptr == 0x1000d000) {
return VM::dmac_ch[8].offset;
} else if (ptr == 0x1000d400) {
return VM::dmac_ch[9].offset;
} else if (ptr == 0x1000e000) {
return VM::dmac.offset;
} else {
// return zero, using this result will segfault GOAL!
// we could die immediately, but it might be worth it to keep going just on the off chance more
// errors are reported, and not just only this one.
lg::error("unknown EE register for VM at #x{:08x}", ptr);
return 0;
}
}
} // namespace VM