project64/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp

210 lines
5.6 KiB
C++

/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include <stdafx.h>
#include "ScriptSystem.h"
#include "Debugger-Scripts.h"
#include "ScriptInstance.h"
#include "ScriptHook.h"
CScriptSystem::CScriptSystem(CDebuggerUI* debugger)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
m_NextCallbackId = 0;
m_Debugger = debugger;
InitializeCriticalSection(&m_CriticalSection);
m_HookCPUExec = new CScriptHook(this);
m_HookCPUExecOpcode = new CScriptHook(this);
m_HookCPURead = new CScriptHook(this);
m_HookCPUWrite = new CScriptHook(this);
m_HookCPUGPRValue = new CScriptHook(this);
m_HookFrameDrawn = new CScriptHook(this);
RegisterHook("exec", m_HookCPUExec);
RegisterHook("read", m_HookCPURead);
RegisterHook("write", m_HookCPUWrite);
RegisterHook("opcode", m_HookCPUExecOpcode);
RegisterHook("gprvalue", m_HookCPUGPRValue);
RegisterHook("draw", m_HookFrameDrawn);
HMODULE hInst = GetModuleHandle(NULL);
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(IDR_JSAPI_TEXT), "TEXT");
HGLOBAL hGlob = LoadResource(hInst, hRes);
DWORD resSize = SizeofResource(hInst, hRes);
m_APIScript = (char*)malloc(resSize + 1);
void* resData = LockResource(hGlob);
memcpy(m_APIScript, resData, resSize);
m_APIScript[resSize] = '\0';
FreeResource(hGlob);
}
CScriptSystem::~CScriptSystem()
{
for (size_t i = 0; i < m_Hooks.size(); i++)
{
delete m_Hooks[i].cbList;
}
UnregisterHooks();
free(m_APIScript);
DeleteCriticalSection(&m_CriticalSection);
}
const char* CScriptSystem::APIScript()
{
return m_APIScript;
}
void CScriptSystem::RunScript(char* path)
{
CScriptInstance* scriptInstance = new CScriptInstance(m_Debugger);
char* pathSaved = (char*)malloc(strlen(path)+1); // freed via DeleteStoppedInstances
strcpy(pathSaved, path);
EnterCriticalSection(&m_CriticalSection);
m_RunningInstances.push_back({ pathSaved, scriptInstance });
LeaveCriticalSection(&m_CriticalSection);
scriptInstance->Start(pathSaved);
}
void CScriptSystem::StopScript(char* path)
{
CScriptInstance* scriptInstance = GetInstance(path);
if (scriptInstance == NULL)
{
return;
}
scriptInstance->ForceStop();
DeleteStoppedInstances();
}
void CScriptSystem::DeleteStoppedInstances()
{
EnterCriticalSection(&m_CriticalSection);
int lastIndex = m_RunningInstances.size() - 1;
for (int i = lastIndex; i >= 0; i--)
{
if (m_RunningInstances[i].scriptInstance->GetState() == STATE_STOPPED)
{
free(m_RunningInstances[i].path);
CScriptInstance* instance = m_RunningInstances[i].scriptInstance;
delete instance;
m_RunningInstances.erase(m_RunningInstances.begin() + i);
}
}
LeaveCriticalSection(&m_CriticalSection);
}
INSTANCE_STATE CScriptSystem::GetInstanceState(char* path)
{
EnterCriticalSection(&m_CriticalSection);
for (size_t i = 0; i < m_RunningInstances.size(); i++)
{
if (strcmp(m_RunningInstances[i].path, path) == 0)
{
INSTANCE_STATE ret = m_RunningInstances[i].scriptInstance->GetState();
LeaveCriticalSection(&m_CriticalSection);
return ret;
}
}
LeaveCriticalSection(&m_CriticalSection);
return STATE_INVALID;
}
CScriptInstance* CScriptSystem::GetInstance(char* path)
{
EnterCriticalSection(&m_CriticalSection);
for (size_t i = 0; i < m_RunningInstances.size(); i++)
{
if (strcmp(m_RunningInstances[i].path, path) == 0)
{
CScriptInstance *ret = m_RunningInstances[i].scriptInstance;
LeaveCriticalSection(&m_CriticalSection);
return ret;
}
}
LeaveCriticalSection(&m_CriticalSection);
return NULL;
}
bool CScriptSystem::HasCallbacksForInstance(CScriptInstance* scriptInstance)
{
for (size_t i = 0; i < m_Hooks.size(); i++)
{
if (m_Hooks[i].cbList->HasContext(scriptInstance))
{
return true;
}
}
return false;
}
void CScriptSystem::ClearCallbacksForInstance(CScriptInstance* scriptInstance)
{
for (size_t i = 0; i < m_Hooks.size(); i++)
{
m_Hooks[i].cbList->RemoveByInstance(scriptInstance);
}
}
void CScriptSystem::RemoveCallbackById(int callbackId)
{
for (size_t i = 0; i < m_Hooks.size(); i++)
{
m_Hooks[i].cbList->RemoveById(callbackId);
}
}
void CScriptSystem::RegisterHook(const char* hookId, CScriptHook* cbList)
{
HOOKENTRY hook = { hookId, cbList };
m_Hooks.push_back(hook);
}
void CScriptSystem::UnregisterHooks()
{
m_Hooks.clear();
}
CScriptHook* CScriptSystem::GetHook(const char* hookId)
{
size_t size = m_Hooks.size();
for (size_t i = 0; i < size; i++)
{
if (strcmp(m_Hooks[i].hookId, hookId) == 0)
{
return m_Hooks[i].cbList;
}
}
return NULL;
}
int CScriptSystem::GetNextCallbackId()
{
return m_NextCallbackId++;
}