if getOperatingSystem()~=1 then return end --not macos

scripts={}

local function registerBigEndianInt16()

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

TypeName:
db '2 Byte Big Endian',0

ByteSize:
dd 2

CallMethod:
db 1

//The convert routine should hold a routine that converts the data to an integer (in eax)
//function declared as: cdecl int ConvertRoutine(unsigned char *input, PTR_UINT address);
//Note: Keep in mind that this routine can be called by multiple threads at the same time.
ConvertRoutine:
//rdi=address of input
//rsi=address
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: cdecl void ConvertBackRoutine(int i, PTR_UINT address, unsigned char *output);
ConvertBackRoutine:
//edi=input
//rsi=address
//rdx=address of output
xor eax,eax
mov ax,di
xchg al,ah

mov dword ptr [rdx],eax  //place the integer the 4 bytes pointed to by rdx
ret
]])
end

----------------------- 32 bit big endian ---------------------

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

TypeName:
db '4 Byte Big Endian',0

ByteSize:
dd 4

CallMethod:
db 1

//The convert routine should hold a routine that converts the data to an integer (in eax)
//function declared as: cdecl int ConvertRoutine(unsigned char *input, PTR_UINT address);
//Note: Keep in mind that this routine can be called by multiple threads at the same time.
ConvertRoutine:
//rdi=address of input
//rsi=address
xor eax,eax
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:  cdecl void ConvertBackRoutine(int i, PTR_UINT address, unsigned char *output);
ConvertBackRoutine:
//edi=input
//rsi=address
//rdx=address of output

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

ret
]])
end


--------------- 32 bit float --------------

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

UsesFloat:
db 1

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

  
ConvertBackRoutine:
//edi=input
//rsi=address
//rdx=address of output
bswap edi //convert the little endian input into a big endian input
mov [rdx],ecx //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
    --print(scriptnames[i].. ' = ' .. s.Value[scripts[scriptnames[i]].reg])
    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


