alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(UsesFloat,1)
alloc(CallMethod,1)

alloc(convType,64)

alloc(PreferedAlignment, 4)

PreferedAlignment:
dd #4
ByteSize:
dd #8

TypeName:
db 'timerBE8AA',0


UsesFloat:
db 0 //Change to 1 if this custom type should be treated as a float

CallMethod:
db 1 //Remove or change to 0 for legacy call mechanism

//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.

struct cvtype
from: dd ?
to: dd ?
divid: dd ?
limitLow: dd ?
limitHigh: dd ?
ends

struct Stack
low: dd ?
high: dd ?
one: dd ?
ten: dd ?
hundred: dd ?
ends

convType:
// for convert second => disp-value
dd #60,#100,#40500000,7ED86BE0,134FD47
// for convert disp-value =>> second
dd #100,#60,1,#2147475959,0




/*
define(low,0)
define(high,4)
define(sec,8)
define(min,0c)
define(hour,10)
*/
ConvertRoutine:
//jmp dllname.functionname

label(conv)


[64-bit]
//or manual:
//parameters: (64-bit)
//rcx=address of input
//rdx=address

//mov eax,[rcx] //eax now contains the bytes 'input' pointed to
push  rbp
mov   rbp,rsp

push  rdi
push  rsi
push  rbx

sub   rsp,30
lea   rdi,[rsp]
mov   rbx,convType  //  conv seconds to disp-value

  mov    eax,[rcx+4]
  mov    edx,[rcx]
  bswap  eax
  bswap  edx
  mov    [rdi+low],eax
  mov    [rdi+high],edx

  call   conv

add   rsp,30

pop   rbx
pop   rsi
pop   rdi

pop   rbp

ret
[/64-bit]



[32-bit]
//jmp dllname.functionname
//or manual:
//parameters: (32-bit)
push ebp
mov ebp,esp
//[ebp+8]=address of input
//[ebp+c]=address
//example:

push edi
push esi
push ebx

sub  esp,30
lea  edi,[esp]
/*
  mov    esi,[ebp+8] //place the address that contains the bytes into eax
  mov    eax,[esi] //place the bytes into eax so it's handled as a normal 4 byte value
  mov    edx,[esi+4]
  bswap  eax
  bswap  edx
  mov    [edi+low],edx
  mov    [edi+high],eax
  call   convTo
*/
mov   rbx,convType  //  conv seconds to disp-value
  mov    ecx,[ebp+8]
  mov    eax,[ecx+4]
  mov    edx,[ecx]
  bswap  eax
  bswap  edx
  mov    [edi+low],eax
  mov    [edi+high],edx

  call   conv


add  esp,30

pop  ebx
pop  esi
pop  edi

pop  ebp
ret
[/32-bit]

//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:




//jmp dllname.functionname
//or manual:
[64-bit]
//parameters: (64-bit)
//ecx=input
//rdx=address
//r8=address of output
//example:

push rbp
mov  rbp,rsp
push rbx
push rsi
push rdi

sub  rsp,30
lea  rdi,[rsp]
mov  rbx,convType+14 // conv disp-value to seconds
  mov    eax,rcx
  test   eax,eax
  jle    @f          // no negative input
  mov    [rdi+low],eax
  xor    edx,edx
  mov    [rdi+high],edx

  call   conv
  test   eax,eax
  jle    @f          // skip if invalid
    xor    edx,edx
    mov    ecx,#40500000
    mul    ecx
    bswap  edx
    bswap  eax
    mov    [r8+00],edx
    mov    [r8+04],eax
@@:
add  rsp,30

pop  rdi
pop  rsi
pop  rbx

pop  rbp
//mov [r8],ecx //place the integer at the 4 bytes pointed to by r8

ret
[/64-bit]

[32-bit]
//parameters: (32-bit)
push ebp
mov ebp,esp
//[ebp+8]=input
//[ebp+c]=address
//[ebp+10]=address of output
//example:
push eax
push ebx
mov eax,[ebp+8] //load the value into eax

push esi
push edi

sub  esp,30
lea  edi,[esp]
mov  ebx,convType+14 // conv disp-value to seconds

  test   eax,eax
  jle    @f          // no negative input
  mov    [edi+low],eax
  xor    edx,edx
  mov    [edi+high],edx

  call   conv
  test   eax,eax
  jle    @f          // skip if invalid
    xor    edx,edx
    mov    ecx,#40500000
    mul    ecx
    bswap  edx
    bswap  eax
    mov    ebx,[ebp+10]
    mov    [ebx+00],edx
    mov    [ebx+04],eax
@@:
add  esp,30

pop  edi
pop  esi
pop  ebx
pop  eax

pop ebp
ret
[/32-bit]







// ??hex)134 FD47 7ED86BE0?? -> #40500000 x #214747_59_59<(hex)7fffffff
//  (hex)269 fb20 == #40500000

label(invalid)
//label(done)

// common conv
//======================================================
  conv:
    mov  eax,[edi+high]
    cmp  eax,[ebx+limitHigh]
    jb   @f
    ja   invalid
    mov  eax,[edi+low]
    cmp  eax,[ebx+limitLow]
    ja   invalid
@@:
    mov  eax,[edi+low]
    mov  edx,[edi+high]
    mov  ecx,[ebx+divid]
    cmp  ecx,1
    je   @f
    div  ecx
@@:
    //   eax now is seconds or disp-value,
    //   depend on convert type,
    //   ready to convert opposite type
    mov  esi,[ebx+to]
    mov  ecx,[ebx+from]
    xor  edx,edx
    div  ecx
    cmp  edx,esi
    jae  invalid

    mov  [edi+one],edx
    xor  edx,edx
    div  ecx
    cmp  edx,esi
    jae  invalid

    mov  [edi+ten],edx
    mov  [edi+hundred],eax

    //   now convert to opposite type

    mov  eax,[edi+ten]
    xor  edx,edx
    mul  esi

    mov  ecx,[edi+one]
    add  ecx,eax

    mov  eax,[edi+hundred]
    xor  edx,edx
    mul  esi
    xor  edx,edx
    mul  esi
    add  eax,ecx
  ret
  invalid:
    xor  eax,eax
    dec  eax
  ret