2013-07-06 01:49:38 +02:00
|
|
|
#pragma once
|
2014-07-11 13:59:13 +02:00
|
|
|
#include "Emu/SysCalls/SC_FUNC.h"
|
2014-08-25 16:56:13 +02:00
|
|
|
#include "Emu/IdManager.h"
|
2014-08-23 16:51:51 +02:00
|
|
|
#include "ErrorCodes.h"
|
2014-07-21 17:58:03 +02:00
|
|
|
#include "LogBase.h"
|
2013-07-06 01:49:38 +02:00
|
|
|
|
|
|
|
|
//TODO
|
|
|
|
|
struct ModuleFunc
|
|
|
|
|
{
|
|
|
|
|
u32 id;
|
|
|
|
|
func_caller* func;
|
2014-11-29 14:16:53 +01:00
|
|
|
vm::ptr<void(*)()> lle_func;
|
2013-07-06 01:49:38 +02:00
|
|
|
|
2014-11-29 14:16:53 +01:00
|
|
|
ModuleFunc(u32 id, func_caller* func, vm::ptr<void(*)()> lle_func = vm::ptr<void(*)()>::make(0))
|
2013-07-06 01:49:38 +02:00
|
|
|
: id(id)
|
|
|
|
|
, func(func)
|
2014-11-29 14:16:53 +01:00
|
|
|
, lle_func(lle_func)
|
2013-07-06 01:49:38 +02:00
|
|
|
{
|
|
|
|
|
}
|
2014-04-15 16:12:15 +02:00
|
|
|
|
|
|
|
|
~ModuleFunc()
|
|
|
|
|
{
|
2014-08-23 16:51:51 +02:00
|
|
|
delete func;
|
2014-04-15 16:12:15 +02:00
|
|
|
}
|
2013-07-06 01:49:38 +02:00
|
|
|
};
|
|
|
|
|
|
2014-03-06 12:40:50 +01:00
|
|
|
struct SFuncOp
|
|
|
|
|
{
|
|
|
|
|
u32 crc;
|
|
|
|
|
u32 mask;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct SFunc
|
|
|
|
|
{
|
|
|
|
|
func_caller* func;
|
2014-03-31 12:04:34 +02:00
|
|
|
void* ptr;
|
2014-04-28 05:41:51 +02:00
|
|
|
const char* name;
|
2014-04-10 00:54:32 +02:00
|
|
|
std::vector<SFuncOp> ops;
|
2014-03-31 12:04:34 +02:00
|
|
|
u64 group;
|
|
|
|
|
u32 found;
|
2014-04-15 16:12:15 +02:00
|
|
|
|
|
|
|
|
~SFunc()
|
|
|
|
|
{
|
2014-08-23 16:51:51 +02:00
|
|
|
delete func;
|
2014-04-15 16:12:15 +02:00
|
|
|
}
|
2014-03-06 12:40:50 +01:00
|
|
|
};
|
|
|
|
|
|
2014-08-23 16:51:51 +02:00
|
|
|
class StaticFuncManager;
|
|
|
|
|
|
2014-07-21 17:58:03 +02:00
|
|
|
class Module : public LogBase
|
2013-07-06 01:49:38 +02:00
|
|
|
{
|
2014-02-02 21:47:17 +01:00
|
|
|
std::string m_name;
|
2014-05-02 08:30:32 +02:00
|
|
|
u16 m_id;
|
2013-07-06 01:49:38 +02:00
|
|
|
bool m_is_loaded;
|
2013-11-16 22:12:30 +01:00
|
|
|
void (*m_load_func)();
|
|
|
|
|
void (*m_unload_func)();
|
2013-07-06 01:49:38 +02:00
|
|
|
|
2014-08-22 18:54:53 +02:00
|
|
|
IdManager& GetIdManager() const;
|
2014-08-23 16:51:51 +02:00
|
|
|
void PushNewFuncSub(SFunc* func);
|
2014-08-22 18:54:53 +02:00
|
|
|
|
2013-07-06 01:49:38 +02:00
|
|
|
public:
|
2014-11-29 14:16:53 +01:00
|
|
|
std::unordered_map<u32, ModuleFunc*> m_funcs_list;
|
2013-07-06 01:49:38 +02:00
|
|
|
|
2014-09-13 22:00:17 +02:00
|
|
|
Module(u16 id, const char* name, void(*load)() = nullptr, void(*unload)() = nullptr);
|
2013-07-06 01:49:38 +02:00
|
|
|
|
2014-05-02 08:30:32 +02:00
|
|
|
Module(Module &other) = delete;
|
|
|
|
|
Module(Module &&other);
|
|
|
|
|
|
|
|
|
|
Module &operator =(Module &other) = delete;
|
|
|
|
|
Module &operator =(Module &&other);
|
2014-11-29 14:16:53 +01:00
|
|
|
|
|
|
|
|
ModuleFunc* GetFunc(u32 id)
|
|
|
|
|
{
|
|
|
|
|
auto res = m_funcs_list.find(id);
|
|
|
|
|
|
|
|
|
|
if (res == m_funcs_list.end())
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
return res->second;
|
|
|
|
|
}
|
2014-05-02 08:30:32 +02:00
|
|
|
|
2014-04-15 16:12:15 +02:00
|
|
|
~Module();
|
|
|
|
|
|
2013-07-06 01:49:38 +02:00
|
|
|
void Load();
|
|
|
|
|
void UnLoad();
|
|
|
|
|
bool Load(u32 id);
|
|
|
|
|
bool UnLoad(u32 id);
|
|
|
|
|
|
|
|
|
|
void SetLoaded(bool loaded = true);
|
|
|
|
|
bool IsLoaded() const;
|
|
|
|
|
|
|
|
|
|
u16 GetID() const;
|
2014-07-21 17:58:03 +02:00
|
|
|
virtual const std::string& GetName() const override;
|
2014-02-02 21:47:17 +01:00
|
|
|
void SetName(const std::string& name);
|
2013-07-06 01:49:38 +02:00
|
|
|
|
|
|
|
|
public:
|
2014-01-19 04:14:11 +01:00
|
|
|
bool CheckID(u32 id) const;
|
2014-12-24 00:38:13 +01:00
|
|
|
|
|
|
|
|
template<typename T> bool CheckId(u32 id, std::shared_ptr<T>& data)
|
2014-01-19 04:14:11 +01:00
|
|
|
{
|
|
|
|
|
ID* id_data;
|
|
|
|
|
|
|
|
|
|
if(!CheckID(id, id_data)) return false;
|
2013-07-06 01:49:38 +02:00
|
|
|
|
2014-10-01 11:45:43 +02:00
|
|
|
data = id_data->GetData()->get<T>();
|
2013-07-06 01:49:38 +02:00
|
|
|
|
2014-01-19 04:14:11 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
2014-02-22 03:53:06 +01:00
|
|
|
|
2014-12-24 00:38:13 +01:00
|
|
|
template<typename T> bool CheckId(u32 id, std::shared_ptr<T>& data, IDType& type)
|
2014-02-22 03:53:06 +01:00
|
|
|
{
|
|
|
|
|
ID* id_data;
|
|
|
|
|
|
|
|
|
|
if(!CheckID(id, id_data)) return false;
|
|
|
|
|
|
2014-10-01 11:45:43 +02:00
|
|
|
data = id_data->GetData()->get<T>();
|
|
|
|
|
type = id_data->GetType();
|
2014-02-22 03:53:06 +01:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-12-24 00:38:13 +01:00
|
|
|
|
2014-01-19 04:14:11 +01:00
|
|
|
bool CheckID(u32 id, ID*& _id) const;
|
2013-07-06 01:49:38 +02:00
|
|
|
|
2014-01-19 04:14:11 +01:00
|
|
|
template<typename T>
|
2014-12-24 00:38:13 +01:00
|
|
|
u32 GetNewId(std::shared_ptr<T>& data, IDType type = TYPE_OTHER)
|
2014-01-19 04:14:11 +01:00
|
|
|
{
|
2014-08-22 18:54:53 +02:00
|
|
|
return GetIdManager().GetNewID<T>(GetName(), data, type);
|
2014-01-19 04:14:11 +01:00
|
|
|
}
|
2013-08-03 11:40:03 +02:00
|
|
|
|
2014-08-23 22:40:04 +02:00
|
|
|
bool RemoveId(u32 id);
|
2014-11-29 14:16:53 +01:00
|
|
|
|
|
|
|
|
void RegisterLLEFunc(u32 id, vm::ptr<void(*)()> func)
|
|
|
|
|
{
|
|
|
|
|
if (auto f = GetFunc(id))
|
|
|
|
|
{
|
|
|
|
|
f->lle_func = func;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_funcs_list[id] = new ModuleFunc(id, nullptr, func);
|
|
|
|
|
}
|
2014-08-23 22:40:04 +02:00
|
|
|
|
2013-11-19 11:30:58 +01:00
|
|
|
template<typename T> __forceinline void AddFunc(u32 id, T func);
|
2014-11-29 14:16:53 +01:00
|
|
|
template<typename T> __forceinline void AddFunc(const char* name, T func);
|
2014-04-28 05:41:51 +02:00
|
|
|
template<typename T> __forceinline void AddFuncSub(const char group[8], const u64 ops[], const char* name, T func);
|
2013-07-06 01:49:38 +02:00
|
|
|
};
|
|
|
|
|
|
2014-08-19 20:17:20 +02:00
|
|
|
u32 getFunctionId(const char* name);
|
2014-07-06 01:30:28 +02:00
|
|
|
|
2013-11-24 01:01:57 +01:00
|
|
|
template<typename T>
|
|
|
|
|
__forceinline void Module::AddFunc(u32 id, T func)
|
|
|
|
|
{
|
2014-11-29 14:16:53 +01:00
|
|
|
m_funcs_list[id] = new ModuleFunc(id, bind_func(func));
|
2013-11-24 01:01:57 +01:00
|
|
|
}
|
|
|
|
|
|
2014-07-06 01:30:28 +02:00
|
|
|
template<typename T>
|
2014-08-19 20:17:20 +02:00
|
|
|
__forceinline void Module::AddFunc(const char* name, T func)
|
2014-07-06 01:30:28 +02:00
|
|
|
{
|
|
|
|
|
AddFunc(getFunctionId(name), func);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-06 12:40:50 +01:00
|
|
|
template<typename T>
|
2014-04-28 05:41:51 +02:00
|
|
|
__forceinline void Module::AddFuncSub(const char group[8], const u64 ops[], const char* name, T func)
|
2014-03-06 12:40:50 +01:00
|
|
|
{
|
|
|
|
|
if (!ops[0]) return;
|
|
|
|
|
|
|
|
|
|
SFunc* sf = new SFunc;
|
2014-04-10 00:54:32 +02:00
|
|
|
sf->ptr = (void *)func;
|
2014-03-06 12:40:50 +01:00
|
|
|
sf->func = bind_func(func);
|
|
|
|
|
sf->name = name;
|
2014-03-31 12:04:34 +02:00
|
|
|
sf->group = *(u64*)group;
|
|
|
|
|
sf->found = 0;
|
2014-03-06 12:40:50 +01:00
|
|
|
|
|
|
|
|
// TODO: check for self-inclusions, use CRC
|
|
|
|
|
for (u32 i = 0; ops[i]; i++)
|
|
|
|
|
{
|
|
|
|
|
SFuncOp op;
|
|
|
|
|
op.mask = ops[i] >> 32;
|
2014-08-30 22:41:01 +02:00
|
|
|
op.crc = (u32)ops[i];
|
2014-03-31 12:04:34 +02:00
|
|
|
if (op.mask) op.crc &= op.mask;
|
2014-09-04 11:21:23 +02:00
|
|
|
op.mask = re32(op.mask);
|
|
|
|
|
op.crc = re32(op.crc);
|
2014-04-10 00:54:32 +02:00
|
|
|
sf->ops.push_back(op);
|
2014-03-06 12:40:50 +01:00
|
|
|
}
|
2014-08-23 16:51:51 +02:00
|
|
|
PushNewFuncSub(sf);
|
2014-03-06 12:40:50 +01:00
|
|
|
}
|
2014-08-23 16:51:51 +02:00
|
|
|
|
2014-08-27 00:44:32 +02:00
|
|
|
void fix_import(Module* module, u32 func, u32 addr);
|
|
|
|
|
|
|
|
|
|
#define FIX_IMPORT(module, func, addr) fix_import(module, getFunctionId(#func), addr)
|
|
|
|
|
|
2014-08-27 15:11:34 +02:00
|
|
|
void fix_relocs(Module* module, u32 lib, u32 start, u32 end, u32 seg2);
|
|
|
|
|
|
2014-08-23 16:51:51 +02:00
|
|
|
#define REG_SUB(module, group, name, ...) \
|
|
|
|
|
static const u64 name ## _table[] = {__VA_ARGS__ , 0}; \
|
|
|
|
|
module->AddFuncSub(group, name ## _table, #name, name)
|
|
|
|
|
|
|
|
|
|
#define REG_FUNC(module, name) module->AddFunc(getFunctionId(#name), name)
|
|
|
|
|
|
|
|
|
|
#define UNIMPLEMENTED_FUNC(module) module->Todo("%s", __FUNCTION__)
|