; ---- String Routines for Ultrabasic
; ---- Gabriel Fernandez
; ---- You are not allowed to use this code without permission

; - STR$
; - EAX, DEST
; - EBX, Value

STR$:
  PUSH EAX
  PUSH EDI
  mov edi, 0
  CMP ebx, 0
  JGE positive3
    NEG EBX
    inc edi
positive3:
  inc edi
  xor ecx, ecx
  mov eax, ebx
  mov ebx, 10
Nextn:
  inc cx
  xor edx, edx
  DIV ebx
    PUSH DX
  CMP EAX, 0
JNE Nextn
  mov eax, tmp
  mov dx, cx
  CMP edi, 1
  JE skipneg
    mov byte [eax], 45
    inc cx
    inc eax
skipneg:
  
Nextn2:
  dec dx
    POP BX
    add bl, 48
    mov [eax], BL
    inc eax
  cmp dx, 0
JNE Nextn2
  mov ebx, 0
  mov bx, cx
  POP EDI
  POP EAX
  mov ecx, tmp
  mov edx, [eax]
  add [eax], ebx
  add eax, edx
  add eax, 4
  Call copydata
RET

; CmpStrings
; EAX - String 1, EBX - String 2
CmpStrings:
  MOV ECX, [EAX]
  MOV EDX, [EBX]
  CMP ecx, edx
  JNE cmpstrnotequal
  CMP ecx, 0
  JE cmpstrequal
  ADD EAX, 4
  ADD EBX, 4
cmpstrloop:
  MOV DL, [EAX]
  MOV DH, [EBX]
  CMP DL, DH
  JNE cmpstrnotequal
  DEC ecx
  CMP ECX, 0
  JNE cmpstrloop
cmpstrequal:
  MOV EAX, 1
RET

cmpstrnotequal:
  MOV EAX, 0
RET

; Clear string
; ECX - offset, EBX - size
clearstring:
  MOV EDX, ECX
  ADD EDX, EBX
clearloop:
  MOV BYTE [ECX], 0
  INC ECX
  CMP ECX, EDX
  JNE clearloop
RET

; Copy Data
; EAX - Out offset
; ECX - in offset, EBX - size

copydata:
  CMP EBX, 0
  JE skipcopydata
  MOV EDX, ECX
  ADD EDX, EBX
  INC EDX
copydataloop:
  MOV BL, [ECX]
  MOV [EAX], BL
  INC ECX
  INC EAX
  CMP ECX, EDX
  JNE copydataloop
skipcopydata:
RET

; Copy Data 2
; EAX - in offset
; ECX - Out offset, EBX - size

copydata2:
  CMP EBX, 0
  JE retfromjump
  MOV EDX, ECX
  ADD EDX, EBX
copydataloop2:
  MOV BL, [EAX]
  MOV [ECX], BL
  INC ECX
  INC EAX
  CMP ECX, EDX
  JNE copydataloop2
retfromjump:
RET


; Copy to string
; EBX - Size, ECX - Offset
; EAX - out Offset
copytostring:
  CMP EBX, 0
  JE dontcopy

  MOV [push1], eax
  MOV EDX, [EAX]

  ADD [EAX], EBX

  ADD EAX, EDX
  MOV [tmp], EAX
  ADD [tmp], EBX
  ADD DWORD [tmp], 4
copyloop:
  ADD EAX, 4

  MOV EDX, [ECX]
  MOV [EAX], EDX

  ADD ECX, 4

  CMP EAX, [tmp]
  JNGE copyloop
; ----------------
  MOV eax, [push1]
dontcopy:
RET

; Getmaxarrayoffset
; EAX - Offset, EDX - Array size
Getmaxarrayoffset:
  MOV [push3], EDX
  MOV DWORD [push4], 0
  MOV EBX, 0
  MOV DWORD [tmp], 0

loop1:
  MOV ECX, [push4]
  SHL ECX, 3
  ADD ECX, EAX

  MOV BX, [ECX+6]
  CMP BX, 0
  JE gmaoskip

  MOV EDX, [ECX]
  SUB EDX, [push5]
  ADD [tmp], EDX
  JMP cmpnext
; ---- If the string never was used
  CMP ECX, EAX
  JE cmpnext  ; First obj
  SUB ECX, 8

  MOV BX, [ECX+4]
  ADD [tmp], EBX
cmpnext:
  MOV ECX, [push4]
  CMP ECX, [push3]
  INC DWORD [push4]
  JE loop1
; ---- Now we add the last value
  MOV ECX, [push4]
  SHL ECX, 3
  ADD ECX, EAX
  MOV BX, [ECX+4]
  ADD [tmp], EBX
  MOV EBX, [tmp]
gmaoskip:
RET

; Moveright
; EDX - number of bytes, EAX - start offset
; EBX - end offset
Moveright:
  DEC EAX
moverloop2:
  MOV [push1], EAX
  MOV [push2], EBX
moverloop:
  MOV CL, [EBX]
  MOV [EBX+1], CL
  DEC EBX
  CMP EBX, EAX
  JNE moverloop

MOV EAX, [push1]
MOV EBX, [push2]
INC EAX
INC EBX

CMP EDX, 0
DEC EDX
JNE moverloop2
RET

; Moveleft
; ECX - number of bytes, EAX - start offset
; EBX - end offset
Moveleft:
  INC EBX
movelloop2:
  MOV [push2], EBX
  MOV [push1], EAX
movelloop:
  MOV DL, [EAX]
  MOV [EAX-1], DL
  INC EAX
  CMP EAX, EBX
  JNE movelloop

MOV EBX, [push2]
MOV EAX, [push1]
DEC EAX
DEC EBX
CMP ECX, 0
DEC ECX
JNE movelloop2
RET

; ---- OLD routines from Gabasic ----
; LCase$, Ucase$
; EAX - dest
; EBX - src

Lcase$:
  PUSH EAX
  mov ecx, [ebx]
  mov edx, [eax]
  cmp ecx, 0
  je skiplcase$
  add ebx, 3
  add [eax], ecx
  add eax, 3
  add eax, edx
nextlc:
  DEC ecx
  inc eax
  inc ebx
  mov dl, [ebx]

  cmp dl, 65
  JNGE cmpnc
  cmp dl, 90
  JNLE cmpnc
  add dl, 32
cmpnc:
  mov [eax], dl
  cmp ecx, 0
JNE nextlc

skiplcase$:
POP EAX
ret

Ucase$:
  PUSH EAX
  mov ecx, [ebx]
  mov edx, [eax]
  cmp ecx, 0
  je skipucase$
  add ebx, 3
  add [eax], ecx
  add eax, 3
  add eax, edx
nextuc:
  DEC ecx
  inc eax
  inc ebx
  mov dl, [ebx]

  cmp dl, 97
  JNGE ucmpnc
  cmp dl, 122
  JNLE ucmpnc
  sub dl, 32
ucmpnc:
  mov [eax], dl
  cmp ecx, 0
JNE nextuc

skipucase$:
POP EAX
ret


; String$
; EAX - dest, EBX - char, ECX - times

String$:
  PUSH EDI
  PUSH EAX
  mov edi, eax
  MOV edx, [eax]
  add edi, edx
  add edi, 4
  Add edx, ecx
  MOV [eax], edx

  mov eax, ebx
  REP STOSB
  POP EAX
  POP EDI
RET

; MID$
; - EAX, src
; - EBX, startpos
; - ECX, len          EDX, dest
MID$:
  DEC EBX
  PUSH EBX
  MOV ebx, [edx]
  add ebx, ecx
  mov [edx], ebx
  add eax, 4
  add edx, 4
  mov esi, eax
  mov edi, edx
  POP EBX
  add esi, ebx
  REP MOVSB
RET

; LTRIM$
; EAX - DEST
; EBX - SRC
ltrim$:
  PUSH eax
  mov ecx, [ebx]
  add ebx, 3
  inc ecx
ltloop1:
    inc ebx
    dec ecx
    mov dl, [ebx]
    cmp dl, 32
    je ltloop1
  mov edx, [eax]
  add [eax], ecx
  add eax, 4
  add eax, edx
  mov [apush1], edi
  mov [apush2], esi
  mov edi, eax
  mov esi, ebx
  REP MOVSB
  mov edi, [apush1]
  mov esi, [apush2]
  POP EAX
ret

; RTRIM$
; EAX - DEST
; EBX - SRC
rtrim$:
  PUSH eax
  PUSH ebx
  mov ecx, [ebx]
  add ebx, ecx
  inc ecx
  add ebx, 4
rtloop1:
    dec ebx
    dec ecx
    mov dl, [ebx]
    cmp dl, 32
    je rtloop1
  mov edx, [eax]
  add [eax], ecx
  add eax, 4
  add eax, edx
  mov [apush1], edi
  mov [apush2], esi
  POP esi
  add esi, 4
  mov edi, eax
  REP MOVSB  
  mov edi, [apush1]
  mov esi, [apush2]
  POP EAX
ret

; --- Val
; EBX, Dest
; RET: EAX, Value

Val:
  mov esi, 0
  mov ecx, [ebx]
  add ebx, 3
  mov al, [ebx+1]
  cmp al, 45
JNE noneg
   mov esi, 1
   dec ecx
   inc ebx
noneg:
  mov eax, 0
  mov edx, 0
next1:
   INC EBX
   INC EDX
   DEC ECX
     mov al, [ebx]
     sub al, 48
     PUSH EAX
   CMP ECX, 0
 JNE next1
  MOV ecx, edx
  MOV EBX, 1
  MOV EDI, 0
next2:
  DEC ECX
    POP EAX
    mov edx, 0
    MUL EBX
      add edi, eax
    MOV EDX, EBX
    Shl ebx, 1
    shl edx, 3
    add ebx, edx
  CMP ECX, 0
 JNE next2
mov eax, edi
cmp esi, 0
JE vskipneg
  neg eax
vskipneg:
RET