1190 lines
64 KiB
Lua
1190 lines
64 KiB
Lua
--------------------------------------------------------------------------------
|
|
-- ZCPU utility & support code
|
|
--------------------------------------------------------------------------------
|
|
local INVALID_BREAKPOINT_IP = 2e7
|
|
|
|
CPULib = CPULib or {}
|
|
if CLIENT then
|
|
-- Sourcecode available as compiled binary
|
|
CPULib.Source = ""
|
|
-- Compiled binary
|
|
CPULib.Buffer = {}
|
|
|
|
-- Sourcecode currently being compiled
|
|
CPULib.CurrentSource = ""
|
|
-- Buffer currently being written
|
|
CPULib.CurrentBuffer = {}
|
|
|
|
-- State variables
|
|
CPULib.Compiling = false
|
|
CPULib.Uploading = false
|
|
CPULib.ServerUploading = false
|
|
|
|
-- Debugger
|
|
CPULib.DebuggerAttached = false
|
|
CPULib.Debugger = {}
|
|
CPULib.Debugger.Variables = {}
|
|
CPULib.Debugger.SourceTab = nil
|
|
|
|
-- Reset on recompile
|
|
CPULib.Debugger.MemoryVariableByIndex = {}
|
|
CPULib.Debugger.MemoryVariableByName = {}
|
|
CPULib.Debugger.Labels = {}
|
|
CPULib.Debugger.PositionByPointer = {}
|
|
CPULib.Debugger.PointersByLine = {}
|
|
|
|
CPULib.Debugger.Breakpoint = {}
|
|
|
|
-- Convars to control CPULib
|
|
local wire_cpu_upload_speed = CreateClientConVar("wire_cpu_upload_speed",1000,false,false)
|
|
local wire_cpu_compile_speed = CreateClientConVar("wire_cpu_compile_speed",256,false,false)
|
|
local wire_cpu_show_all_registers = CreateClientConVar("wire_cpu_show_all_registers",0,false,false)
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Request compiling specific sourcecode
|
|
function CPULib.Compile(source,fileName,successCallback,errorCallback,targetPlatform)
|
|
-- Stop any compile/upload process that is running right now
|
|
timer.Remove("cpulib_compile")
|
|
timer.Remove("cpulib_upload")
|
|
CPULib.Uploading = false
|
|
|
|
-- See if compiled source is available
|
|
--if CPULib.Source == source then
|
|
-- successCallback()
|
|
-- return
|
|
--end
|
|
|
|
-- Remember the sourcecode being compiled
|
|
CPULib.CurrentSource = source
|
|
CPULib.CurrentBuffer = {}
|
|
|
|
-- Clear debugging info
|
|
CPULib.Debugger.MemoryVariableByIndex = {}
|
|
CPULib.Debugger.MemoryVariableByName = {}
|
|
CPULib.Debugger.Labels = {}
|
|
CPULib.Debugger.PositionByPointer = {}
|
|
CPULib.Debugger.PointersByLine = {}
|
|
CPULib.CPUName = nil
|
|
|
|
-- Start compiling the sourcecode
|
|
HCOMP:StartCompile(source,fileName or "source",CPULib.OnWriteByte,nil)
|
|
HCOMP.Settings.CurrentPlatform = targetPlatform or "CPU"
|
|
print("=== HL-ZASM High Level Assembly Compiler Output ==")
|
|
|
|
-- Initialize callbacks
|
|
CPULib.SuccessCallback = successCallback
|
|
CPULib.ErrorCallback = errorCallback
|
|
|
|
-- Run the timer
|
|
timer.Create("cpulib_compile",1/60,0,CPULib.OnCompileTimer)
|
|
CPULib.Compiling = true
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Make sure the file is opened in the tab
|
|
function CPULib.SelectTab(editor,fileName)
|
|
if not editor then return end
|
|
local editorType = string.lower(editor.EditorType)
|
|
local fullFileName = editorType.."chip\\"..fileName
|
|
|
|
if string.sub(fileName,1,7) == editorType.."chip" then
|
|
fullFileName = fileName
|
|
end
|
|
|
|
local sourceTab
|
|
for tab=1,editor:GetNumTabs() do
|
|
if editor:GetEditor(tab).chosenfile == fullFileName then
|
|
sourceTab = tab
|
|
end
|
|
end
|
|
|
|
if not sourceTab then
|
|
editor:LoadFile(fullFileName,true)
|
|
sourceTab = editor:GetActiveTabIndex()
|
|
else
|
|
editor:SetActiveTab(sourceTab)
|
|
end
|
|
|
|
return editor:GetEditor(sourceTab),sourceTab
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Request validating the code
|
|
function CPULib.Validate(editor,source,fileName)
|
|
CPULib.Compile(source,fileName,
|
|
function()
|
|
editor.C.Val:SetBGColor(50, 128, 20, 180)
|
|
editor.C.Val:SetFGColor(255, 255, 255, 128)
|
|
editor.C.Val:SetText(" Success, "..(HCOMP.WritePointer or "?").." bytes compiled.")
|
|
end,
|
|
function(error,errorPos)
|
|
editor.C.Val:SetBGColor(128, 20, 50, 180)
|
|
editor.C.Val:SetFGColor(255, 255, 255, 128)
|
|
editor.C.Val:SetText(" "..(error or "unknown error"))
|
|
|
|
if not errorPos then return end
|
|
|
|
local textEditor = CPULib.SelectTab(editor,errorPos.File)
|
|
if not textEditor then return end
|
|
textEditor:SetCaret({errorPos.Line,errorPos.Col})
|
|
end,editor.EditorType)
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Compiler callback
|
|
function CPULib.OnWriteByte(caller,address,byte)
|
|
CPULib.CurrentBuffer[address] = byte
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Compiler timer
|
|
function CPULib.OnCompileTimer()
|
|
local compile_speed = wire_cpu_compile_speed:GetFloat()
|
|
|
|
for _ = 1, compile_speed do
|
|
local status,result = pcall(HCOMP.Compile,HCOMP)
|
|
if not status then
|
|
print("==================================================")
|
|
if CPULib.ErrorCallback then CPULib.ErrorCallback(HCOMP.ErrorMessage or ("Internal error: "..result),HCOMP.ErrorPosition) end
|
|
timer.Remove("cpulib_compile")
|
|
CPULib.Compiling = false
|
|
|
|
return
|
|
elseif not result then
|
|
print("==================================================")
|
|
CPULib.Source = CPULib.CurrentSource
|
|
CPULib.Buffer = CPULib.CurrentBuffer
|
|
|
|
if CPULib.SuccessCallback then
|
|
CPULib.Debugger.Labels = HCOMP.DebugInfo.Labels
|
|
CPULib.Debugger.PositionByPointer = HCOMP.DebugInfo.PositionByPointer
|
|
CPULib.Debugger.PointersByLine = HCOMP.DebugInfo.PointersByLine
|
|
|
|
CPULib.SuccessCallback()
|
|
end
|
|
timer.Remove("cpulib_compile")
|
|
CPULib.Compiling = false
|
|
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Uploader timer
|
|
function CPULib.OnUploadTimer()
|
|
if not CPULib.RemainingData then return end
|
|
|
|
local upload_speed = wire_cpu_upload_speed:GetFloat() -- Number of index/value pairs to send (11 bytes each)
|
|
if game.SinglePlayer() then upload_speed = 5000 end
|
|
|
|
local iters = math.min(upload_speed, CPULib.RemainingUploadData)
|
|
net.Start("wire_cpulib_buffer")
|
|
net.WriteUInt(iters, 16)
|
|
for _ = 1, iters do
|
|
local index,value = next(CPULib.RemainingData)
|
|
CPULib.RemainingUploadData = CPULib.RemainingUploadData - 1
|
|
net.WriteUInt(index, 24)
|
|
net.WriteDouble(value or 0) -- 64bits, in case theres any float literals. Int21 is sufficient for all function calls/memory addresses
|
|
CPULib.RemainingData[index] = nil
|
|
end
|
|
if CPULib.RemainingUploadData <= 0 then
|
|
timer.Remove("cpulib_upload")
|
|
net.WriteBit(true) -- End
|
|
CPULib.Uploading = false
|
|
else
|
|
net.WriteBit(false) -- Keep going
|
|
end
|
|
net.SendToServer()
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Start upload
|
|
function CPULib.Upload(customBuffer)
|
|
-- Stop any upload in the progress
|
|
timer.Remove("cpulib_upload")
|
|
|
|
-- Send the buffer over to server
|
|
net.Start("wire_cpulib_bufferstart") net.WriteString(CPULib.CPUName or "") net.SendToServer()
|
|
|
|
CPULib.TotalUploadData = 0
|
|
CPULib.RemainingData = {}
|
|
if customBuffer then
|
|
for k,v in pairs(customBuffer) do
|
|
CPULib.RemainingData[k] = v
|
|
CPULib.TotalUploadData = CPULib.TotalUploadData + 1
|
|
end
|
|
else
|
|
for k,v in pairs(CPULib.Buffer) do
|
|
CPULib.RemainingData[k] = v
|
|
CPULib.TotalUploadData = CPULib.TotalUploadData + 1
|
|
end
|
|
end
|
|
|
|
CPULib.RemainingUploadData = CPULib.TotalUploadData
|
|
timer.Create("cpulib_upload",0.5,0,CPULib.OnUploadTimer)
|
|
CPULib.Uploading = true
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Get debug text for specific variable/function name
|
|
function CPULib.GetDebugPopupText(var)
|
|
if not var then return "" end
|
|
local csvar = string.upper(var)
|
|
|
|
if CPULib.Debugger.Variables[csvar] then
|
|
return var.." = "..CPULib.Debugger.Variables[csvar]
|
|
else
|
|
if CPULib.Debugger.Labels[csvar] then
|
|
if CPULib.Debugger.Labels[csvar].Offset then
|
|
if not CPULib.Debugger.MemoryVariableByName[csvar] then
|
|
CPULib.Debugger.MemoryVariableByName[csvar] = CPULib.Debugger.Labels[csvar].Offset
|
|
table.insert(CPULib.Debugger.MemoryVariableByIndex,csvar)
|
|
RunConsoleCommand("wire_cpulib_debugvar",#CPULib.Debugger.MemoryVariableByIndex,CPULib.Debugger.Labels[csvar].Offset)
|
|
end
|
|
return var.." = ..."
|
|
elseif CPULib.Debugger.Labels[csvar].Pointer then
|
|
return var.." = ptr "..CPULib.Debugger.Labels[csvar].Pointer
|
|
else
|
|
return var.." = cannot resolve"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Get debug text for specific variable/function name
|
|
CPULib.InterruptText = nil
|
|
function CPULib.GetDebugWindowText()
|
|
local result = {
|
|
"EAX = "..(CPULib.Debugger.Variables.EAX or "#####"),
|
|
"EBX = "..(CPULib.Debugger.Variables.EBX or "#####"),
|
|
"ECX = "..(CPULib.Debugger.Variables.ECX or "#####"),
|
|
"EDX = "..(CPULib.Debugger.Variables.EDX or "#####"),
|
|
"ESI = "..(CPULib.Debugger.Variables.ESI or "#####"),
|
|
"EDI = "..(CPULib.Debugger.Variables.EDI or "#####"),
|
|
"EBP = "..(CPULib.Debugger.Variables.EBP or "#####"),
|
|
"ESP = "..(CPULib.Debugger.Variables.ESP or "#####"),
|
|
}
|
|
|
|
table.insert(result,"")
|
|
local maxReg = 7
|
|
if wire_cpu_show_all_registers:GetFloat() == 1 then maxReg = 31 end
|
|
|
|
for reg=0,maxReg do
|
|
table.insert(result,"R"..reg.." = "..(CPULib.Debugger.Variables["R"..reg] or "#####"))
|
|
end
|
|
|
|
|
|
table.insert(result,"")
|
|
if CPULib.Debugger.Variables.IP == INVALID_BREAKPOINT_IP then
|
|
table.insert(result,"IP = #####")
|
|
else
|
|
table.insert(result,"IP = "..(CPULib.Debugger.Variables.IP or "#####"))
|
|
end
|
|
|
|
if CPULib.InterruptText then
|
|
table.insert(result,"")
|
|
table.insert(result,CPULib.InterruptText)
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Invalidate debugger data
|
|
function CPULib.InvalidateDebugger()
|
|
CPULib.InterruptText = nil
|
|
CPULib.Debugger.MemoryVariableByIndex = {}
|
|
CPULib.Debugger.MemoryVariableByName = {}
|
|
CPULib.Debugger.Breakpoint = {}
|
|
CPULib.Debugger.Variables = {}
|
|
CPULib.Debugger.FirstFile = nil
|
|
CPULib.DebugUpdateHighlights()
|
|
end
|
|
|
|
net.Receive("CPULib.InvalidateDebugger", function(netlen)
|
|
local state = net.ReadUInt(2) -- 0: No change just invalidate, 1: detach, 2: attach
|
|
if state == 1 then
|
|
CPULib.DebuggerAttached = false
|
|
GAMEMODE:AddNotify("CPU debugger detached!",NOTIFY_GENERIC,7)
|
|
elseif state == 2 then
|
|
CPULib.DebuggerAttached = true
|
|
GAMEMODE:AddNotify("CPU debugger has been attached!",NOTIFY_GENERIC,7)
|
|
end
|
|
CPULib.InvalidateDebugger()
|
|
end)
|
|
|
|
-- Get breakpoint at line
|
|
function CPULib.GetDebugBreakpoint(fileName,caretPos)
|
|
if not fileName or not caretPos then return nil end
|
|
return CPULib.Debugger.Breakpoint[caretPos[1]..":"..fileName]
|
|
end
|
|
|
|
-- Set breakpoint at line
|
|
-- FIXME: bug: can only set breakpoints in one file
|
|
function CPULib.SetDebugBreakpoint(fileName,caretPos,condition)
|
|
if not fileName or not caretPos then return nil end
|
|
if not condition then
|
|
CPULib.Debugger.Breakpoint[caretPos[1]..":"..fileName] = nil
|
|
if CPULib.Debugger.PointersByLine[caretPos[1]..":"..fileName] then
|
|
RunConsoleCommand("wire_cpulib_debugbreakpoint",CPULib.Debugger.PointersByLine[caretPos[1]..":"..fileName][1],0)
|
|
end
|
|
else
|
|
if CPULib.Debugger.PointersByLine[caretPos[1]..":"..fileName] then
|
|
CPULib.Debugger.Breakpoint[caretPos[1]..":"..fileName] = condition
|
|
RunConsoleCommand("wire_cpulib_debugbreakpoint",CPULib.Debugger.PointersByLine[caretPos[1]..":"..fileName][1],condition)
|
|
end
|
|
end
|
|
|
|
CPULib.DebugUpdateHighlights(true)
|
|
end
|
|
|
|
-- Update highlighted lines
|
|
function CPULib.DebugUpdateHighlights(dontForcePosition)
|
|
if ZCPU_Editor then
|
|
-- Highlight current position
|
|
local currentPosition = CPULib.Debugger.PositionByPointer[CPULib.Debugger.Variables.IP]
|
|
|
|
if currentPosition then
|
|
-- Clear all highlighted lines
|
|
for tab=1,ZCPU_Editor:GetNumTabs() do
|
|
ZCPU_Editor:GetEditor(tab):ClearHighlightedLines()
|
|
end
|
|
|
|
local textEditor = CPULib.SelectTab(ZCPU_Editor,currentPosition.File)
|
|
if textEditor then
|
|
textEditor:HighlightLine(currentPosition.Line,130,0,0,255)
|
|
if not dontForcePosition then
|
|
textEditor:SetCaret({currentPosition.Line,1}) --currentPosition.Col
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Highlight breakpoints
|
|
for key,breakpoint in pairs(CPULib.Debugger.Breakpoint) do
|
|
local line = tonumber(string.sub(key,1,(string.find(key,":") or 0) - 1)) or 0
|
|
local file = string.sub(key, (string.find(key,":") or 0) + 1)
|
|
|
|
local textEditor = CPULib.SelectTab(ZCPU_Editor,file)
|
|
if textEditor then
|
|
if currentPosition and (currentPosition.Line == line) then
|
|
if breakpoint == true then
|
|
textEditor:HighlightLine(line,130,70,20,255)
|
|
else
|
|
textEditor:HighlightLine(line,130,20,70,255)
|
|
end
|
|
else
|
|
if breakpoint == true then
|
|
textEditor:HighlightLine(line,0,70,20,255)
|
|
else
|
|
textEditor:HighlightLine(line,0,20,70,255)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Debug data arrived from server
|
|
function CPULib.OnDebugData_Registers(um)
|
|
CPULib.Debugger.Variables.IP = um:ReadFloat()
|
|
CPULib.Debugger.Variables.EAX = um:ReadFloat()
|
|
CPULib.Debugger.Variables.EBX = um:ReadFloat()
|
|
CPULib.Debugger.Variables.ECX = um:ReadFloat()
|
|
CPULib.Debugger.Variables.EDX = um:ReadFloat()
|
|
CPULib.Debugger.Variables.ESI = um:ReadFloat()
|
|
CPULib.Debugger.Variables.EDI = um:ReadFloat()
|
|
CPULib.Debugger.Variables.EBP = um:ReadFloat()
|
|
CPULib.Debugger.Variables.ESP = um:ReadFloat()
|
|
|
|
for reg=0,31 do
|
|
CPULib.Debugger.Variables["R"..reg] = um:ReadFloat()
|
|
end
|
|
|
|
CPULib.DebugUpdateHighlights()
|
|
end
|
|
usermessage.Hook("cpulib_debugdata_registers", CPULib.OnDebugData_Registers)
|
|
|
|
function CPULib.OnDebugData_Variables(um)
|
|
local startIndex = um:ReadShort()
|
|
for varIdx = startIndex,startIndex+59 do
|
|
if CPULib.Debugger.MemoryVariableByIndex[varIdx] then
|
|
CPULib.Debugger.Variables[CPULib.Debugger.MemoryVariableByIndex[varIdx]] = um:ReadFloat()
|
|
end
|
|
end
|
|
end
|
|
usermessage.Hook("cpulib_debugdata_variables", CPULib.OnDebugData_Variables)
|
|
|
|
function CPULib.OnDebugData_Interrupt(um)
|
|
local interruptNo,interruptParameter = um:ReadFloat(),um:ReadFloat()
|
|
CPULib.InterruptText = "Error #"..interruptNo.. " ["..interruptParameter.."]"
|
|
end
|
|
usermessage.Hook("cpulib_debugdata_interrupt", CPULib.OnDebugData_Interrupt)
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Show ZCPU/ZGPU documentation
|
|
CPULib.HandbookWindow = nil
|
|
|
|
function CPULib.ShowDocumentation(platform)
|
|
local w = ScrW() * 2/3
|
|
local h = ScrH() * 2/3
|
|
local browserWindow = vgui.Create("DFrame")
|
|
browserWindow:SetTitle("Documentation")
|
|
browserWindow:SetPos((ScrW() - w)/2, (ScrH() - h)/2)
|
|
browserWindow:SetSize(w,h)
|
|
browserWindow:MakePopup()
|
|
|
|
local browser = vgui.Create("DHTML",browserWindow)
|
|
browser:SetPos(10, 25)
|
|
browser:SetSize(w - 20, h - 35)
|
|
|
|
browser:OpenURL("http://wiki.wiremod.com/wiki/Category:ZCPU_Handbook")
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if SERVER then
|
|
util.AddNetworkString("CPULib.ServerUploading")
|
|
------------------------------------------------------------------------------
|
|
-- Data received from server
|
|
CPULib.DataBuffer = {}
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Set this entity as a receiver for networked upload
|
|
function CPULib.SetUploadTarget(entity,player)
|
|
CPULib.DataBuffer[player:UserID()] = {
|
|
Entity = entity,
|
|
Player = player,
|
|
Data = {},
|
|
}
|
|
end
|
|
|
|
util.AddNetworkString("wire_cpulib_bufferstart")
|
|
net.Receive("wire_cpulib_bufferstart", function(netlen, player)
|
|
local Buffer = CPULib.DataBuffer[player:UserID()]
|
|
if (not Buffer) or (Buffer.Player ~= player) then return end
|
|
if not IsValid(Buffer.Entity) then return end
|
|
|
|
net.Start("CPULib.ServerUploading") net.WriteBit(true) net.Send(player)
|
|
if Buffer.Entity:GetClass() == "gmod_wire_cpu" then
|
|
Buffer.Entity:SetCPUName(net.ReadString())
|
|
end
|
|
end)
|
|
|
|
-- Concommand to send a single stream of bytes
|
|
util.AddNetworkString("wire_cpulib_buffer")
|
|
net.Receive("wire_cpulib_buffer", function(netlen, player)
|
|
local Buffer = CPULib.DataBuffer[player:UserID()]
|
|
if (not Buffer) or (Buffer.Player ~= player) then return end
|
|
if not Buffer.Entity then return end
|
|
|
|
for _ = 1, net.ReadUInt(16) do
|
|
Buffer.Data[net.ReadUInt(24)] = net.ReadDouble()
|
|
end
|
|
|
|
if net.ReadBit() ~= 0 then -- We're done!
|
|
CPULib.DataBuffer[player:UserID()] = nil
|
|
net.Start("CPULib.ServerUploading") net.WriteBit(false) net.Send(player)
|
|
|
|
if Buffer.Entity:GetClass() == "gmod_wire_cpu" then
|
|
Buffer.Entity:FlashData(Buffer.Data)
|
|
elseif Buffer.Entity:GetClass() == "gmod_wire_dhdd" then
|
|
for k,v in pairs(Buffer.Data) do
|
|
Buffer.Entity.Memory[k] = v
|
|
end
|
|
Buffer.Entity:ShowOutputs()
|
|
elseif (Buffer.Entity:GetClass() == "gmod_wire_gpu") or (Buffer.Entity:GetClass() == "gmod_wire_spu") then
|
|
Buffer.Entity:WriteCell(65535,0)
|
|
if Buffer.Entity.WriteCell then
|
|
for k,v in pairs(Buffer.Data) do
|
|
Buffer.Entity:WriteCell(k,v)
|
|
end
|
|
end
|
|
Buffer.Entity:WriteCell(65535,Buffer.Entity.Clk)
|
|
Buffer.Entity:WriteCell(65534,1)
|
|
else
|
|
if Buffer.Entity.WriteCell then
|
|
for k,v in pairs(Buffer.Data) do
|
|
Buffer.Entity:WriteCell(k,v)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
------------------------------------------------------------------------------
|
|
-- 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)
|
|
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
|
|
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)
|
|
CPULib.SendDebugData(entity.VM,CPULib.DebuggerData[player:UserID()].MemPointers,player)
|
|
end
|
|
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
|
|
end
|
|
end
|
|
end
|
|
|
|
CPULib.DebuggerData[player:UserID()] = {
|
|
Entity = entity,
|
|
Player = player,
|
|
MemPointers = {},
|
|
PreviousUpdateTime = CurTime(),
|
|
}
|
|
end
|
|
|
|
-- Log debug interrupt
|
|
function CPULib.DebugLogInterrupt(player,interruptNo,interruptParameter,isExternal,cascadeInterrupt)
|
|
local umsgrp = RecipientFilter()
|
|
umsgrp:AddPlayer(player)
|
|
|
|
umsg.Start("cpulib_debugdata_interrupt", umsgrp)
|
|
umsg.Float(interruptNo)
|
|
umsg.Float(interruptParameter)
|
|
umsg.End()
|
|
end
|
|
|
|
-- Send debug log entry to client
|
|
function CPULib.SendDebugLogEntry(player,text)
|
|
--
|
|
end
|
|
|
|
-- Send debugging data to client
|
|
function CPULib.SendDebugData(VM,MemPointers,Player,onlyMemPointers)
|
|
local umsgrp = RecipientFilter()
|
|
umsgrp:AddPlayer(Player)
|
|
|
|
if not onlyMemPointers then
|
|
umsg.Start("cpulib_debugdata_registers", umsgrp)
|
|
umsg.Float(VM.IP)
|
|
umsg.Float(VM.EAX)
|
|
umsg.Float(VM.EBX)
|
|
umsg.Float(VM.ECX)
|
|
umsg.Float(VM.EDX)
|
|
umsg.Float(VM.ESI)
|
|
umsg.Float(VM.EDI)
|
|
umsg.Float(VM.EBP)
|
|
umsg.Float(VM.ESP)
|
|
|
|
for reg = 0,31 do
|
|
umsg.Float(VM["R"..reg])
|
|
end
|
|
umsg.End()
|
|
end
|
|
|
|
if MemPointers then
|
|
for msgIdx=0,math.floor(#MemPointers/60) do
|
|
umsg.Start("cpulib_debugdata_variables", umsgrp)
|
|
umsg.Short(msgIdx*60)
|
|
for varIdx=msgIdx*60,msgIdx*60+59 do
|
|
if MemPointers[varIdx] then
|
|
umsg.Float(VM:ReadCell(MemPointers[varIdx]))
|
|
end
|
|
end
|
|
umsg.End()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Concommand to step forward
|
|
concommand.Add("wire_cpulib_debugstep", function(player, command, args)
|
|
local Data = CPULib.DebuggerData[player:UserID()]
|
|
if (not Data) or (Data.Player ~= player) then return end
|
|
if not IsValid(Data.Entity) then return end
|
|
|
|
if not args[1] then -- Step forward
|
|
Data.Entity.VM:Step(1)
|
|
Data.Entity.VMStopped = true
|
|
else -- Run until instruction
|
|
Data.Entity.VMStopped = false
|
|
Data.Entity:NextThink(CurTime())
|
|
|
|
Data.Entity.LastInstruction = tonumber(args[1]) or 0
|
|
Data.Entity.OnLastInstruction = function()
|
|
Data.Entity.LastInstruction = nil
|
|
Data.Entity.OnLastInstruction = nil
|
|
CPULib.SendDebugData(Data.Entity.VM,Data.MemPointers,Data.Player)
|
|
end
|
|
end
|
|
CPULib.SendDebugData(Data.Entity.VM,Data.MemPointers,Data.Player)
|
|
end)
|
|
|
|
-- Concommand to run till breakpoint
|
|
concommand.Add("wire_cpulib_debugrun", function(player, command, args)
|
|
local Data = CPULib.DebuggerData[player:UserID()]
|
|
if (not Data) or (Data.Player ~= player) then return end
|
|
if not IsValid(Data.Entity) then return end
|
|
|
|
-- Send a fake update that messes up line pointer
|
|
local tempIP = Data.Entity.VM.IP
|
|
Data.Entity.VM.IP = INVALID_BREAKPOINT_IP
|
|
CPULib.SendDebugData(Data.Entity.VM,nil,Data.Player)
|
|
Data.Entity.VM.IP = tempIP
|
|
|
|
Data.Entity.Clk = true
|
|
Data.Entity:NextThink(CurTime())
|
|
end)
|
|
|
|
-- Concommand to reset
|
|
concommand.Add("wire_cpulib_debugreset", function(player, command, args)
|
|
local Data = CPULib.DebuggerData[player:UserID()]
|
|
if (not Data) or (Data.Player ~= player) then return end
|
|
if not IsValid(Data.Entity) then return end
|
|
|
|
Data.Entity.VM:Reset()
|
|
CPULib.SendDebugData(Data.Entity.VM,Data.MemPointers,Data.Player)
|
|
end)
|
|
|
|
-- Concommand to add a variable
|
|
concommand.Add("wire_cpulib_debugvar", function(player, command, args)
|
|
local Data = CPULib.DebuggerData[player:UserID()]
|
|
if (not Data) or (Data.Player ~= player) then return end
|
|
if not IsValid(Data.Entity) then return end
|
|
|
|
Data.MemPointers[tonumber(args[1]) or 0] = tonumber(args[2])
|
|
CPULib.SendDebugData(Data.Entity.VM,Data.MemPointers,Data.Player,true)
|
|
end)
|
|
|
|
-- Concommand to set a debug breakpoint
|
|
concommand.Add("wire_cpulib_debugbreakpoint", function(player, command, args)
|
|
local Data = CPULib.DebuggerData[player:UserID()]
|
|
if (not Data) or (Data.Player ~= player) then return end
|
|
if not IsValid(Data.Entity) then return end
|
|
|
|
if tonumber(args[2]) == 0 then
|
|
Data.Entity.BreakpointInstructions[tonumber(args[1]) or 0] = nil
|
|
else
|
|
Data.Entity.BreakpointInstructions[tonumber(args[1]) or 0] = true
|
|
end
|
|
end)
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Create a new virtual machine
|
|
--------------------------------------------------------------------------------
|
|
function CPULib.VirtualMachine()
|
|
-- Create new instance of the VM
|
|
include("wire/zvm/zvm_core.lua")
|
|
|
|
-- Remove from global scope
|
|
local newVM = ZVM
|
|
ZVM = nil
|
|
return newVM
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Generate a serial number
|
|
--------------------------------------------------------------------------------
|
|
local sessionBase, sessionDate
|
|
function CPULib.GenerateSN(entityType)
|
|
local currentDate = os.date("*t")
|
|
|
|
local SNDate = (currentDate.year-2007)*500+(currentDate.yday)
|
|
if (not sessionBase) or (SNDate ~= sessionDate) then
|
|
sessionBase = math.floor(math.random()*99999)
|
|
sessionDate = SNDate
|
|
else
|
|
sessionBase = sessionBase + 1
|
|
end
|
|
|
|
if entityType == "CPU" then
|
|
return sessionBase + 100000 + SNDate*1000000
|
|
elseif entityType == "SPU" then
|
|
return sessionBase + 200000 + SNDate*1000000
|
|
elseif entityType == "GPU" then
|
|
return sessionBase + 300000 + SNDate*1000000
|
|
elseif entityType == "UNK" then
|
|
return sessionBase + 700000 + SNDate*1000000
|
|
end
|
|
end
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Get device type
|
|
--------------------------------------------------------------------------------
|
|
local DeviceType = {
|
|
["gmod_wire_extbus"] = 2,
|
|
["gmod_wire_addressbus"] = 3,
|
|
["gmod_wire_cpu"] = 4,
|
|
["gmod_wire_gpu"] = 5,
|
|
["gmod_wire_spu"] = 6,
|
|
["gmod_wire_hdd"] = 7,
|
|
["gmod_wire_dhdd"] = 8,
|
|
["gmod_wire_datarate"] = 9,
|
|
["gmod_wire_cd_ray"] = 10,
|
|
["gmod_wire_consolescreen"] = 11,
|
|
["gmod_wire_digitalscreen"] = 12,
|
|
["gmod_wire_dataplug"] = 13,
|
|
["gmod_wire_datasocket"] = 14,
|
|
["gmod_wire_keyboard"] = 15,
|
|
["gmod_wire_oscilloscope"] = 16,
|
|
["gmod_wire_soundemitter"] = 17,
|
|
["gmod_wire_value"] = 18,
|
|
["gmod_wire_dataport"] = 19,
|
|
["gmod_wire_gate"] = 20,
|
|
}
|
|
|
|
function CPULib.GetDeviceType(class)
|
|
return DeviceType[class] or 1
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Columns in the instruction set reference table:
|
|
-- Opc - Instruction number
|
|
-- Mnemonic - Symbolic mnemonic (uppercase). Can be "RESERVED"
|
|
-- Ops - Number of operands
|
|
-- Version - Minimum CPU version required
|
|
-- Flags - Several or none of the following flags:
|
|
-- W1: single-operand opcode which writes 1st operand
|
|
-- R0: runlevel 0 opcode (privileged opcode)
|
|
-- OB: obsolete/should not be used
|
|
-- UB: unconditional branching instruction
|
|
-- CB: conditional branching instruction
|
|
-- TR: trigonometric syntax operand
|
|
-- OL: old mnemonic for the instruction
|
|
-- BL: instruction supports block prefix
|
|
-- Op1 - operand 1 name
|
|
-- Op2 - operand 2 name
|
|
|
|
-- Possible operand names:
|
|
-- X,Y: arbitrary integer or floating-point value
|
|
-- PTR: 48-bit pointer into memory
|
|
-- CS: 48-bit pointer into memory, new value of CS segment
|
|
-- IDX: unsigned integer index into internal processor table
|
|
-- PAGE: unsigned integer page number (each page is 128 bytes)
|
|
-- PORT: unsigned 47-bit integer port number
|
|
-- BIT: integer between 0 and 47
|
|
-- INTR: interrupt nubmer (integer between 0 and 255)
|
|
-- SIZE: unsigned 47-bit integer memory block size
|
|
--
|
|
-- COLOR: 4-byte color
|
|
-- VEC2F: 2-byte vector
|
|
--
|
|
-- INT: 48-bit signed integer
|
|
|
|
CPULib.InstructionTable = {}
|
|
local W1,R0,OB,UB,CB,TR,OL,BL = 1,2,4,8,16,32,64,128
|
|
|
|
local function Bit(x,n) return (math.floor(x / n) % 2) == 1 end
|
|
local function Entry(Set,Opc,Mnemonic,Ops,Version,Flags,Op1,Op2,Reference)
|
|
table.insert(CPULib.InstructionTable,
|
|
{ Set = Set,
|
|
Opcode = Opc,
|
|
Mnemonic = Mnemonic,
|
|
OperandCount = Ops,
|
|
MinimumVersion = Version,
|
|
Operand1 = Op1,
|
|
Operand2 = Op2,
|
|
Reference = Reference,
|
|
|
|
WritesFirstOperand = Bit(Flags,W1),
|
|
Privileged = Bit(Flags,R0),
|
|
Obsolete = Bit(Flags,OB),
|
|
UnconditionalBranching = Bit(Flags,UB),
|
|
ConditionalBranching = Bit(Flags,CB),
|
|
Trigonometric = Bit(Flags,TR),
|
|
Old = Bit(Flags,OL),
|
|
BlockPrefix = Bit(Flags,BL),
|
|
})
|
|
end
|
|
local function CPU(...) Entry("CPU",...) end
|
|
local function GPU(...) Entry("GPU",...) end
|
|
local function VEX(...) Entry("VEX",...) end
|
|
local function SPU(...) Entry("SPU",...) end
|
|
|
|
|
|
-------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- Zyelios CPU/GPU/SPU instruction set reference table
|
|
-------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--- Opc Mnemonic ------- Ops Version Flags ---- Op1 ---- Op2 ---- Reference ------------------------------------------------------------------
|
|
CPU(000, "RESERVED", 0, 0.00, 0, "", "", "Stop processor execution")
|
|
CPU(001, "JNE", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is not equal")
|
|
CPU(001, "JNZ", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is not zero")
|
|
CPU(002, "JMP", 1, 1.00, UB, "PTR", "", "Jump to PTR")
|
|
CPU(003, "JG", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is greater")
|
|
CPU(003, "JNLE", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is not less or equal")
|
|
CPU(004, "JGE", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is greater or equal")
|
|
CPU(004, "JNL", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is not less")
|
|
CPU(005, "JL", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is less")
|
|
CPU(005, "JNGE", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is not greater or equal")
|
|
CPU(006, "JLE", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is less or equal")
|
|
CPU(006, "JNG", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is not greater")
|
|
CPU(007, "JE", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is equal")
|
|
CPU(007, "JZ", 1, 1.00, CB, "PTR", "", "Jump to PTR if result is zero")
|
|
CPU(008, "CPUID", 1, 1.00, 0, "IDX", "", "Write processor information variable IDX into EAX register")
|
|
CPU(009, "PUSH", 1, 1.00, 0, "X", "", "Push X onto processor stack")
|
|
---- Dec 1 --------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(010, "ADD", 2, 1.00, 0, "X", "Y", "X = X + Y")
|
|
CPU(011, "SUB", 2, 1.00, 0, "X", "Y", "X = X - Y")
|
|
CPU(012, "MUL", 2, 1.00, 0, "X", "Y", "X = X * Y")
|
|
CPU(013, "DIV", 2, 1.00, 0, "X", "Y", "X = X / Y")
|
|
CPU(014, "MOV", 2, 1.00, 0, "X", "Y", "X = Y")
|
|
CPU(015, "CMP", 2, 1.00, 0, "X", "Y", "Compare X and Y. Use with conditional branching instructions")
|
|
CPU(016, "RD", 2, 1.00, R0+OB, "X", "PTR", "Read value from memory by pointer PTR")
|
|
CPU(017, "WD", 2, 1.00, R0+OB, "PTR", "Y", "Write value to memory by pointer PTR")
|
|
CPU(018, "MIN", 2, 1.00, 0, "X", "Y", "Set X to smaller value out of X and Y")
|
|
CPU(019, "MAX", 2, 1.00, 0, "X", "Y", "Set X to bigger value out of X and Y")
|
|
---- Dec 2 --------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(020, "INC", 1, 1.00, W1, "X", "", "Increase X by one")
|
|
CPU(021, "DEC", 1, 1.00, W1, "X", "", "Decrease X by one")
|
|
CPU(022, "NEG", 1, 1.00, W1, "X", "", "Change sign of X")
|
|
CPU(023, "RAND", 1, 1.00, W1, "X", "", "Set X to random value")
|
|
CPU(024, "LOOP", 1, 2.00, CB, "PTR", "", "Decrease ECX, and if ECX is not set to 0, jump to PTR")
|
|
CPU(024, "LOOPC", 1, 10.00, CB, "PTR", "", "Decrease ECX, and if ECX is not set to 0, jump to PTR")
|
|
CPU(025, "LOOPA", 1, 2.00, CB, "PTR", "", "Decrease EAX, and if EAX is not set to 0, jump to PTR")
|
|
CPU(026, "LOOPB", 1, 2.00, CB, "PTR", "", "Decrease EBX, and if EBX is not set to 0, jump to PTR")
|
|
CPU(027, "LOOPD", 1, 2.00, CB, "PTR", "", "Decrease EDX, and if EDX is not set to 0, jump to PTR")
|
|
CPU(028, "SPG", 1, 2.00, R0, "PAGE", "", "Make PAGE readonly")
|
|
CPU(029, "CPG", 1, 2.00, R0, "PAGE", "", "Make PAGE readable and writeable")
|
|
---- Dec 3---------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(030, "POP", 1, 1.00, 0, "X", "", "Pop value off stack and write it into X")
|
|
CPU(031, "CALL", 1, 1.00, UB, "PTR", "", "Call subroutine by address PTR")
|
|
CPU(032, "BNOT", 1, 1.00, W1, "INT", "", "Flip all bits in the integer number")
|
|
CPU(033, "FINT", 1, 1.00, W1, "X", "", "Force X to be an integer value")
|
|
CPU(034, "FRND", 1, 1.00, W1, "X", "", "Round X to the nearest integer value")
|
|
CPU(034, "RND", 1, 1.00, W1+OL, "X", "", "FRND")
|
|
CPU(035, "FFRAC", 1, 1.00, W1, "X", "", "Remove integer part of the X, leaving only the fractional part")
|
|
CPU(036, "FINV", 1, 1.00, W1, "X", "", "X = 1 / X")
|
|
CPU(037, "HALT", 1, 1.00, OB, "PORT", "", "Halt processor execution until PORT is written to")
|
|
CPU(038, "FSHL", 1, 2.00, W1, "X", "", "Multiply X by 2 (does not floor)")
|
|
CPU(039, "FSHR", 1, 2.00, W1, "X", "", "Divide X by 2 (does not floor)")
|
|
---- Dec 4 --------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(040, "RET", 0, 1.00, UB, "", "", "Return from a subroutine")
|
|
CPU(041, "IRET", 0, 2.00, UB, "", "", "Return from an interrupt")
|
|
CPU(042, "STI", 0, 2.00, R0, "", "", "Enable interrupt handling")
|
|
CPU(043, "CLI", 0, 2.00, R0, "", "", "Disable interrupt handling")
|
|
CPU(044, "STP", 0, 2.00, R0+OB, "", "", "Enable protected mode")
|
|
CPU(045, "CLP", 0, 2.00, R0+OB, "", "", "Disable protected mode")
|
|
CPU(046, "RESERVED", 0, 0.00, R0, "", "", "")
|
|
CPU(047, "RETF", 0, 1.00, UB, "", "", "Return from a far subroutine call")
|
|
CPU(048, "STEF", 0, 4.00, R0, "", "", "Enable extended mode")
|
|
CPU(049, "CLEF", 0, 4.00, R0, "", "", "Disable extended mode")
|
|
---- Dec 5 --------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(050, "AND", 2, 1.00, 0, "X", "Y", "Logical AND between X and Y")
|
|
CPU(051, "OR", 2, 1.00, 0, "X", "Y", "Logical OR between X and Y")
|
|
CPU(052, "XOR", 2, 1.00, 0, "X", "Y", "Logical XOR between X and Y")
|
|
CPU(053, "FSIN", 2, 1.00, TR, "X", "Y", "Write sine of X to Y")
|
|
CPU(054, "FCOS", 2, 1.00, TR, "X", "Y", "Write cosine of X to Y")
|
|
CPU(055, "FTAN", 2, 1.00, TR, "X", "Y", "Write tangent of X to Y")
|
|
CPU(056, "FASIN", 2, 1.00, TR, "X", "Y", "Write arcsine of X to Y")
|
|
CPU(057, "FACOS", 2, 1.00, TR, "X", "Y", "Write arccosine of X to Y")
|
|
CPU(058, "FATAN", 2, 1.00, TR, "X", "Y", "Write arctangent of X to Y")
|
|
CPU(059, "MOD", 2, 2.00, 0, "X", "Y", "Write remainder of X/Y to Y")
|
|
---- Dec 6 --------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(060, "BIT", 2, 2.00, 0, "INT", "BIT", "Test whether BIT of X is set. Use with conditional branching instructions")
|
|
CPU(061, "SBIT", 2, 2.00, 0, "INT", "BIT", "Set BIT of X")
|
|
CPU(062, "CBIT", 2, 2.00, 0, "INT", "BIT", "Clear BIT of X")
|
|
CPU(063, "TBIT", 2, 2.00, 0, "INT", "BIT", "Toggle BIT of X")
|
|
CPU(064, "BAND", 2, 2.00, 0, "INT", "INT", "Write result of binary AND between operands")
|
|
CPU(065, "BOR", 2, 2.00, 0, "INT", "INT", "Write result of binary OR between operands")
|
|
CPU(066, "BXOR", 2, 2.00, 0, "INT", "INT", "Write result of binary XOR between operands")
|
|
CPU(067, "BSHL", 2, 2.00, 0, "INT", "X", "Shift bits of INT left by X")
|
|
CPU(068, "BSHR", 2, 2.00, 0, "INT", "X", "Shift bits of INT right by X")
|
|
CPU(069, "JMPF", 2, 2.00, UB, "PTR", "CS", "Jump to PTR in code segment CS")
|
|
---- Dec 7 --------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(070, "NMIINT", 1, 4.00, R0+OL, "INTR", "", "EXTINT")
|
|
CPU(070, "EXTINT", 1, 10.00, R0, "INTR", "", "Call interrupt INTR as an external interrupt")
|
|
CPU(071, "CNE", 1, 2.00, CB, "PTR", "", "Call subrotine if result is not equal")
|
|
CPU(071, "CNZ", 1, 2.00, CB, "PTR", "", "Call subrotine if result is not zero")
|
|
CPU(072, "RESERVED", 1, 0.00, 0, "", "", "")
|
|
CPU(073, "CG", 1, 2.00, CB, "PTR", "", "Call subrotine if result is greater")
|
|
CPU(073, "CNLE", 1, 2.00, CB, "PTR", "", "Call subrotine if result is not less or equal")
|
|
CPU(074, "CGE", 1, 2.00, CB, "PTR", "", "Call subrotine if result is greater or equal")
|
|
CPU(074, "CNL", 1, 2.00, CB, "PTR", "", "Call subrotine if result is not less")
|
|
CPU(075, "CL", 1, 2.00, CB, "PTR", "", "Call subrotine if result is less")
|
|
CPU(075, "CNGE", 1, 2.00, CB, "PTR", "", "Call subrotine if result is not greater or equal")
|
|
CPU(076, "CLE", 1, 2.00, CB, "PTR", "", "Call subrotine if result is less or equal")
|
|
CPU(076, "CNG", 1, 2.00, CB, "PTR", "", "Call subrotine if result is not greater")
|
|
CPU(077, "CE", 1, 2.00, CB, "PTR", "", "Call subrotine if result is equal")
|
|
CPU(077, "CZ", 1, 2.00, CB, "PTR", "", "Call subrotine if result is zero")
|
|
CPU(078, "MCOPY", 1, 2.00, BL, "INT", "", "Copy INT bytes from array pointed by ESI to EDI")
|
|
CPU(079, "MXCHG", 1, 2.00, BL, "INT", "", "Swap INT bytes between two arrays pointed by ESI and EDI")
|
|
---- Dec 8 --------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(080, "FPWR", 2, 2.00, 0, "X", "Y", "Raise X to power Y")
|
|
CPU(081, "XCHG", 2, 2.00, 0, "X", "Y", "Swap X and Y")
|
|
CPU(082, "FLOG", 2, 2.00, OL, "X", "Y", "FLN")
|
|
CPU(082, "FLN", 2, 10.00, 0, "X", "Y", "Write logarithm (base e) of Y to X")
|
|
CPU(083, "FLOG10", 2, 2.00, 0, "X", "Y", "Write logarithm (base 10) of Y to X")
|
|
CPU(084, "IN", 2, 2.00, 0, "X", "PORT", "Input value from PORT to X")
|
|
CPU(085, "OUT", 2, 2.00, 0, "PORT", "Y", "Write X to PORT")
|
|
CPU(086, "FABS", 2, 2.00, TR, "X", "Y", "Write absolute value of Y to X")
|
|
CPU(087, "FSGN", 2, 2.00, TR, "X", "Y", "Write sign of Y to X")
|
|
CPU(088, "FEXP", 2, 2.00, TR, "X", "Y", "Write exponent of Y to X")
|
|
CPU(089, "CALLF", 2, 2.00, UB, "PTR", "CS", "Call subroutine by offset PTR in code segment CS")
|
|
---- Dec 9 --------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(090, "FPI", 1, 2.00, W1, "X", "", "Set X to precise value of PI (3.1415926..)")
|
|
CPU(091, "FE", 1, 2.00, W1, "X", "", "Set X to precise value of E (2.7182818..)")
|
|
CPU(092, "INT", 1, 2.00, 0, "INTR", "", "Call interrupt INTR")
|
|
CPU(093, "TPG", 1, 2.00, 0, "PAGE", "", "Test PAGE. Use branching instructions to test for zero on failure, non-zero if test passed.")
|
|
CPU(094, "FCEIL", 1, 2.00, W1, "X", "", "Rounds X up to the next integer")
|
|
CPU(095, "ERPG", 1, 2.00, R0, "PAGE", "", "Erase ROM page")
|
|
CPU(096, "WRPG", 1, 2.00, R0, "PAGE", "", "Copy RAM page into ROM page")
|
|
CPU(097, "RDPG", 1, 2.00, R0, "PAGE", "", "Read ROM page into RAM")
|
|
CPU(098, "TIMER", 1, 2.00, W1, "X", "", "Set X to value of the internal processor timer")
|
|
CPU(099, "LIDTR", 1, 2.00, R0, "PTR", "", "Set interrupt table pointer to PTR")
|
|
---- Dec 10 -------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(100, "RESERVED", 1, 0.00, R0, "", "", "")
|
|
CPU(101, "JNER", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is not equal")
|
|
CPU(101, "JNZR", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is not zero")
|
|
CPU(102, "JMPR", 1, 3.00, UB, "INT", "", "Relative jump INT bytes forward")
|
|
CPU(103, "JGR", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is greater")
|
|
CPU(103, "JNLER", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is not less or equal")
|
|
CPU(104, "JGER", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is greater or equal")
|
|
CPU(104, "JNLR", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is not less")
|
|
CPU(105, "JLR", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is less")
|
|
CPU(105, "JNGER", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is not greater or equal")
|
|
CPU(106, "JLER", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is less or equal")
|
|
CPU(106, "JNGR", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is not greater")
|
|
CPU(107, "JER", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is equal")
|
|
CPU(107, "JZR", 1, 3.00, CB, "INT", "", "Relative jump INT bytes forward if result is zero")
|
|
CPU(108, "LNEG", 1, 3.00, W1, "X", "", "Logically negate X")
|
|
CPU(109, "RESERVED", 1, 0.00, R0, "", "", "")
|
|
---- Dec 11 -------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(110, "NMIRET", 0, 2.00, R0+OL, "", "", "EXTRET")
|
|
CPU(110, "EXTRET", 0, 10.00, R0, "", "", "Return from an external interrupt")
|
|
CPU(111, "IDLE", 0, 4.00, R0, "", "", "Skip several processor cycles")
|
|
CPU(112, "NOP", 0, 5.00, 0, "", "", "Do nothing")
|
|
CPU(113, "RESERVED", 0, 0.00, 0, "", "", "")
|
|
CPU(114, "PUSHA", 0, 8.00, 0, "", "", "Push all general purpose registers to stack")
|
|
CPU(115, "POPA", 0, 8.00, 0, "", "", "Pop all general purpose registers off stack")
|
|
CPU(116, "STD2", 0, 10.00, R0, "", "", "Enable hardware debug mode")
|
|
CPU(117, "LEAVE", 0, 10.00, 0, "", "", "Leave subroutine stack frame")
|
|
CPU(118, "STM", 0, 10.00, R0, "", "", "Enable extended memory mode")
|
|
CPU(119, "CLM", 0, 10.00, R0, "", "", "Disable extended memory mode")
|
|
---- Dec 12 -------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(120, "CPUGET", 2, 5.00, R0, "X", "IDX", "Read internal processor register IDX")
|
|
CPU(121, "CPUSET", 2, 5.00, R0, "IDX", "Y", "Write internal processor register IDX")
|
|
CPU(122, "SPP", 2, 5.00, R0+BL, "PAGE", "IDX", "Set page flag IDX")
|
|
CPU(123, "CPP", 2, 5.00, R0+BL, "PAGE", "IDX", "Clear page flag IDX")
|
|
CPU(124, "SRL", 2, 5.00, R0+BL, "PAGE", "INT", "Set page runlevel to INT")
|
|
CPU(125, "CRL", 2, 5.00, R0, "X", "PAGE", "Write page runlevel to INT")
|
|
CPU(126, "LEA", 2, 5.00, 0, "X", "Y", "Load absolute address fetched by operand Y into X")
|
|
CPU(127, "BLOCK", 2, 6.00, 0, "PTR", "SIZE", "Make next instruction run on this block")
|
|
CPU(128, "CMPAND", 2, 6.00, 0, "X", "Y", "Compare X and Y, and logically combine with result of previous comparsion using AND")
|
|
CPU(129, "CMPOR", 2, 6.00, 0, "X", "Y", "Compare X and Y, and logically combine with result of previous comparsion using OR")
|
|
---- Dec 13 -------------------------------------------------------------------------------------------------------------------------------------
|
|
CPU(130, "MSHIFT", 2, 7.00, 0, "COUNT", "OFFSET","Shift (and rotate) data pointed by ESI by OFFSET bytes")
|
|
CPU(131, "SMAP", 2, 8.00, R0+BL, "PAGE1", "PAGE2", "Remap PAGE1 to physical page PAGE2")
|
|
CPU(132, "GMAP", 2, 8.00, R0, "X", "PAGE", "Read what physical page PAGE is mapped to")
|
|
CPU(133, "RSTACK", 2, 9.00, 0, "X", "IDX", "Read value from stack at offset IDX (from address SS+IDX)")
|
|
CPU(134, "SSTACK", 2, 9.00, 0, "IDX", "Y", "Write value to stack at offset IDX (to address SS+IDX)")
|
|
CPU(135, "ENTER", 1, 10.00, 0, "SIZE", "", "Enter stack frame and allocate SIZE bytes on stack for local variables")
|
|
CPU(136, "IRETP", 1, 2.00, R0, "PTBL", "", "Set PTBL, then return from an interrupt")
|
|
CPU(137, "EXTRETP", 1, 10.00, R0, "PTBL", "", "Set PTBL, then return from an external interrupt")
|
|
---- Dec 14 -- UNDEFINED ------------------------------------------------------------------------------------------------------------------------
|
|
CPU(140, "EXTRETA", 0, 11.00, R0, "", "", "Return from an external interrupt and restore R0-R31 registers")
|
|
CPU(141, "EXTRETPA", 1, 11.00, R0, "PTBL", "", "Set PTBL, then return from an external interrupt with restoring R0-R31 registers")
|
|
---- Dec 15 -- UNDEFINED ------------------------------------------------------------------------------------------------------------------------
|
|
---- Dec 16 -- UNDEFINED ------------------------------------------------------------------------------------------------------------------------
|
|
---- Dec 17 -- UNDEFINED ------------------------------------------------------------------------------------------------------------------------
|
|
---- Dec 18 -- UNDEFINED ------------------------------------------------------------------------------------------------------------------------
|
|
---- Dec 19 -- UNDEFINED ------------------------------------------------------------------------------------------------------------------------
|
|
---- Dec 20 -- Output buffer control ------------------------------------------------------------------------------------------------------------
|
|
GPU(200, "DTEST", 0, 1.0, 0, "", "", "Output a test pattern to screen")
|
|
GPU(200, "DRECT_TEST", 0, 0.5, OL, "", "", "DTEST")
|
|
GPU(201, "DEXIT", 0, 0.5, UB, "", "", "End execution of the current frame")
|
|
GPU(201, "DVSYNC", 0, 1.0, 0, "", "", "Wait until next frame (only in asynchronous thread)")
|
|
GPU(202, "DCLR", 0, 0.5, 0, "", "", "Clear screen color to black")
|
|
GPU(203, "DCLRTEX", 0, 0.5, 0, "", "", "Clear background with texture")
|
|
GPU(204, "DVXFLUSH", 0, 0.6, 0, "", "", "Flush current vertex buffer to screen")
|
|
GPU(205, "DVXCLEAR", 0, 0.6, 0, "", "", "Clear vertex buffer")
|
|
GPU(206, "DSETBUF_VX", 0, 1.0, 0, "", "", "Set frame buffer to vertex output")
|
|
GPU(207, "DSETBUF_SPR", 0, 1.0, 0, "", "", "Set frame buffer to sprite buffer")
|
|
GPU(207, "DBACKBUF", 0, 1.0, 0, "", "", "Set frame buffer to back buffer")
|
|
GPU(208, "DSETBUF_FBO", 0, 1.0, 0, "", "", "Set frame buffer to view buffer")
|
|
GPU(208, "DFRONTBUF", 0, 1.0, 0, "", "", "Set frame buffer to front buffer")
|
|
GPU(209, "DSWAP", 0, 1.0, 0, "", "", "Copy back buffer to front buffer")
|
|
---- Dec 21 -- Pipe controls and one-operand opcodes --------------------------------------------------------------------------------------------
|
|
GPU(210, "DVXPIPE", 1, 0.5, 0, "IDX", "", "Set vertex pipe")
|
|
GPU(211, "DCVXPIPE", 1, 0.5, OL, "IDX", "", "DCPIPE")
|
|
GPU(211, "DCPIPE", 1, 1.0, 0, "IDX", "", "Set coordinate pipe")
|
|
GPU(212, "DENABLE", 1, 0.5, 0, "IDX", "", "Enable parameter")
|
|
GPU(213, "DDISABLE", 1, 0.5, 0, "IDX", "", "Disable parameter")
|
|
GPU(214, "DCLRSCR", 1, 0.5, 0, "COLOR", "", "Clear screen with color")
|
|
GPU(215, "DCOLOR", 1, 0.5, 0, "COLOR", "", "Set current color")
|
|
GPU(216, "DTEXTURE", 1, 1.0, 0, "IDX", "", "Set current texture")
|
|
GPU(217, "DSETFONT", 1, 0.5, 0, "IDX", "", "Set current font")
|
|
GPU(218, "DSETSIZE", 1, 0.5, 0, "INT", "", "Set font size")
|
|
GPU(219, "DMOVE", 1, 0.5, 0, "VEC2F", "", "Set drawing position offset")
|
|
---- Dec 22 -- Rendering opcodes ----------------------------------------------------------------------------------------------------------------
|
|
GPU(220, "DVXDATA_2F", 2, 0.5, 0, "VEC2F", "IDX", "Draw a solid 2D polygon (pointer to 2D data, vertex count)")
|
|
GPU(220, "DVXPOLY", 2, 0.5, 0, "VEC2F", "IDX", "Draw a solid 2D polygon (pointer to 2D data, vertex count)")
|
|
GPU(221, "DVXDATA_2F_TEX",2, 0.5, 0, "VEC2F", "IDX", "Draw a textured 2D polygon (pointer to 2D data, vertex count)")
|
|
GPU(221, "DVXTEXPOLY", 2, 0.5, 0, "VEC2F", "IDX", "Draw a textured 2D polygon (pointer to 2D data, vertex count)")
|
|
GPU(222, "DVXDATA_3F", 2, 0.5, 0, "VEC3F", "IDX", "Draw a solid 3D polygon (pointer to 3D data, vertex count)")
|
|
GPU(223, "DVXDATA_3F_TEX",2, 0.5, 0, "VEC3FT","IDX", "Draw a textured 3D polygon (pointer to 3D data, vertex count)")
|
|
GPU(224, "DVXDATA_3F_WF", 2, 0.5, 0, "VEC3F", "IDX", "Draw a wireframe 3D polygon (pointer to 3D data, vertex count)")
|
|
GPU(225, "DRECT", 2, 0.5, 0, "VEC2F", "VEC2F", "Draw a rectangle (by endpoints)")
|
|
GPU(226, "DCIRCLE", 2, 0.5, 0, "VEC2F", "Y", "Draw a circle with radius Y")
|
|
GPU(227, "DLINE", 2, 0.5, 0, "VEC2F", "VEC2F", "Draw a line")
|
|
GPU(228, "DRECTWH", 2, 0.6, 0, "VEC2F", "VEC2F", "Draw a rectangle (by offset, size)")
|
|
GPU(229, "DORECT", 2, 0.5, 0, "VEC2F", "VEC2F", "Draw an outlined rectangle")
|
|
---- Dec 23 -- Additional rendering opcodes -----------------------------------------------------------------------------------------------------
|
|
GPU(230, "DTRANSFORM2F", 2, 0.5, 0, "VEC2F", "VEC2F", "Transform vector and write it to first operand")
|
|
GPU(231, "DTRANSFORM3F", 2, 0.5, 0, "VEC3F", "VEC3F", "Transform vector and write it to first operand")
|
|
GPU(232, "DSCRSIZE", 2, 0.5, 0, "X", "Y", "Set screen size")
|
|
GPU(233, "DROTATESCALE", 2, 0.5, 0, "X", "Y", "Rotate by X, scale by Y")
|
|
GPU(234, "DORECTWH", 2, 0.5, 0, "VEC2F", "VEC2F", "Draw an outlined rectangle by width/height")
|
|
GPU(235, "DCULLMODE", 2, 0.7, 0, "IDX", "IDX", "Set cullmode and lighting mode")
|
|
--GPU(236, "DARRAY", 2, 1.0, 0, "VEC2F", "STRUCT","Draw an array of pixels")
|
|
--GPU(237, "DDTERMINAL", 2, 1.0, 0, "VEC2F", "STRUCT","Draw a console screen/terminal window")
|
|
GPU(238, "DPIXEL", 2, 1.0, 0, "VEC2F", "COLOR", "Draw a pixel to screen")
|
|
GPU(239, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
---- Dec 24 -- Text output and lighting ---------------------------------------------------------------------------------------------------------
|
|
GPU(240, "DWRITE", 2, 0.5, 0, "VEC2F", "STRING","Write a string")
|
|
GPU(241, "DWRITEI", 2, 0.5, 0, "VEC2F", "INT", "Write an integer value")
|
|
GPU(242, "DWRITEF", 2, 0.5, 0, "VEC3F", "Y", "Write a float value")
|
|
GPU(243, "DENTRYPOINT", 2, 0.5, 0, "IDX", "PTR", "Set entry point")
|
|
GPU(244, "DSETLIGHT", 2, 0.6, 0, "IDX", "STRUCT","Set light")
|
|
GPU(245, "DGETLIGHT", 2, 0.6, 0, "STRUCT","IDX", "Get light")
|
|
GPU(246, "DWRITEFMT", 2, 0.6, 0, "VEC2F", "STRING","Write a formatted string")
|
|
GPU(247, "DWRITEFIX", 2, 0.5, 0, "VEC2F", "Y", "Write a fixed value")
|
|
GPU(248, "DTEXTWIDTH", 2, 0.8, 0, "INT", "STRING","Return text width")
|
|
GPU(249, "DTEXTHEIGHT", 2, 0.8, 0, "INT", "STRING","Return text height")
|
|
---- Dec 25 -- Vector mode extension ------------------------------------------------------------------------------------------------------------
|
|
VEX(250, "VADD", 2, 7.00, 0, "VEC", "VEC", "X = X + Y")
|
|
VEX(251, "VSUB", 2, 7.00, 0, "VEC", "VEC", "X = X - Y")
|
|
VEX(252, "VMUL", 2, 7.00, 0, "VEC", "X", "X = X * SCALAR Y")
|
|
VEX(253, "VDOT", 2, 7.00, 0, "VEC", "VEC", "X = X dot Y")
|
|
VEX(254, "VCROSS", 2, 7.00, 0, "VEC", "VEC", "X = X cross Y")
|
|
VEX(255, "VMOV", 2, 7.00, 0, "VEC", "VEC", "X = Y")
|
|
VEX(256, "VNORM", 2, 7.00, 0, "VEC", "VEC", "X = NORMALIZE(Y)")
|
|
VEX(257, "VCOLORNORM", 2, 10.0, 0, "COLOR", "COLOR", "Normalize color (clamp it to RGB range)")
|
|
GPU(258, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(259, "DLOOPXY", 2, 0.7, CB, "PTR", "PTR", "2D loop by ECX/EDX registers")
|
|
VEX(259, "LOOPXY", 2, 10.0, CB, "PTR", "PTR", "2D loop by ECX/EDX registers")
|
|
---- Dec 26 -- Matrix math ----------------------------------------------------------------------------------------------------------------------
|
|
VEX(260, "MADD", 2, 7.00, 0, "MATRIX","MATRIX","X = X + Y")
|
|
VEX(261, "MSUB", 2, 7.00, 0, "MATRIX","MATRIX","X = X - Y")
|
|
VEX(262, "MMUL", 2, 7.00, 0, "MATRIX","MATRIX","X = X * Y")
|
|
VEX(263, "MROTATE", 2, 7.00, 0, "MATRIX","VEC4F", "Rotation matrix based on rotation vector")
|
|
VEX(264, "MSCALE", 2, 7.00, 0, "MATRIX","VEC4F", "Scaling matrix based on scaling vector")
|
|
VEX(265, "MPERSPECTIVE", 2, 7.00, 0, "MATRIX","VEC4F", "Perspective matrix based on FOV and near/far planes")
|
|
VEX(266, "MTRANSLATE", 2, 7.00, 0, "MATRIX","VEC4F", "Translation matrix based on translation vector")
|
|
VEX(267, "MLOOKAT", 2, 7.00, 0, "MATRIX","VEC4F", "Lookat matrix based on three vectors")
|
|
VEX(268, "MMOV", 2, 7.00, 0, "MATRIX","MATRIX","X = Y")
|
|
VEX(269, "VLEN", 2, 7.00, 0, "X", "VEC", "X = Sqrt(Y dot Y)")
|
|
---- Dec 27 -- Matrix math ----------------------------------------------------------------------------------------------------------------------
|
|
VEX(270, "MIDENT", 1, 7.00, 0, "MATRIX","", "Load identity matrix")
|
|
GPU(271, "MLOADPROJ", 1, 0.6, 0, "MATRIX","", "Load matrix into view matrix")
|
|
GPU(272, "MREAD", 1, 0.6, 0, "MATRIX","", "Write view matrix into matrix")
|
|
VEX(273, "VMODE", 1, 7.00, 0, "IDX", "", "Set vector math mode")
|
|
GPU(274, "DT", 1, 0.6, W1, "X", "", "Set X to frame length time")
|
|
GPU(275, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
GPU(276, "DSHADE", 1, 0.5, 0, "X", "", "Shade the current color")
|
|
GPU(277, "DSETWIDTH", 1, 0.5, 0, "X", "", "Set line width")
|
|
GPU(278, "MLOAD", 1, 0.6, 0, "MATRIX","", "Load matrix into model matrix")
|
|
GPU(279, "DSHADENORM", 1, 0.6, 0, "X", "", "Shade the current color and normalize it")
|
|
GPU(279, "DSHADECOL", 1, 0.6, OL, "X", "", "DSHADENORM")
|
|
---- Dec 28 -- Advanced rendering ---------------------------------------------------------------------------------------------------------------
|
|
GPU(280, "DDFRAME", 1, 1.0, 0, "STRUCT","", "Draw bordered frame")
|
|
GPU(281, "DDBAR", 1, 1.0, 0, "STRUCT","", "Draw a progress bar")
|
|
GPU(282, "DDGAUGE", 1, 1.0, 0, "STRUCT","", "Draw gauge needle")
|
|
GPU(283, "DRASTER", 1, 0.6, 0, "INT", "", "Set rasterizer quality level")
|
|
GPU(284, "DDTERRAIN", 1, 0.8, 0, "STRUCT","", "Draw terrain")
|
|
GPU(285, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
GPU(286, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
GPU(287, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
GPU(288, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
GPU(289, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
---- Dec 29 -- Additional instructions ----------------------------------------------------------------------------------------------------------
|
|
GPU(290, "DLOADBYTES", 2, 1.0, 0, "IDX", "PTR", "Load into texture slot by pointer")
|
|
GPU(291, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(292, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(293, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(294, "DMULDT", 2, 0.7, 0, "X", "Y", "X = Y * dT")
|
|
VEX(295, "VDIV", 2, 7.00, 0, "VEC", "Y", "VEC = VEC / Y")
|
|
VEX(296, "VTRANSFORM", 2, 8.00, 0, "VEC", "MATRIX","X = X * MATRIX")
|
|
GPU(297, "DSMOOTH", 2, 1.0, 0, "X", "Y", "Smooth X with smoothness Y")
|
|
GPU(298, "DBEGIN", 0, 1.0, 0, "", "", "Begin rendering (from async thread)")
|
|
GPU(299, "DEND", 0, 1.0, 0, "", "", "End rendering (from async thread)")
|
|
---- Dec 30 -- 3D rendering ---------------------------------------------------------------------------------------------------------------------
|
|
GPU(300, "DROTATE", 1, 1.0, 0, "VEC4F", "", "Rotate model by vector")
|
|
GPU(301, "DTRANSLATE", 1, 1.0, 0, "VEC4F", "", "Translate model by vector")
|
|
GPU(302, "DSCALE", 1, 1.0, 0, "VEC4F", "", "Scale model by vector")
|
|
GPU(303, "DXTEXTURE", 1, 1.0, 0, "STR", "", "Bind a specific external texture")
|
|
GPU(304, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(305, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(306, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(307, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(308, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
GPU(309, "RESERVED", 2, 0.0, 0, "", "", "")
|
|
---- Dec 31 -- UNDEFINED ------------------------------------------------------------------------------------------------------------------------
|
|
---- Dec 32 -- SPU output control ---------------------------------------------------------------------------------------------------------------
|
|
SPU(320, "CHRESET" , 1, 1.0, 0, "CHAN", "", "Reset channel")
|
|
SPU(321, "CHSTART", 1, 1.0, 0, "CHAN", "", "Start sound on channel")
|
|
SPU(322, "CHSTOP", 1, 1.0, 0, "CHAN", "", "Stop sound on channel")
|
|
SPU(323, "CHTRIGGER", 1, 1.0, 0, "CHAN", "", "Trigger the ADSR envelope on channel")
|
|
SPU(324, "CHRELEASE", 1, 1.0, 0, "CHAN", "", "Release the ADSR envelope on channel")
|
|
SPU(325, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
SPU(326, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
SPU(327, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
SPU(328, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
SPU(329, "RESERVED", 1, 0.0, 0, "", "", "")
|
|
---- Dec 33 -- SPU channel control --------------------------------------------------------------------------------------------------------------
|
|
SPU(330, "WSET", 2, 1.0, 0, "WAVE", "STRING","Set lookup name for specific wave")
|
|
SPU(331, "CHWAVE", 2, 1.0, 0, "CHAN", "WAVE", "Set waveform")
|
|
SPU(332, "CHLOOP", 2, 1.0, 0, "CHAN", "IDX", "Set looping mode")
|
|
SPU(333, "CHVOLUME", 2, 1.0, 0, "CHAN", "X", "Set volume")
|
|
SPU(334, "CHPITCH", 2, 1.0, 0, "CHAN", "X", "Set pitch (value interpretation depends on register)")
|
|
SPU(335, "CHMODT", 2, 1.0, 0, "CHAN", "X", "Set LFO modulation type")
|
|
SPU(336, "CHMODA", 2, 1.0, 0, "CHAN", "X", "Set LFO modulation amplitude")
|
|
SPU(337, "CHMODF", 2, 1.0, 0, "CHAN", "X", "Set LFO modulation frequency")
|
|
SPU(338, "CHADSR", 2, 1.0, 0, "CHAN", "VEC4F", "Set channel ADSR")
|
|
SPU(339, "WLEN", 2, 1.0, 0, "X", "WAVE", "Read sound length in seconds")
|