From 47e2804fbdd0b3b735aa27bd5f0c6cd69480a2a6 Mon Sep 17 00:00:00 2001 From: Bilbard Date: Sat, 11 Jul 2026 23:30:14 -0600 Subject: [PATCH 1/8] Improved Dynamic Memory from wire extras (minus persistence), automatically upgrade spawned/duped memory gates to Dynamic Memory --- lua/entities/gmod_wire_dynmemory.lua | 226 +++++++++++++++++++++++ lua/entities/gmod_wire_gate.lua | 13 ++ lua/wire/gates/memory.lua | 259 +-------------------------- lua/wire/stools/dynmemory.lua | 74 ++++++++ 4 files changed, 320 insertions(+), 252 deletions(-) create mode 100644 lua/entities/gmod_wire_dynmemory.lua create mode 100644 lua/wire/stools/dynmemory.lua diff --git a/lua/entities/gmod_wire_dynmemory.lua b/lua/entities/gmod_wire_dynmemory.lua new file mode 100644 index 0000000000..dc166e2ac8 --- /dev/null +++ b/lua/entities/gmod_wire_dynmemory.lua @@ -0,0 +1,226 @@ +AddCSLuaFile() +DEFINE_BASECLASS( "base_wire_entity" ) +ENT.PrintName = "Wire Dynamic Memory" +ENT.Author = "Sebastian J., the gabe" +ENT.WireDebugName = "Dynamic Memory" + +if CLIENT then return end -- No more client + +function ENT:Initialize() + self:PhysicsInit(SOLID_VPHYSICS) + self:SetMoveType(MOVETYPE_VPHYSICS) + self:SetSolid(SOLID_VPHYSICS) + + self.Inputs = Wire_CreateInputs(self, {"Clk"}) + + self.Outputs = Wire_CreateOutputs(self, {"Out"}) + + self.Size = 1 + self.Memory = {} + self.Memory[0] = 0 + + --this flag assists in replacing the old ram gate chips + --when adv. dupe 2 spawns something, it seems to run Setup() at least twice + --at the first setup we successfully hijack the memory chip and imitate its capacity + --at the second setup, the size is set back to 1 since were not being initialized through FromGate() + --to fix this, the legacy flag disables resizing of the ram chip until it is duped and spawned in again, + --since at this point we dont have to hijack the old ram chip + self.Legacy = false + + --the old dynamic memory chips had persistence like the dhdd + --if this feature is ever wanted, the required code is all here (and dynmemory.lua), but commented out + --self.Persistent = false + + self.AddrWrite = 0 + self.AddrRead = 0 + self.AddrWriteY = 0 + self.AddrReadY = 0 + self.Clk = false + self.Data = 0 + + self.WOM = false + self.Bifurcate = false + self.BifurcateMagic = 0 +end + +function ENT:Setup(size, wom, bifurcate, legacy) + if self.Legacy then return end + self.WOM = (wom == 1) + self.Bifurcate = (bifurcate == 1) + + local inputbuilt = {} + + if not self.WOM then + if self.Bifurcate then + inputbuilt = {"Clk", "AddrReadX", "AddrReadY", "AddrWriteX", "AddrWriteY", "Data", "Reset"} + else + inputbuilt = {"Clk", "AddrRead", "AddrWrite", "Data", "Reset"} + end + else + if self.Bifurcate then + inputbuilt = {"Clk", "AddrWriteX", "AddrWriteY", "Data", "Reset"} + else + inputbuilt = {"Clk", "AddrWrite", "Data", "Reset"} + end + end + + self.Inputs = Wire_AdjustInputs(self, inputbuilt) + + local size = math.Clamp(math.floor(size or self.Size), 1, 2097152) --2mb limit + + if self.Bifurcate then + self.BifurcateMagic = math.floor(math.sqrt(size)) + size = self.BifurcateMagic * self.BifurcateMagic + end + + local overheap = size - self.Size + + if (overheap < 0) then + for i= size, self.Size -1 do + self.Memory[i] = nil + end + elseif (overheap > 0) then + for i = self.Size, size - 1 do + self.Memory[i] = 0 + end + end + self.Size = size + + local sstr = self.Size + local sunit = " Bytes" + + if self.Bifurcate then + sstr = tostring(self.BifurcateMagic) .. "x" .. tostring(self.BifurcateMagic) .. sunit + else + if (sstr >= 1048576) then + sunit = "MB" + sstr = math.floor(sstr / 10485.76) / 100 --shows up to 2 decimals + elseif (sstr >= 1024) then + sunit = "KB" + sstr = math.floor(sstr / 1024) + end + sstr = tostring(sstr) .. sunit + end + + self:SetOverlayText(sstr .. (self.WOM == true and " Write-Only" or "") .. " RAM" .. (self.Size >= 1024 and " (" .. self.Size .. " bytes)" or "") .. (legacy and " (Legacy)" or "") ) + + self.Legacy = legacy +end + +function ENT:Think() + if self.Bifurcate then + if self.Clk and self.AddrWrite >= 0 and self.AddrWrite < self.BifurcateMagic and self.AddrWriteY >= 0 and self.AddrWriteY < self.BifurcateMagic then + self:WriteCell(self.AddrWrite + self.AddrWriteY*64, self.Data) + end + if not self.WOM and self.AddrRead >= 0 and self.AddrRead < self.BifurcateMagic and self.AddrReadY >= 0 and self.AddrReadY < self.BifurcateMagic then + WireLib.TriggerOutput(self, "Out", self.Memory[self.AddrRead + self.AddrReadY * self.BifurcateMagic]) + end + else + if self.Clk and self.AddrWrite < self.Size and self.AddrWrite >= 0 then + self:WriteCell(self.AddrWrite, self.Data) + end + if not self.WOM and self.AddrRead < self.Size and self.AddrRead >= 0 then + WireLib.TriggerOutput(self, "Out", self.Memory[self.AddrRead]) + end + end + self:NextThink(CurTime() + 0.02) --same as gate ent + return true +end + +--[[function ENT:SetPersistent(val) + self.Persistent = val or self.Persistent +end]] + +function ENT:TriggerInput(iname, Value) + if (iname == "Reset") then + if (Value == 1) then + for i=0, self.Size - 1 do + self.Memory[i] = 0 + end + end + elseif (iname == "AddrWrite") or (iname == "AddrWriteX") then + self.AddrWrite = math.floor(Value) + elseif (iname == "AddrRead") or (iname == "AddrReadX") then + self.AddrRead = math.floor(Value) + elseif (iname == "AddrWriteY") then + self.AddrWriteY = math.floor(Value) + elseif (iname == "AddrReadY") then + self.AddrReadY = math.floor(Value) + elseif (iname == "Data") then + self.Data = Value + elseif (iname == "Clk") then + self.Clk = Value > 0 + end +end + +function ENT:ReadCell(Address) + Address = math.floor(tonumber(Address)) + if self.WOM or (Address < 0 || Address >= self.Size) then + return 0 + end + return self.Memory[Address] +end + +function ENT:WriteCell(Address, Value) + Address = math.floor(tonumber(Address)) + if (Address < 0 || Address >= self.Size) then + return false + end + self.Memory[Address] = Value or 0 + return true +end + +local gateconv = {} +--{size, write only, bifurcate} +gateconv["ram8"] = {8, 0, 0} +gateconv["ram64"] = {64, 0, 0} +gateconv["ram1k"] = {1024, 0, 0} +gateconv["ram32k"] = {32768, 0, 0} +gateconv["ram128k"] = {131072, 0, 0} +gateconv["ram64x64"] = {4096, 0, 1} +gateconv["wom4"] = {4, 1, 0} + +function ENT:FromGate(action) + if gateconv[action] then + self:Setup(gateconv[action][1], gateconv[action][2], gateconv[action][3], true) + end +end + +function ENT:BuildDupeInfo() + local info = self.BaseClass.BuildDupeInfo(self) or {} + + info.MemSize = self.Size + info.WOM = self.WOM + info.Bifurcate = self.Bifurcate + --[[info.Persistent = self.Persistent + if (self.Persistent) then + info.Memory = {} + --same 256k limit as DHDD + for i=0, math.min(self.Size - 1, 262143) do + if (self.Memory[i]) then + info.Memory[i] = self.Memory[i] + end + end + end]] + + return info +end + +function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID) + self.BaseClass.ApplyDupeInfo(self, ply, ent, info, GetEntByID) + + self:Setup(info.MemSize or 1, info.WOM or 0, info.Bifurcate or 0, false) + + --[[self.Persistent = info.Persistent + if (info.Persistent) then + info.Memory = info.Memory or {} + --same 256k (512^2) limit as DHDD + for i=0, math.min(self.Size - 1, 262143) do + if (info.Memory[i]) then + self.Memory[i] = info.Memory[i] + end + end + end]] +end + +duplicator.RegisterEntityClass("gmod_wire_dynmemory", WireLib.MakeWireEnt, "Data", "Size", "WOM", "Bifurcate")--, "Persistent") diff --git a/lua/entities/gmod_wire_gate.lua b/lua/entities/gmod_wire_gate.lua index 61c11efe2e..ec680b821a 100644 --- a/lua/entities/gmod_wire_gate.lua +++ b/lua/entities/gmod_wire_gate.lua @@ -227,6 +227,19 @@ function WireLib.MakeWireGate(ply, pos, ang, model, action, noclip) local gate = GateActions[action] if not gate or gate.is_banned then return end + if gate.Upgrade then + local limitstr = gate.Upgrade:sub(6).."s" + if IsValid(ply) and (not ply:CheckLimit(limitstr)) then return false end + local upgrade = ents.Create(gate.Upgrade) + upgrade:SetModel(model) + upgrade:SetAngles(ang) + upgrade:SetPos(pos) + upgrade:Spawn() + upgrade:FromGate(action) + upgrade:SetPlayer(ply) + if IsValid(ply) then ply:AddCount(limitstr, upgrade) end + return upgrade + end return WireLib.MakeWireEnt(ply, { Class = "gmod_wire_gate", Pos = pos, Angle = ang, Model = model }, action, noclip) end diff --git a/lua/wire/gates/memory.lua b/lua/wire/gates/memory.lua index a6af5d9301..8d760fc77e 100644 --- a/lua/wire/gates/memory.lua +++ b/lua/wire/gates/memory.lua @@ -112,282 +112,37 @@ GateActions["toggle"] = { GateActions["wom4"] = { name = "Write Only Memory(4 store)", - inputs = { "Clk", "AddrWrite", "Data" }, - output = function( gate, Clk, AddrWrite, Data ) - AddrWrite = math.floor(tonumber(AddrWrite)) - if ( Clk > 0 ) then - if ( AddrWrite >= 0 ) and ( AddrWrite < 4 ) then - gate.LatchStore[AddrWrite] = Data - end - end - return 0 - end, - reset = function( gate ) - gate.LatchStore = {} - for i = 0, 3 do - gate.LatchStore[i] = 0 - end - end, - label = function() - return "Write Only Memory - 4 store" - end + Upgrade = "gmod_wire_dynmemory", } GateActions["ram8"] = { name = "RAM(8 store)", - inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, - output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) - if (Reset > 0) then - gate.LatchStore = {} - end - - AddrRead = math.floor(tonumber(AddrRead)) - AddrWrite = math.floor(tonumber(AddrWrite)) - - if (Clk > 0) then - if (AddrWrite >= 0) and (AddrWrite < 8) then - gate.LatchStore[AddrWrite] = Data - end - end - - if (AddrRead < 0) or (AddrRead >= 8) then return 0 end - - return gate.LatchStore[AddrRead] or 0 - end, - reset = function(gate) - gate.LatchStore = {} - end, - label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset) - return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. - "\nReadAddr:"..AddrRead.." = "..Out - end, - ReadCell = function(dummy,gate,Address) - if (Address < 0) or (Address >= 8) then - return 0 - else - return gate.LatchStore[Address] or 0 - end - end, - WriteCell = function(dummy,gate,Address,value) - if (Address < 0) or (Address >= 8) then - return false - else - gate.LatchStore[Address] = value - return true - end - end + Upgrade = "gmod_wire_dynmemory" } GateActions["ram64"] = { name = "RAM(64 store)", - inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, - output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) - if (Reset > 0) then - gate.LatchStore = {} - end - - AddrRead = math.floor(tonumber(AddrRead)) - AddrWrite = math.floor(tonumber(AddrWrite)) - if (Clk > 0) then - if (AddrWrite < 64) then - gate.LatchStore[AddrWrite] = Data - end - end - return gate.LatchStore[AddrRead] or 0 - end, - reset = function(gate) - gate.LatchStore = {} - end, - label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset) - return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. - "\nReadAddr:"..AddrRead.." = "..Out - end, - ReadCell = function(dummy,gate,Address) - if (Address < 0) or (Address >= 64) then - return 0 - else - return gate.LatchStore[Address] or 0 - end - end, - WriteCell = function(dummy,gate,Address,value) - if (Address < 0) or (Address >= 64) then - return false - else - gate.LatchStore[Address] = value - return true - end - end + Upgrade = "gmod_wire_dynmemory" } GateActions["ram1k"] = { name = "RAM(1kb)", - inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, - output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) - if (Reset > 0) then - gate.LatchStore = {} - end - - AddrRead = math.floor(tonumber(AddrRead)) - AddrWrite = math.floor(tonumber(AddrWrite)) - if (Clk > 0) then - if (AddrWrite < 1024) then - gate.LatchStore[AddrWrite] = Data - end - end - return gate.LatchStore[AddrRead] or 0 - end, - reset = function(gate) - gate.LatchStore = {} - end, - label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset ) - return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. - "\nReadAddr:"..AddrRead.." = "..Out - end, - ReadCell = function(dummy,gate,Address) - if (Address < 0) or (Address >= 1024) then - return 0 - else - return gate.LatchStore[Address] or 0 - end - end, - WriteCell = function(dummy,gate,Address,value) - if (Address < 0) or (Address >= 1024) then - return false - else - gate.LatchStore[Address] = value - return true - end - end + Upgrade = "gmod_wire_dynmemory" } GateActions["ram32k"] = { name = "RAM(32kb)", - inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, - output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) - if (Reset > 0) then - gate.LatchStore = {} - end - - AddrRead = math.floor(tonumber(AddrRead)) - AddrWrite = math.floor(tonumber(AddrWrite)) - if (Clk > 0) then - if (AddrWrite < 32768) then - gate.LatchStore[AddrWrite] = Data - end - end - return gate.LatchStore[AddrRead] or 0 - end, - reset = function(gate) - gate.LatchStore = {} - end, - label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset ) - return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. - "\nReadAddr:"..AddrRead.." = "..Out - end, - ReadCell = function(dummy,gate,Address) - if (Address < 0) or (Address >= 32768) then - return 0 - else - return gate.LatchStore[Address] or 0 - end - end, - WriteCell = function(dummy,gate,Address,value) - if (Address < 0) or (Address >= 32768) then - return false - else - gate.LatchStore[Address] = value - return true - end - end + Upgrade = "gmod_wire_dynmemory" } GateActions["ram128k"] = { name = "RAM(128kb)", - inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, - output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) - if (Reset > 0) then - gate.LatchStore = {} - end - - AddrRead = math.floor(tonumber(AddrRead)) - AddrWrite = math.floor(tonumber(AddrWrite)) - if (Clk > 0) then - if (AddrWrite < 131072) then - gate.LatchStore[AddrWrite] = Data - end - end - return gate.LatchStore[AddrRead] or 0 - end, - reset = function(gate) - gate.LatchStore = {} - end, - label = function(Out, Clk, AddrRead, AddrWrite, Data) - return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.. - "\nReadAddr:"..AddrRead.." = "..Out - end, - ReadCell = function(dummy,gate,Address) - if (Address < 0) or (Address >= 131072) then - return 0 - else - return gate.LatchStore[Address] or 0 - end - end, - WriteCell = function(dummy,gate,Address,value) - if (Address < 0) or (Address >= 131072) then - return false - else - gate.LatchStore[Address] = value - return true - end - end + Upgrade = "gmod_wire_dynmemory" } GateActions["ram64x64"] = { name = "RAM(64x64 store)", - inputs = { "Clk", "AddrReadX", "AddrReadY", "AddrWriteX", "AddrWriteY", "Data", "Reset" }, - output = function(gate, Clk, AddrReadX, AddrReadY, AddrWriteX, AddrWriteY, Data, Reset ) - if (Reset > 0) then - gate.LatchStore = {} - end - - AddrReadX = math.floor(tonumber(AddrReadX)) - AddrReadY = math.floor(tonumber(AddrReadY)) - AddrWriteX = math.floor(tonumber(AddrWriteX)) - AddrWriteY = math.floor(tonumber(AddrWriteY)) - if (Clk > 0) then - if (AddrWriteX >= 0) and (AddrWriteX < 64) or (AddrWriteY >= 0) and (AddrWriteY < 64) then - gate.LatchStore[AddrWriteX + AddrWriteY*64] = Data - end - end - - if (AddrReadX < 0) or (AddrReadX >= 64) or (AddrReadY < 0) or (AddrReadY >= 64) then - return 0 - end - - return gate.LatchStore[AddrReadX + AddrReadY*64] or 0 - end, - reset = function(gate) - gate.LatchStore = {} - end, - label = function(Out, Clk, AddrReadX, AddrReadY, AddrWriteX, AddrWriteY, Data, Reset) - return "WriteAddr:"..AddrWriteX..", "..AddrWriteY.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. - "\nReadAddr:"..AddrReadX..", "..AddrReadY.." = "..Out - end, - ReadCell = function(dummy,gate,Address) - if (Address < 0) or (Address >= 4096) then - return 0 - else - return gate.LatchStore[Address] or 0 - end - end, - WriteCell = function(dummy,gate,Address,value) - if (Address < 0) or (Address >= 4096) then - return false - else - gate.LatchStore[Address] = value - return true - end - end + Upgrade = "gmod_wire_dynmemory" } GateActions["udcounter"] = { diff --git a/lua/wire/stools/dynmemory.lua b/lua/wire/stools/dynmemory.lua new file mode 100644 index 0000000000..2ed40a3d75 --- /dev/null +++ b/lua/wire/stools/dynmemory.lua @@ -0,0 +1,74 @@ +WireToolSetup.setCategory( "Memory" ) +WireToolSetup.open( "dynmemory", "Dynamic Memory Chip", "gmod_wire_dynmemory", nil, "Dynamic Memory Chips" ) + +if CLIENT then + language.Add( "Tool.wire_dynmemory.name", "Dynamic Memory Chip Tool (Wire)" ) + language.Add( "Tool.wire_dynmemory.desc", "Spawns a Dynamic Memory Chip" ) + language.Add( "Tool.wire_dynmemory.wom", "Write-Only Mode" ) + language.Add( "Tool.wire_dynmemory.womdesc", "Disables reading from memory. Affects highspeed access." ) + language.Add( "Tool.wire_dynmemory.bifurcate", "Bifurcate" ) + language.Add( "Tool.wire_dynmemory.bifurcatedesc", "Bifurcates address lines into ReadAddr(X,Y) and WriteAddr(X,Y). Memory size will be adjusted for round addresses. A memory size of 4096 would mean the bifurcated chip is 64x64. Has no effect on highspeed access." ) + --language.Add( "Tool.wire_dynmemory.pers", "Persistent Memory" ) + --language.Add( "Tool.wire_dynmemory.persdesc", "Should contents save when duped?" ) + TOOL.Information = { { name = "left", text = "Create/Update " .. TOOL.Name }, { name = "right", text = "Copy " .. TOOL.Name } } + + --language.Add( "Tool.wire_dynmemory.note", "NOTE: Persistence only saves the first\n512^2 values (256kb) to prevent\nmassive dupe files and lag." ) + + TOOL.ClientConVar["model"] = "models/jaanus/wiretool/wiretool_gate.mdl" + TOOL.ClientConVar["size"] = 16384 + TOOL.ClientConVar["wom"] = 0 + TOOL.ClientConVar["bifurcate"] = 0 + --TOOL.ClientConVar["persistent"] = 0 + + function TOOL.BuildCPanel( panel ) + ModelPlug_AddToCPanel(panel, "gate", "wire_dynmemory", nil, 4) + + panel:NumSlider("Memory Size","wire_dynmemory_size",1,2097152,0) + + panel:AddControl("Checkbox", { + Label = "#Tool.wire_dynmemory.wom", + Description = "", + Command = "wire_dynmemory_wom" + }) + + panel:Help("#Tool.wire_dynmemory.womdesc") + + panel:AddControl("Checkbox", { + Label = "#Tool.wire_dynmemory.bifurcate", + Description = "", + Command = "wire_dynmemory_bifurcate" + }) + + panel:Help("#Tool.wire_dynmemory.bifurcatedesc") + + --[[panel:AddControl("Checkbox", { + Label = "#Tool.wire_dynmemory.pers", + Description = "#Tool.wire_dynmemory.persdesc", + Command = "wire_dynmemory_persistent" + }) + panel:Help("#Tool.wire_dynmemory.note")]] + end + + WireToolSetup.setToolMenuIcon( "icon16/database.png" ) +else + function TOOL:GetConVars() + return self:GetClientNumber( "size" ), self:GetClientNumber( "wom" ), self:GetClientNumber( "bifurcate" )--, self:GetClientNumber( "persistent" ) + end +end +WireToolSetup.BaseLang() +WireToolSetup.SetupMax( 32 ) + +function TOOL:RightClick(trace) + if (CLIENT) then return true end + + if (trace.Entity and trace.Entity:IsValid()) then + if (trace.Entity:GetClass() == "gmod_wire_dynmemory") then + self:GetOwner():ConCommand('wire_dynmemory_size "'..trace.Entity.Size..'"\n') + self:GetOwner():ConCommand('wire_dynmemory_wom "'..(trace.Entity.WOM and "1" or "0")..'"\n') + self:GetOwner():ConCommand('wire_dynmemory_bifurcate "'..(trace.Entity.Bifurcate and "1" or "0")..'"\n') + return true + end + end + + return false +end From 91ac3da93d0b29f8190f616bb8064b1b02970ba8 Mon Sep 17 00:00:00 2001 From: Bilbard Date: Sat, 11 Jul 2026 23:43:14 -0600 Subject: [PATCH 2/8] Fix typo in dupe info --- lua/entities/gmod_wire_dynmemory.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/entities/gmod_wire_dynmemory.lua b/lua/entities/gmod_wire_dynmemory.lua index dc166e2ac8..9ba978ff57 100644 --- a/lua/entities/gmod_wire_dynmemory.lua +++ b/lua/entities/gmod_wire_dynmemory.lua @@ -190,8 +190,8 @@ function ENT:BuildDupeInfo() local info = self.BaseClass.BuildDupeInfo(self) or {} info.MemSize = self.Size - info.WOM = self.WOM - info.Bifurcate = self.Bifurcate + info.WOM = (self.WOM and 1 or 0) + info.Bifurcate = (self.Bifurcate and 1 or 0) --[[info.Persistent = self.Persistent if (self.Persistent) then info.Memory = {} From face83da2edd8c41cc72b6a996a83e30494a0492 Mon Sep 17 00:00:00 2001 From: Bilbard Date: Sun, 12 Jul 2026 09:32:53 -0600 Subject: [PATCH 3/8] Use the magic, not 64 --- lua/entities/gmod_wire_dynmemory.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/entities/gmod_wire_dynmemory.lua b/lua/entities/gmod_wire_dynmemory.lua index 9ba978ff57..5635d48660 100644 --- a/lua/entities/gmod_wire_dynmemory.lua +++ b/lua/entities/gmod_wire_dynmemory.lua @@ -97,7 +97,7 @@ function ENT:Setup(size, wom, bifurcate, legacy) sstr = math.floor(sstr / 10485.76) / 100 --shows up to 2 decimals elseif (sstr >= 1024) then sunit = "KB" - sstr = math.floor(sstr / 1024) + sstr = math.floor(sstr / 102.4) / 10 --shows up to 1 decimal end sstr = tostring(sstr) .. sunit end @@ -110,7 +110,7 @@ end function ENT:Think() if self.Bifurcate then if self.Clk and self.AddrWrite >= 0 and self.AddrWrite < self.BifurcateMagic and self.AddrWriteY >= 0 and self.AddrWriteY < self.BifurcateMagic then - self:WriteCell(self.AddrWrite + self.AddrWriteY*64, self.Data) + self:WriteCell(self.AddrWrite + self.AddrWriteY * self.BifurcateMagic, self.Data) end if not self.WOM and self.AddrRead >= 0 and self.AddrRead < self.BifurcateMagic and self.AddrReadY >= 0 and self.AddrReadY < self.BifurcateMagic then WireLib.TriggerOutput(self, "Out", self.Memory[self.AddrRead + self.AddrReadY * self.BifurcateMagic]) From f0d5f3a5988fbc7ac8fbe5a96e898bfe4d130e74 Mon Sep 17 00:00:00 2001 From: Bilbard Date: Sun, 12 Jul 2026 10:50:58 -0600 Subject: [PATCH 4/8] Edge-case protection --- lua/entities/gmod_wire_dynmemory.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/entities/gmod_wire_dynmemory.lua b/lua/entities/gmod_wire_dynmemory.lua index 5635d48660..2c0a6c0245 100644 --- a/lua/entities/gmod_wire_dynmemory.lua +++ b/lua/entities/gmod_wire_dynmemory.lua @@ -183,7 +183,9 @@ gateconv["wom4"] = {4, 1, 0} function ENT:FromGate(action) if gateconv[action] then self:Setup(gateconv[action][1], gateconv[action][2], gateconv[action][3], true) + return end + self:Setup(1, 0, 0, true) --this shouldnt be able to happen end function ENT:BuildDupeInfo() From 010d269cbbecd9999607106f8ae9f3ae74f13540 Mon Sep 17 00:00:00 2001 From: Bilbard Date: Sun, 12 Jul 2026 11:32:12 -0600 Subject: [PATCH 5/8] OOPS forgot FPGA needs those --- lua/wire/gates/memory.lua | 252 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/lua/wire/gates/memory.lua b/lua/wire/gates/memory.lua index 8d760fc77e..5e15f1f608 100644 --- a/lua/wire/gates/memory.lua +++ b/lua/wire/gates/memory.lua @@ -112,36 +112,288 @@ GateActions["toggle"] = { GateActions["wom4"] = { name = "Write Only Memory(4 store)", + inputs = { "Clk", "AddrWrite", "Data" }, + output = function( gate, Clk, AddrWrite, Data ) + AddrWrite = math.floor(tonumber(AddrWrite)) + if ( Clk > 0 ) then + if ( AddrWrite >= 0 ) and ( AddrWrite < 4 ) then + gate.LatchStore[AddrWrite] = Data + end + end + return 0 + end, + reset = function( gate ) + gate.LatchStore = {} + for i = 0, 3 do + gate.LatchStore[i] = 0 + end + end, + label = function() + return "Write Only Memory - 4 store" + end, Upgrade = "gmod_wire_dynmemory", } GateActions["ram8"] = { name = "RAM(8 store)", + inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, + output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) + if (Reset > 0) then + gate.LatchStore = {} + end + + AddrRead = math.floor(tonumber(AddrRead)) + AddrWrite = math.floor(tonumber(AddrWrite)) + + if (Clk > 0) then + if (AddrWrite >= 0) and (AddrWrite < 8) then + gate.LatchStore[AddrWrite] = Data + end + end + + if (AddrRead < 0) or (AddrRead >= 8) then return 0 end + + return gate.LatchStore[AddrRead] or 0 + end, + reset = function(gate) + gate.LatchStore = {} + end, + label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset) + return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. + "\nReadAddr:"..AddrRead.." = "..Out + end, + ReadCell = function(dummy,gate,Address) + if (Address < 0) or (Address >= 8) then + return 0 + else + return gate.LatchStore[Address] or 0 + end + end, + WriteCell = function(dummy,gate,Address,value) + if (Address < 0) or (Address >= 8) then + return false + else + gate.LatchStore[Address] = value + return true + end + end, Upgrade = "gmod_wire_dynmemory" } GateActions["ram64"] = { name = "RAM(64 store)", + inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, + output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) + if (Reset > 0) then + gate.LatchStore = {} + end + + AddrRead = math.floor(tonumber(AddrRead)) + AddrWrite = math.floor(tonumber(AddrWrite)) + if (Clk > 0) then + if (AddrWrite < 64) then + gate.LatchStore[AddrWrite] = Data + end + end + return gate.LatchStore[AddrRead] or 0 + end, + reset = function(gate) + gate.LatchStore = {} + end, + label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset) + return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. + "\nReadAddr:"..AddrRead.." = "..Out + end, + ReadCell = function(dummy,gate,Address) + if (Address < 0) or (Address >= 64) then + return 0 + else + return gate.LatchStore[Address] or 0 + end + end, + WriteCell = function(dummy,gate,Address,value) + if (Address < 0) or (Address >= 64) then + return false + else + gate.LatchStore[Address] = value + return true + end + end, Upgrade = "gmod_wire_dynmemory" } GateActions["ram1k"] = { name = "RAM(1kb)", + inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, + output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) + if (Reset > 0) then + gate.LatchStore = {} + end + + AddrRead = math.floor(tonumber(AddrRead)) + AddrWrite = math.floor(tonumber(AddrWrite)) + if (Clk > 0) then + if (AddrWrite < 1024) then + gate.LatchStore[AddrWrite] = Data + end + end + return gate.LatchStore[AddrRead] or 0 + end, + reset = function(gate) + gate.LatchStore = {} + end, + label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset ) + return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. + "\nReadAddr:"..AddrRead.." = "..Out + end, + ReadCell = function(dummy,gate,Address) + if (Address < 0) or (Address >= 1024) then + return 0 + else + return gate.LatchStore[Address] or 0 + end + end, + WriteCell = function(dummy,gate,Address,value) + if (Address < 0) or (Address >= 1024) then + return false + else + gate.LatchStore[Address] = value + return true + end + end, Upgrade = "gmod_wire_dynmemory" } GateActions["ram32k"] = { name = "RAM(32kb)", + inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, + output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) + if (Reset > 0) then + gate.LatchStore = {} + end + + AddrRead = math.floor(tonumber(AddrRead)) + AddrWrite = math.floor(tonumber(AddrWrite)) + if (Clk > 0) then + if (AddrWrite < 32768) then + gate.LatchStore[AddrWrite] = Data + end + end + return gate.LatchStore[AddrRead] or 0 + end, + reset = function(gate) + gate.LatchStore = {} + end, + label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset ) + return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. + "\nReadAddr:"..AddrRead.." = "..Out + end, + ReadCell = function(dummy,gate,Address) + if (Address < 0) or (Address >= 32768) then + return 0 + else + return gate.LatchStore[Address] or 0 + end + end, + WriteCell = function(dummy,gate,Address,value) + if (Address < 0) or (Address >= 32768) then + return false + else + gate.LatchStore[Address] = value + return true + end + end, Upgrade = "gmod_wire_dynmemory" } GateActions["ram128k"] = { name = "RAM(128kb)", + inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" }, + output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset ) + if (Reset > 0) then + gate.LatchStore = {} + end + + AddrRead = math.floor(tonumber(AddrRead)) + AddrWrite = math.floor(tonumber(AddrWrite)) + if (Clk > 0) then + if (AddrWrite < 131072) then + gate.LatchStore[AddrWrite] = Data + end + end + return gate.LatchStore[AddrRead] or 0 + end, + reset = function(gate) + gate.LatchStore = {} + end, + label = function(Out, Clk, AddrRead, AddrWrite, Data) + return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.. + "\nReadAddr:"..AddrRead.." = "..Out + end, + ReadCell = function(dummy,gate,Address) + if (Address < 0) or (Address >= 131072) then + return 0 + else + return gate.LatchStore[Address] or 0 + end + end, + WriteCell = function(dummy,gate,Address,value) + if (Address < 0) or (Address >= 131072) then + return false + else + gate.LatchStore[Address] = value + return true + end + end, Upgrade = "gmod_wire_dynmemory" } GateActions["ram64x64"] = { name = "RAM(64x64 store)", + inputs = { "Clk", "AddrReadX", "AddrReadY", "AddrWriteX", "AddrWriteY", "Data", "Reset" }, + output = function(gate, Clk, AddrReadX, AddrReadY, AddrWriteX, AddrWriteY, Data, Reset ) + if (Reset > 0) then + gate.LatchStore = {} + end + + AddrReadX = math.floor(tonumber(AddrReadX)) + AddrReadY = math.floor(tonumber(AddrReadY)) + AddrWriteX = math.floor(tonumber(AddrWriteX)) + AddrWriteY = math.floor(tonumber(AddrWriteY)) + if (Clk > 0) then + if (AddrWriteX >= 0) and (AddrWriteX < 64) or (AddrWriteY >= 0) and (AddrWriteY < 64) then + gate.LatchStore[AddrWriteX + AddrWriteY*64] = Data + end + end + + if (AddrReadX < 0) or (AddrReadX >= 64) or (AddrReadY < 0) or (AddrReadY >= 64) then + return 0 + end + + return gate.LatchStore[AddrReadX + AddrReadY*64] or 0 + end, + reset = function(gate) + gate.LatchStore = {} + end, + label = function(Out, Clk, AddrReadX, AddrReadY, AddrWriteX, AddrWriteY, Data, Reset) + return "WriteAddr:"..AddrWriteX..", "..AddrWriteY.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset.. + "\nReadAddr:"..AddrReadX..", "..AddrReadY.." = "..Out + end, + ReadCell = function(dummy,gate,Address) + if (Address < 0) or (Address >= 4096) then + return 0 + else + return gate.LatchStore[Address] or 0 + end + end, + WriteCell = function(dummy,gate,Address,value) + if (Address < 0) or (Address >= 4096) then + return false + else + gate.LatchStore[Address] = value + return true + end + end, Upgrade = "gmod_wire_dynmemory" } From 12ecf4c96bfc69735174d261a83f41107e92bd8b Mon Sep 17 00:00:00 2001 From: Bilbard Date: Sun, 12 Jul 2026 20:49:52 -0600 Subject: [PATCH 6/8] Size output --- lua/entities/gmod_wire_dynmemory.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lua/entities/gmod_wire_dynmemory.lua b/lua/entities/gmod_wire_dynmemory.lua index 2c0a6c0245..a9fceadc8d 100644 --- a/lua/entities/gmod_wire_dynmemory.lua +++ b/lua/entities/gmod_wire_dynmemory.lua @@ -13,7 +13,7 @@ function ENT:Initialize() self.Inputs = Wire_CreateInputs(self, {"Clk"}) - self.Outputs = Wire_CreateOutputs(self, {"Out"}) + self.Outputs = Wire_CreateOutputs(self, {"Out", "Size"}) self.Size = 1 self.Memory = {} @@ -104,6 +104,8 @@ function ENT:Setup(size, wom, bifurcate, legacy) self:SetOverlayText(sstr .. (self.WOM == true and " Write-Only" or "") .. " RAM" .. (self.Size >= 1024 and " (" .. self.Size .. " bytes)" or "") .. (legacy and " (Legacy)" or "") ) + WireLib.TriggerOutput(self, "Size", self.Size) + self.Legacy = legacy end From d59683fae47fd65d9ac32741790376a842f17682 Mon Sep 17 00:00:00 2001 From: Bilbard Date: Thu, 16 Jul 2026 18:55:43 -0600 Subject: [PATCH 7/8] Lint --- lua/entities/gmod_wire_dynmemory.lua | 4 ++-- lua/wire/gates/memory.lua | 2 +- lua/wire/stools/dynmemory.lua | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lua/entities/gmod_wire_dynmemory.lua b/lua/entities/gmod_wire_dynmemory.lua index a9fceadc8d..80edd22945 100644 --- a/lua/entities/gmod_wire_dynmemory.lua +++ b/lua/entities/gmod_wire_dynmemory.lua @@ -157,7 +157,7 @@ end function ENT:ReadCell(Address) Address = math.floor(tonumber(Address)) - if self.WOM or (Address < 0 || Address >= self.Size) then + if self.WOM or Address < 0 or Address >= self.Size then return 0 end return self.Memory[Address] @@ -165,7 +165,7 @@ end function ENT:WriteCell(Address, Value) Address = math.floor(tonumber(Address)) - if (Address < 0 || Address >= self.Size) then + if Address < 0 or Address >= self.Size then return false end self.Memory[Address] = Value or 0 diff --git a/lua/wire/gates/memory.lua b/lua/wire/gates/memory.lua index 5e15f1f608..4344b97432 100644 --- a/lua/wire/gates/memory.lua +++ b/lua/wire/gates/memory.lua @@ -407,7 +407,7 @@ GateActions["udcounter"] = { local lClk = (Clk > 0) local lReset = (Reset > 0) if ((gate.PrevInc ~= lInc or gate.PrevDec ~= lDec or gate.PrevClk ~= lClk) and lClk) then - if (lInc) and (not lDec) and (not lReset) then + if lInc and not lDec and not lReset then gate.countStore = (gate.countStore or 0) + 1 elseif (not lInc) and (lDec) and (not lReset) then gate.countStore = (gate.countStore or 0) - 1 diff --git a/lua/wire/stools/dynmemory.lua b/lua/wire/stools/dynmemory.lua index 2ed40a3d75..9c8802be8d 100644 --- a/lua/wire/stools/dynmemory.lua +++ b/lua/wire/stools/dynmemory.lua @@ -63,9 +63,9 @@ function TOOL:RightClick(trace) if (trace.Entity and trace.Entity:IsValid()) then if (trace.Entity:GetClass() == "gmod_wire_dynmemory") then - self:GetOwner():ConCommand('wire_dynmemory_size "'..trace.Entity.Size..'"\n') - self:GetOwner():ConCommand('wire_dynmemory_wom "'..(trace.Entity.WOM and "1" or "0")..'"\n') - self:GetOwner():ConCommand('wire_dynmemory_bifurcate "'..(trace.Entity.Bifurcate and "1" or "0")..'"\n') + self:GetOwner():ConCommand("wire_dynmemory_size "..trace.Entity.Size.."\n") + self:GetOwner():ConCommand("wire_dynmemory_wom "..(trace.Entity.WOM and "1" or "0").."\n") + self:GetOwner():ConCommand("wire_dynmemory_bifurcate "..(trace.Entity.Bifurcate and "1" or "0").."\n") return true end end From e5f47a75502ea82003006383b7674637cc0eec3f Mon Sep 17 00:00:00 2001 From: Bilbard Date: Sat, 18 Jul 2026 20:01:27 -0600 Subject: [PATCH 8/8] Actions on trigger, not think --- lua/entities/gmod_wire_dynmemory.lua | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lua/entities/gmod_wire_dynmemory.lua b/lua/entities/gmod_wire_dynmemory.lua index 80edd22945..3a5fe85463 100644 --- a/lua/entities/gmod_wire_dynmemory.lua +++ b/lua/entities/gmod_wire_dynmemory.lua @@ -105,37 +105,18 @@ function ENT:Setup(size, wom, bifurcate, legacy) self:SetOverlayText(sstr .. (self.WOM == true and " Write-Only" or "") .. " RAM" .. (self.Size >= 1024 and " (" .. self.Size .. " bytes)" or "") .. (legacy and " (Legacy)" or "") ) WireLib.TriggerOutput(self, "Size", self.Size) + self:CalcOutput() self.Legacy = legacy end -function ENT:Think() - if self.Bifurcate then - if self.Clk and self.AddrWrite >= 0 and self.AddrWrite < self.BifurcateMagic and self.AddrWriteY >= 0 and self.AddrWriteY < self.BifurcateMagic then - self:WriteCell(self.AddrWrite + self.AddrWriteY * self.BifurcateMagic, self.Data) - end - if not self.WOM and self.AddrRead >= 0 and self.AddrRead < self.BifurcateMagic and self.AddrReadY >= 0 and self.AddrReadY < self.BifurcateMagic then - WireLib.TriggerOutput(self, "Out", self.Memory[self.AddrRead + self.AddrReadY * self.BifurcateMagic]) - end - else - if self.Clk and self.AddrWrite < self.Size and self.AddrWrite >= 0 then - self:WriteCell(self.AddrWrite, self.Data) - end - if not self.WOM and self.AddrRead < self.Size and self.AddrRead >= 0 then - WireLib.TriggerOutput(self, "Out", self.Memory[self.AddrRead]) - end - end - self:NextThink(CurTime() + 0.02) --same as gate ent - return true -end - --[[function ENT:SetPersistent(val) self.Persistent = val or self.Persistent end]] function ENT:TriggerInput(iname, Value) if (iname == "Reset") then - if (Value == 1) then + if (Value > 0) then for i=0, self.Size - 1 do self.Memory[i] = 0 end @@ -153,6 +134,25 @@ function ENT:TriggerInput(iname, Value) elseif (iname == "Clk") then self.Clk = Value > 0 end + self:CalcOutput() +end + +function ENT:CalcOutput() + if self.Bifurcate then + if self.Clk and self.AddrWrite >= 0 and self.AddrWrite < self.BifurcateMagic and self.AddrWriteY >= 0 and self.AddrWriteY < self.BifurcateMagic then + self:WriteCell(self.AddrWrite + self.AddrWriteY * self.BifurcateMagic, self.Data) + end + if not self.WOM and self.AddrRead >= 0 and self.AddrRead < self.BifurcateMagic and self.AddrReadY >= 0 and self.AddrReadY < self.BifurcateMagic then + WireLib.TriggerOutput(self, "Out", self.Memory[self.AddrRead + self.AddrReadY * self.BifurcateMagic]) + end + else + if self.Clk and self.AddrWrite < self.Size and self.AddrWrite >= 0 then + self:WriteCell(self.AddrWrite, self.Data) + end + if not self.WOM and self.AddrRead < self.Size and self.AddrRead >= 0 then + WireLib.TriggerOutput(self, "Out", self.Memory[self.AddrRead]) + end + end end function ENT:ReadCell(Address)