if getSystemArchitecture()>=2 then return end --arm+ not supported yet
if getOperatingSystem()~=2 then return end --not linux

local scripts={}

--[[
param passing in 64-bit
1=rdi
2=rsi
3=rdx
4=rcx
--]]

local function registerBigEndianInt16()
scripts['2 Byte Big Endian'].type=registerCustomTypeAutoAssembler([[
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)

TypeName:
db '2 Byte Big Endian',0

ByteSize:
dd 2

//The convert routine should hold a routine that converts the data to an integer (in eax)
//function declared as: stdcall int ConvertRoutine(unsigned char *input);
//Note: Keep in mind that this routine can be called by multiple threads at the same time.
ConvertRoutine:
//jmp dllname.functionname

//or manual:
//parameters: (64-bit)
//rdi=address of input
xor eax,eax
mov ax,[rdi] //eax now contains the bytes 'input' pointed to
xchg ah,al //convert to big endian

ret

//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value)
//function declared as: stdcall void ConvertBackRoutine(int i, unsigned char *output);
ConvertBackRoutine:
//jmp dllname.functionname
//or manual:

//parameters: (64-bit)
//rdi=input
//rsi=address of output
//example:
mov ax,di
xchg ah,al //convert the little endian input into a big endian input
mov [rdx],ax //place the integer the 4 bytes pointed to by rdx

ret


]])
end

local function registerBigEndianInt32()
scripts['4 Byte Big Endian'].type=registerCustomTypeAutoAssembler([[
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)

TypeName:
db '4 Byte Big Endian',0

ByteSize:
dd 4

//The convert routine should hold a routine that converts the data to an integer (in eax)
//function declared as: stdcall int ConvertRoutine(unsigned char *input);
//Note: Keep in mind that this routine can be called by multiple threads at the same time.
ConvertRoutine:
//jmp dllname.functionname
//or manual:
//parameters: (64-bit)
//rdi=address of input
xor rax,rax
mov eax,[rdi] //eax now contains the bytes 'input' pointed to
bswap eax //convert to big endian

ret


//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value)
//function declared as: stdcall void ConvertBackRoutine(int i, unsigned char *output);
ConvertBackRoutine:
//jmp dllname.functionname
//or manual:

//parameters: (64-bit)
//edi=input
//rsi=address of output
//example:
bswap edi //convert the little endian input into a big endian input
mov [rsi],edi //place the integer the 4 bytes pointed to by rdx

ret
]])
end


local function registerBigEndianFloat()
scripts['Float Big Endian'].type=registerCustomTypeAutoAssembler([[
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)
alloc(UsesFloat,1)
  
  
TypeName:
db 'Float Big Endian',0
  
  
ByteSize:
dd 4

UsesFloat:
db 1
  
  
ConvertRoutine:
xor eax,eax
mov eax,[rdi] //eax now contains the bytes 'input' pointed to
bswap eax //convert to big endian
ret


  
ConvertBackRoutine:
bswap edi //convert the little endian input into a big endian input
mov [rsi],edi //place the integer the 4 bytes pointed to by rdx
ret


]])
end


scripts['2 Byte Big Endian']={func=registerBigEndianInt16,reg='EnableBigEndianInt16'}
scripts['4 Byte Big Endian']={func=registerBigEndianInt32,reg='EnableBigEndianInt32'}
scripts['Float Big Endian']={func=registerBigEndianFloat,reg='EnableBigEndianFloat'}
local scriptnames={'2 Byte Big Endian','4 Byte Big Endian','Float Big Endian'}


--when loaded check if it should load the custom types
local i
local s=getSettings()
for i=1,#scriptnames do 
  if (s.Value[scripts[scriptnames[i]].reg]=='1') then
    scripts[scriptnames[i]].func()
  end
end

local sf=getSettingsForm()

local CustomTypesPage=nil
for i=0, sf.SettingsPageControl.PageCount-1 do
  if sf.SettingsPageControl.Page[i].Name=='CustomTypes' then --Do NOT translate this
    CustomTypesPage=sf.SettingsPageControl.Page[i]
  end
end
if CustomTypesPage==nil then
  --first script to add it
  CustomTypesPage=sf.SettingsPageControl.addTab()
  CustomTypesPage.Name='CustomTypes' --again, do NOT translate this
  CustomTypesPage.Caption=translate('Extra Custom Types')

  local insertNode=sf.SettingsTreeView.Items[3]  --insert it near the unrandomizer since it'd be used as often as that setting
  local node=sf.SettingsTreeView.Items.insert(insertNode, CustomTypesPage.Caption)
  node.data=userDataToInteger(CustomTypesPage)

  local clb=createCheckListBox(CustomTypesPage);
  clb.Align='alClient'
  clb.Name='List'
end


for i=1, #scriptnames do
  CustomTypesPage.List.Items.Add(scriptnames[i])
  CustomTypesPage.List.Checked[CustomTypesPage.List.Items.Count-1]=scripts[scriptnames[i]].type~=nil
end

local oldOnClose=sf.OnClose
sf.OnClose=function(sender, closeAction)
  local result=closeAction
  if oldOnClose~=nil then
    result=oldOnClose(sender, closeAction)
  end
  
  if (result==caHide) and (sender.ModalResult==mrOK) then
    local i
    for i=0, CustomTypesPage.List.Items.Count-1 do
      local ctname=CustomTypesPage.List.Items[i]
      
      
      if scripts[ctname] then --known name
        if CustomTypesPage.List.Checked[i] then
          if scripts[ctname].type==nil then
            scripts[ctname].func()                    
          end               
          local regname=scripts[ctname].reg;
          s.Value[scripts[ctname].reg]='1' 
         -- print(s.ClassName)
        else
          
          if scripts[ctname].type then
            --print("destroy")
            scripts[ctname].type.destroy()
            scripts[ctname].type=nil
          end
          s.Value[scripts[ctname].reg]='0'
       
        end
      end
    end
  end
  return result
end


