TOOL.Category = "Wire - Control" TOOL.Name = "Chip - CPU" TOOL.Command = nil TOOL.ConfigName = "" TOOL.Tab = "Wire" if CLIENT then language.Add("Tool_wire_cpu_name", "CPU Tool (Wire)") language.Add("Tool_wire_cpu_desc", "Spawns a central processing unit") language.Add("Tool_wire_cpu_0", "Primary: upload program to hispeed device, Reload: attach debugger, Shift+Reload: clear, Secondary: open editor") language.Add("sboxlimit_wire_cpu", "You've hit ZCPU limit!") language.Add("undone_wire_cpu", "Undone the ZCPU") language.Add("ToolWirecpu_Model", "Model:" ) end if SERVER then CreateConVar("sbox_maxwire_cpus", 7) end cleanup.Register("wire_cpus") TOOL.ClientConVar = { model = "models/cheeze/wires/cpu.mdl", filename = "", memorymodel = "64krom", } if CLIENT then ------------------------------------------------------------------------------ -- Make sure firing animation is displayed clientside ------------------------------------------------------------------------------ function TOOL:LeftClick() return true end function TOOL:Reload() return true end function TOOL:RightClick() return false end end if SERVER then ------------------------------------------------------------------------------ -- ZCPU entity factory ------------------------------------------------------------------------------ local function MakeWireCPU(player, Pos, Ang, model) if !player:CheckLimit("wire_cpus") then return false end local self = ents.Create("gmod_wire_cpu") if !self:IsValid() then return false end self:SetModel(model) self:SetAngles(Ang) self:SetPos(Pos) self:Spawn() self:SetPlayer(player) self.player = player player:AddCount("wire_cpus", self) player:AddCleanup("wire_cpus", self) return self end duplicator.RegisterEntityClass("gmod_wire_cpu", MakeWireCPU, "Pos", "Ang", "Model") ------------------------------------------------------------------------------ -- Reload: wipe ROM/RAM and reset memory model, or attach debugger ------------------------------------------------------------------------------ function TOOL:Reload(trace) if trace.Entity:IsPlayer() then return false end local player = self:GetOwner() if player:KeyDown(IN_SPEED) then if (trace.Entity:IsValid()) and (trace.Entity:GetClass() == "gmod_wire_cpu") and (trace.Entity.player == player) then trace.Entity:SetMemoryModel(self:GetClientInfo("memorymodel")) trace.Entity:FlashData({}) player:SendLua("CPULib.InvalidateDebugger()") end else if (not trace.Entity:IsPlayer()) and (trace.Entity:IsValid()) and (trace.Entity:GetClass() == "gmod_wire_cpu") and (trace.Entity.player == player) then CPULib.AttachDebugger(trace.Entity,player) CPULib.SendDebugData(trace.Entity.VM,nil,player) player:SendLua("CPULib.DebuggerAttached = true") player:SendLua("CPULib.InvalidateDebugger()") player:SendLua("GAMEMODE:AddNotify(\"CPU debugger has been attached!\",NOTIFY_GENERIC,7)") else CPULib.AttachDebugger(nil,player) player:SendLua("CPULib.DebuggerAttached = false") player:SendLua("CPULib.InvalidateDebugger()") player:SendLua("GAMEMODE:AddNotify(\"CPU debugger deattached!\",NOTIFY_GENERIC,7)") end end return true end ------------------------------------------------------------------------------ -- Left click: spawn CPU or upload current program into it ------------------------------------------------------------------------------ function TOOL:LeftClick(trace) if trace.Entity:IsPlayer() then return false end local player = self:GetOwner() local model = self:GetClientInfo("model") local pos = trace.HitPos local ang = trace.HitNormal:Angle() ang.pitch = ang.pitch + 90 -- Re-upload data to CPU or a hispeed device if (trace.Entity:IsValid()) and ((trace.Entity:GetClass() == "gmod_wire_cpu") or (trace.Entity.WriteCell)) and (trace.Entity:GetPlayer() == player) then CPULib.SetUploadTarget(trace.Entity,player) player:SendLua("ZCPU_RequestCode()") player:SendLua("CPULib.InvalidateDebugger()") return true end if !self:GetSWEP():CheckLimit("wire_cpus") then return false end local entity = ents.Create("gmod_wire_cpu") if !entity:IsValid() then return false end player:AddCount("wire_cpus", entity) entity:SetModel(model) entity:SetAngles(ang) entity:SetPos(pos) entity:Spawn() entity:SetPlayer(player) entity.player = player entity:SetPos(trace.HitPos - trace.HitNormal * entity:OBBMins().z) local constraint = WireLib.Weld(entity, trace.Entity, trace.PhysicsBone, true) undo.Create("wire_cpu") undo.AddEntity(entity) undo.SetPlayer(player) undo.AddEntity(constraint) undo.Finish() entity:SetMemoryModel(self:GetClientInfo("memorymodel")) player:AddCleanup("wire_cpus", entity) CPULib.SetUploadTarget(entity,player) player:SendLua("ZCPU_RequestCode()") return true end ------------------------------------------------------------------------------ -- Right click: open editor ------------------------------------------------------------------------------ function TOOL:RightClick(trace) local player = self:GetOwner() player:SendLua("ZCPU_OpenEditor()") return true end ------------------------------------------------------------------------------ -- Update ghost entity ------------------------------------------------------------------------------ function TOOL:UpdateGhostWireCPU(ent, player) if not ent then return end if not ent:IsValid() then return end local tr = utilx.GetPlayerTrace(player, player:GetCursorAimVector()) local trace = util.TraceLine(tr) if not trace.Hit then return end if (trace.Entity) and ((trace.Entity:GetClass() == "gmod_wire_cpu") or (trace.Entity:IsPlayer()) or (trace.Entity.WriteCell)) then ent:SetNoDraw(true) return end local Ang = trace.HitNormal:Angle() Ang.pitch = Ang.pitch + 90 local min = ent:OBBMins() ent:SetPos(trace.HitPos - trace.HitNormal * min.z) ent:SetAngles(Ang) ent:SetNoDraw(false) end ------------------------------------------------------------------------------ -- Think loop ------------------------------------------------------------------------------ function TOOL:Think() local model = self:GetClientInfo("model") if (not self.GhostEntity) or (not self.GhostEntity:IsValid()) or (self.GhostEntity:GetModel() ~= model) or (not self.GhostEntity:GetModel()) then self:MakeGhostEntity(model, Vector(0,0,0), Angle(0,0,0)) end self:UpdateGhostWireCPU(self.GhostEntity, self:GetOwner()) end end -------------------------------------------------------------------------------- if CLIENT then ------------------------------------------------------------------------------ -- Compiler callbacks on the compiling state ------------------------------------------------------------------------------ local function compile_success() CPULib.Upload() end local function compile_error(errorText) print(errorText) GAMEMODE:AddNotify(errorText,NOTIFY_GENERIC,7) end ------------------------------------------------------------------------------ -- Request code to be compiled (called remotely from server) ------------------------------------------------------------------------------ function ZCPU_RequestCode() if ZCPU_Editor then CPULib.Compile(ZCPU_Editor:GetCode(),ZCPU_Editor:GetChosenFile(),compile_success,compile_error) end end ------------------------------------------------------------------------------ -- Open ZCPU editor ------------------------------------------------------------------------------ function ZCPU_OpenEditor() if not ZCPU_Editor then ZCPU_Editor = vgui.Create("Expression2EditorFrame") ZCPU_Editor:Setup("ZCPU Editor", "CPUChip", "CPU") end ZCPU_Editor:Open() end ------------------------------------------------------------------------------ -- Build tool control panel ------------------------------------------------------------------------------ function TOOL.BuildCPanel(panel) panel:AddControl("Header", { Text = "#Tool_wire_cpu_name", Description = "#Tool_wire_cpu_desc" }) ---------------------------------------------------------------------------- local Button = vgui.Create("DButton" , panel) panel:AddPanel(Button) Button:SetText("Online ZCPU documentation") Button.DoClick = function(button) CPULib.ShowDocumentation("ZCPU") end ---------------------------------------------------------------------------- local currentDirectory local FileBrowser = vgui.Create("wire_expression2_browser" , panel) panel:AddPanel(FileBrowser) FileBrowser:Setup("CPUChip") FileBrowser:SetSize(235,400) function FileBrowser:OnFileClick() local lastClickTime = CurTime() if not ZCPU_Editor then ZCPU_Editor = vgui.Create("Expression2EditorFrame") ZCPU_Editor:Setup("ZCPU Editor", "CPUChip", "CPU") end if (currentDirectory == self.File.FileDir) and (CurTime() - lastClickTime < 1) then ZCPU_Editor:Open(currentDirectory) else lastClickTime = CurTime() currentDirectory = self.File.FileDir ZCPU_Editor:LoadFile(currentDirectory) end end ---------------------------------------------------------------------------- local New = vgui.Create("DButton" , panel) panel:AddPanel(New) New:SetText("New file") New.DoClick = function(button) ZCPU_OpenEditor() ZCPU_Editor:AutoSave() ZCPU_Editor:NewScript(false) end panel:AddControl("Label", {Text = ""}) ---------------------------------------------------------------------------- local OpenEditor = vgui.Create("DButton", panel) panel:AddPanel(OpenEditor) OpenEditor:SetText("Open Editor") OpenEditor.DoClick = ZCPU_OpenEditor ---------------------------------------------------------------------------- panel:AddControl("Label", {Text = ""}) panel:AddControl("Label", {Text = "CPU settings:"}) ---------------------------------------------------------------------------- local modelPanel = WireDermaExts.ModelSelect(panel, "wire_cpu_model", list.Get("Wire_gate_Models"), 2) panel:AddControl("Label", {Text = ""}) ---------------------------------------------------------------------------- panel:AddControl("ComboBox", { Label = "Memory model", Options = { ["128 bytes ROM only"] = {wire_cpu_memorymodel = "128rom"}, ["128 bytes RAM/ROM"] = {wire_cpu_memorymodel = "128"}, ["64KB RAM/ROM"] = {wire_cpu_memorymodel = "64krom"}, ["64KB RAM only"] = {wire_cpu_memorymodel = "64k"}, ["128KB RAM/ROM"] = {wire_cpu_memorymodel = "128krom"}, ["No internal RAM/ROM"] = {wire_cpu_memorymodel = "flat"}, } }) panel:AddControl("Label", {Text = "Sets the processor memory model (determines iteraction with the external devices)"}) end ------------------------------------------------------------------------------ -- Tool screen ------------------------------------------------------------------------------ surface.CreateFont("Lucida Console", 30, 1000, true, false, "ZCPUToolScreenFont") surface.CreateFont("Lucida Console", 26, 1000, true, false, "ZCPUToolScreenFontSmall") local function outc(text,y,color) draw.DrawText(text,"ZCPUToolScreenFont",2,32*y,color,0) end local prevStateTime = RealTime() local prevState = nil local consoleHistory = { "", "", "", "", "", "" } local stageName = {"Preprocessing","Tokenizing","Parsing","Generating","Optimizing","Resolving","Outputting"} local stageNameShort = {"Preproc","Tokenize","Parse","Generate","Optimize","Resolve","Output"} local function outform(x,y,w,h,title) surface.SetDrawColor(255, 255, 255, 255) surface.DrawRect(x*28-3,y*32-3,w*28,h*32) surface.SetDrawColor(0, 0, 0, 255) surface.DrawRect(x*28+3,y*32+3,w*28,h*32) surface.SetDrawColor(192, 220, 192, 255) surface.DrawRect(x*28,y*32,w*28-3,h*32-3) surface.SetDrawColor(192, 192, 192, 255) surface.DrawRect(x*28,y*32,w*28,h*32) if title then surface.SetDrawColor(0, 0, 128, 255) surface.DrawRect(x*28+4,y*32+4,w*28-4,1*32-4) draw.DrawText(title,"ZCPUToolScreenFontSmall",x*28+4,y*32+4,Color(255,255,255,255),0) end end function CPULib.RenderCPUTool(screenIndex,toolName) if screenIndex == 0 then surface.SetDrawColor(0, 0, 128, 255) surface.DrawRect(0, 0, 256, 256) surface.SetDrawColor(240, 240, 0, 255) surface.DrawRect(0,0,256,32) outc(" ToolOS r"..VERSION.." ",0,Color(0,0,0,255)) if CPULib.Uploading then outc("Program size:",2,Color(255,255,255,255)) outc(string.format("%d bytes",CPULib.TotalUploadData),3,Color(255,255,255,255)) outc(string.format("Uploading %2d%%",100-100*CPULib.RemainingUploadData/(CPULib.TotalUploadData+1e-12)),5,Color(255,255,255,255)) outc(string.format("%d bytes",CPULib.RemainingUploadData),6,Color(255,255,255,255)) prevStateTime = RealTime() elseif CPULib.ServerUploading then outc("Program size:",2,Color(255,255,255,255)) outc(string.format("%d bytes",#CPULib.Buffer),3,Color(255,255,255,255)) outc("Uploading 100",5,Color(255,255,255,255)) outc(" Standby ",6,Color(255,255,255,255)) prevStateTime = RealTime() elseif CPULib.Compiling then outc(string.format("Stage %2d/7",HCOMP.Stage+1),2,Color(255,255,255,255)) outc(stageName[HCOMP.Stage+1],3,Color(255,255,255,255)) prevStateTime = RealTime() else if RealTime() - prevStateTime > 0.15 then outc("Flash utility",1,Color(255,255,255,255)) outc("(C) 2007-2011",2,Color(255,255,255,255)) outc("Black Phoenix",3,Color(255,255,255,255)) outc(string.format("RAM: %5d KB",collectgarbage("count") or 0),7,Color(255,255,255,255)) else surface.SetDrawColor(0, 0, 0, 255) surface.DrawRect(0, 0, 256, 256) end end elseif screenIndex == 1 then surface.SetDrawColor(0, 0, 0, 255) surface.DrawRect(0, 0, 256, 256) surface.SetDrawColor(240, 120, 0, 255) surface.DrawRect(16*(#toolName+1),32*0+14,256,4) outc(toolName,0,Color(240, 120,0,255)) outc(string.format(" RAM %5d KB",collectgarbage("count") or 0),1,Color(255,255,255,255)) surface.SetDrawColor(240, 120, 0, 255) surface.DrawRect(16*(5),32*2+14,256,4) outc("TASK",2,Color(240, 120,0,255)) outc(" STATUS",3,Color(255,255,255,255)) surface.SetDrawColor(240, 120, 0, 255) surface.DrawRect(16*(4),32*6+14,256,4) outc("NET",6,Color(240, 120,0,255)) if CPULib.Uploading then outc(string.format("UP %.3f KB",CPULib.RemainingUploadData/1024),7,Color(255,255,255,255)) outc(string.format("ROMUPL [%3d%%]",100-100*CPULib.RemainingUploadData/(CPULib.TotalUploadData+1e-12)),4,Color(255,255,255,255)) outc("UPLMON [ OK ]",5,Color(255,255,255,255)) elseif CPULib.ServerUploading then outc("UPLMON [ OK ]",4,Color(255,255,255,255)) outc("DOWN SYNC",7,Color(255,255,255,255)) elseif CPULib.Compiling then outc(string.format("HCOMP [%2d/7]",HCOMP.Stage),4,Color(255,255,255,255)) outc("IDLE",7,Color(255,255,255,255)) else outc("IDLE",7,Color(255,255,255,255)) end elseif screenIndex == 2 then surface.SetDrawColor(0, 0, 0, 255) surface.DrawRect(0, 0, 256, 256) outc("TL-UNIX "..(VERSION/100),0,Color(200,200,200,255)) outc(consoleHistory[1],2,Color(200,200,200,255)) outc(consoleHistory[2],3,Color(200,200,200,255)) outc(consoleHistory[3],4,Color(200,200,200,255)) outc(consoleHistory[4],5,Color(200,200,200,255)) outc(consoleHistory[5],6,Color(200,200,200,255)) outc(consoleHistory[6],7,Color(200,200,200,255)) if CPULib.Uploading then if prevState ~= 0 then consoleHistory[1] = consoleHistory[2] consoleHistory[2] = consoleHistory[3] consoleHistory[3] = consoleHistory[4] consoleHistory[4] = string.lower(toolName).."@:/# upl" end consoleHistory[5] = string.format(" %3d%%",100-100*CPULib.RemainingUploadData/(CPULib.TotalUploadData+1e-12)) consoleHistory[6] = string.format(" %d B",CPULib.RemainingUploadData) prevState = 0 elseif CPULib.ServerUploading then consoleHistory[5] = " ###" consoleHistory[6] = " 0 B" prevState = 0 elseif CPULib.Compiling then if prevState ~= 1 then consoleHistory[1] = consoleHistory[2] consoleHistory[2] = consoleHistory[3] consoleHistory[3] = consoleHistory[4] consoleHistory[4] = consoleHistory[5] consoleHistory[5] = string.lower(toolName).."@:/# hcmp" end consoleHistory[6] = string.format("Stage %2d/7",HCOMP.Stage+1) prevState = 1 else if prevState ~= 2 then consoleHistory[1] = consoleHistory[2] consoleHistory[2] = consoleHistory[3] consoleHistory[3] = consoleHistory[4] consoleHistory[4] = consoleHistory[5] consoleHistory[5] = consoleHistory[6] consoleHistory[6] = string.lower(toolName).."@:/# " end prevState = 2 end elseif screenIndex == 3 then surface.SetDrawColor(0, 128, 128, 255) surface.DrawRect(0, 0, 256, 256) outform(0,7,12,1) outform(0,7,3,1) outc("MENU",7,Color(0,0,0,255)) if CPULib.Uploading then outform(1,1,7,5,"Upload") outc(string.format(" %.3f kb",CPULib.RemainingUploadData/1024),3,Color(0,0,0,255)) outc(string.format(" %3d%% done",100-100*CPULib.RemainingUploadData/(CPULib.TotalUploadData+1e-12)),4,Color(0,0,0,255)) outform(1,5,7,0.9) surface.SetDrawColor(0, 0, 128, 255) surface.DrawRect(1*28+4,5*32+4, math.floor((7*28-4)*(1-CPULib.RemainingUploadData/(CPULib.TotalUploadData+1e-12))/14)*14, 1*32-8) elseif CPULib.ServerUploading then outform(1,3,7,3,"Upload") outc(" Standby",5,Color(0,0,0,255)) elseif CPULib.Compiling then outform(1,1,7,5,"HL-ZASM") outc(string.format(" Stage %d/7",HCOMP.Stage+1),3,Color(0,0,0,255)) outc(" "..stageNameShort[HCOMP.Stage+1],4,Color(0,0,0,255)) else -- end end end function TOOL:RenderToolScreen() cam.Start2D() local currentTime = os.date("*t") CPULib.RenderCPUTool(currentTime.yday % 4,"CPU") cam.End2D() end end