Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 118 additions & 40 deletions lua/wire/cpulib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -565,52 +565,129 @@ if SERVER then
-- Players and corresponding entities (for the debugger)
CPULib.DebuggerData = {}

------------------------------------------------------------------------------
-- Attach a debugger
function CPULib.AttachDebugger(entity,player)
if entity then
entity.BreakpointInstructions = {}
entity.OnBreakpointInstruction = function(IP)
CPULib.SendDebugData(entity.VM,CPULib.DebuggerData[player:UserID()].MemPointers,player)

----------------------------------------------------------------------
-- Detach debugger
function CPULib.DetachDebugger(player)
if not IsValid(player) then return end

local data = CPULib.DebuggerData[player:UserID()]
if not data then return end

local ent = data.Entity
if IsValid(ent) and ent.VM then
ent.BreakpointInstructions = nil
ent.OnBreakpointInstruction = nil
ent.OnVMStep = nil


if ent.VM.BaseJump then
ent.VM.Jump = ent.VM.BaseJump
ent.VM.BaseJump = nil
end

if ent.VM.BaseInterrupt then
ent.VM.Interrupt = ent.VM.BaseInterrupt
ent.VM.BaseInterrupt = nil
end
entity.OnVMStep = function()
if CurTime() - CPULib.DebuggerData[player:UserID()].PreviousUpdateTime > 0.2 then
CPULib.DebuggerData[player:UserID()].PreviousUpdateTime = CurTime()

-- Send a fake update that messes up line pointer, updates registers
local tempIP = entity.VM.IP
entity.VM.IP = INVALID_BREAKPOINT_IP
CPULib.SendDebugData(entity.VM,nil,player)
entity.VM.IP = tempIP

if ent._CPULibDebuggerHooked then
ent._CPULibDebuggerHooked = nil
if ent._CPULibOriginalOnRemove then
ent.OnRemove = ent._CPULibOriginalOnRemove
ent._CPULibOriginalOnRemove = nil
else
ent.OnRemove = nil
end
end
if not entity.VM.BaseJump then
entity.VM.BaseJump = entity.VM.Jump
entity.VM.Jump = function(VM,IP,CS)
VM:BaseJump(IP,CS)
entity.ForceLastInstruction = true
end

CPULib.DebuggerData[player:UserID()] = nil
end


----------------------------------------------------------------------
-- Attach a debugger
function CPULib.AttachDebugger(entity, player)
if not IsValid(player) then return end

-- DETACH PATH
if not entity then
CPULib.DetachDebugger(player)
return
end

if not IsValid(entity) or not entity.VM then return end


--// detach any existing debugger first
CPULib.DetachDebugger(player)


if not entity._CPULibDebuggerHooked then
entity._CPULibDebuggerHooked = true

entity._CPULibOriginalOnRemove = entity.OnRemove

entity.OnRemove = function(ent)
if entity._CPULibOriginalOnRemove then
entity._CPULibOriginalOnRemove(ent)
end
entity.VM.BaseInterrupt = entity.VM.Interrupt
entity.VM.Interrupt = function(VM,interruptNo,interruptParameter,isExternal,cascadeInterrupt)
VM:BaseInterrupt(interruptNo,interruptParameter,isExternal,cascadeInterrupt)
if interruptNo < 27 then
CPULib.DebugLogInterrupt(player,interruptNo,interruptParameter,isExternal,cascadeInterrupt)
CPULib.SendDebugData(entity.VM,CPULib.DebuggerData[player:UserID()].MemPointers,player)
end

if IsValid(player) then
if not CPULib.DebuggerData[player:UserID()] then return end

CPULib.DetachDebugger(player)

net.Start("CPULib.InvalidateDebugger")
net.WriteUInt(1, 2) --// 1 = detach
net.Send(player)
end
end
else
if CPULib.DebuggerData[player:UserID()] then
if CPULib.DebuggerData[player:UserID()].Entity and
CPULib.DebuggerData[player:UserID()].Entity.VM and
CPULib.DebuggerData[player:UserID()].Entity.VM.BaseInterrupt then

CPULib.DebuggerData[player:UserID()].Entity.BreakpointInstructions = nil
if CPULib.DebuggerData[player:UserID()].Entity.VM.BaseJump then
CPULib.DebuggerData[player:UserID()].Entity.VM.Jump = CPULib.DebuggerData[player:UserID()].Entity.VM.BaseJump
CPULib.DebuggerData[player:UserID()].Entity.VM.Interrupt = CPULib.DebuggerData[player:UserID()].Entity.VM.BaseInterrupt
CPULib.DebuggerData[player:UserID()].Entity.VM.BaseJump = nil
CPULib.DebuggerData[player:UserID()].Entity.VM.BaseInterrupt = nil
end

entity.BreakpointInstructions = {}

entity.OnBreakpointInstruction = function(IP)
local data = CPULib.DebuggerData[player:UserID()]
if not data then return end

CPULib.SendDebugData(entity.VM, data.MemPointers, player)
end

entity.OnVMStep = function()
local data = CPULib.DebuggerData[player:UserID()]
if not data then return end

if CurTime() - data.PreviousUpdateTime > 0.2 then
data.PreviousUpdateTime = CurTime()

-- Send a fake update that messes up line pointer, updates registers
local tempIP = entity.VM.IP
entity.VM.IP = INVALID_BREAKPOINT_IP
CPULib.SendDebugData(entity.VM, nil, player)
entity.VM.IP = tempIP
end
end

if not entity.VM.BaseJump then
entity.VM.BaseJump = entity.VM.Jump
entity.VM.Jump = function(VM, IP, CS)
VM:BaseJump(IP, CS)
entity.ForceLastInstruction = true
end

entity.VM.BaseInterrupt = entity.VM.Interrupt
entity.VM.Interrupt = function(VM, interruptNo, interruptParameter, isExternal, cascadeInterrupt)
VM:BaseInterrupt(interruptNo, interruptParameter, isExternal, cascadeInterrupt)

if interruptNo < 27 then
CPULib.DebugLogInterrupt(player, interruptNo, interruptParameter, isExternal, cascadeInterrupt)

local data = CPULib.DebuggerData[player:UserID()]
if data then
CPULib.SendDebugData(entity.VM, data.MemPointers, player)
end
end
end
Expand All @@ -624,6 +701,7 @@ if SERVER then
}
end


-- Log debug interrupt
function CPULib.DebugLogInterrupt(player,interruptNo,interruptParameter,isExternal,cascadeInterrupt)
local umsgrp = RecipientFilter()
Expand Down
Loading