// Additional functions for CPCBasic

function inline byte SaveProgramStack() // Store the initial stack pointer
{
  "ld   hl,0            ",
  "add  hl,sp           ",
  "ld   (__EndLoad+1),hl",
} using End;

function byte End() // End program and returns to Basic
{
  "__EndLoad: ld   sp,0",
  "           ret      "
}

function inline word SetDataPointer(word) // Set the data pointer
{
  "ld   (__DataLoad+1),hl"
} using Data;

function word Data() // Return the address of current data and update pointer to next
{
  "__DataLoad: ld   hl,0              ; Get data pointer          ",
  "            inc  hl                                            ",
  "            inc  hl                ; Update data pointer       ",
  "            ld   (__DataLoad+1),hl ; Store updated data pointer",
  "            dec  hl                                            ",
  "            ld   a,(hl)                                        ",
  "            dec  hl                                            ",
  "            ld   l,(hl)                                        ",
  "            ld   h,a               ; Current data value to HL  ",
  "            ret                                                "
}

function register word TimersSpace(byte) // Return the address of the nth buffer timer
{
  "                     ld   hl,__TimersSpaceBuffer                                  ",
  "                     ld   de,13                                                   ",
  "__TimersSpaceLoop:   or   a                                                       ",
  "                     ret  z                                                       ",
  "                     add  hl,de                                                   ",
  "                     dec  a                                                       ",
  "                     jr   __TimersSpaceLoop ; Multiply numer of buffer timer by 13",
  "__TimersSpaceBuffer: defs 13*4                                                    "
}

function word EnvelopeSpace() // Return the addres of the envelope space definition
{
  "                       ld   hl,__EnvelopeSpaceBuffer",
  "                       ret                          ",
  "__EnvelopeSpaceBuffer: defs 5*3                     "
}

function inline word EnvelopeSpaceValue(byte) // Return the address of the nth byte of the envelope space definition
{
  "ld   hl,__EnvelopeSpaceBuffer",
  "ld   d,0                     ",
  "ld   e,a                     ",
  "add  hl,de                   "
} using EnvelopeSpace;

function register word DescriptorString(word) // Return the address for a descriptor of string
{
  "push hl         ; Save string address               ",
  "call _StrLen                                        ",
  "push hl         ; Save string length                ",
  "ld   hl,3                                           ",
  "call _GetMemory ; Get space for string descriptor   ",
  "pop  de         ; Restore string length             ",
  "ld   (hl),e     ; Store string lenght in descriptor ",
  "inc  hl                                             ",
  "pop  de         ; Restore string address            ",
  "ld   (hl),e                                         ",
  "inc  hl                                             ",
  "ld   (hl),d     ; Store string address in descriptor",
  "dec  hl                                             ",
  "dec  hl         ; Restore descriptor address        ",
  "ret                                                 "
} using StrLen, GetMemory;

function inline word StackValue(word) // Return the nth value in stack
{
  "add  hl,hl ",
  "add  hl,sp ",
  "ld   a,(hl)",
  "inc  hl    ",
  "ld   h,(hl)",
  "ld   l,a   "
}

function inline byte Push(word) // Push a value into stack
{
  "push hl"
}

function inline byte Pop(byte) // Remove n values from stack
{
  "ld   l,a                                    ",
  "ld   h,0   ; HL = number of values to remove",
  "add  hl,hl ; HL = HL * 2                    ",
  "add  hl,sp                                  ",
  "ld   sp,hl                                  "
}

function byte Call(word, byte) // Call routine with the number of parameters specified
{
  "ld   ix,6                               ",
  "add  ix,sp                              ",
  "ld   h,(ix-1)                           ",
  "ld   l,(ix-2) ; HL = routine address    ",
  "ld   a,(ix-3) ; A = number of parameters",
  "jp   (hl)                               "
}

function byte Rsx(word, byte) // Call RSX command with number of parameters specified
{
  "ld   ix,6                               ",
  "add  ix,sp                              ",
  "ld   h,(ix-1)                           ",
  "ld   l,(ix-2) ; HL = routine address    ",
  "call __kl_find_command                  ",
  "ld   a,(ix-3) ; A = number of parameters",
  "jp   __kl_far_pchl                      "
}

function inline byte Cat() // Catalogue of tape/disc
{
  "ld   hl,2048                     ",
  "call _GetMemory                  ",
  "ex   de,hl ; Buffer address to DE",
  "call __cas_catalog               "
} using GetMemory;

function inline byte CursorSystem(byte) // Set the system cursor state
{
  "or   a            ",
  "jr   z,$+7        ",
  "call __txt_cur_on ",
  "jr   $+3          ",
  "call __txt_cur_off"
}

function inline byte CursorUser(byte) // Set the user cursor state
{
  "or   a                ",
  "jr   z,$+7            ",
  "call __txt_cur_enable ",
  "jr   $+5              ",
  "call __txt_cur_disable"
}

function register byte SetList(word) // Set the string as data list, returning the data number or 0 if error
{
  "                        ld   de,__GetElementData                                  ",
  "                        ex   de,hl              ; Data address to HL, string to DE",
  "                        ld   c,1                ; Data counter                    ",
  "__SetListLoop:          call __SetListSkipSpace                                   ",
  "                        or   a                                                    ",
  "                        jr   z,__SetListEndData ; End string                      ",
  "                        cp   34                 ; quotes                          ",
  "                        jr   z,__SetListQuotes  ; Data with quotes                ",
  "                        ld   b,\",\"                                              ",
  "                        call __SetListCopy                                        ",
  "__SetListTrim:          dec  hl                                                   ",
  "                        ld   a,(hl)                                               ",
  "                        cp   \" \"                                                ",
  "                        jr   z,__SetListTrim                                      ",
  "                        inc  hl                 ; Next character non space        ",
  "__SetListEndData:       ld   (hl),0                                               ",
  "                        inc  hl                                                   ",
  "                        ld   a,(de)                                               ",
  "                        or   a                                                    ",
  "                        jr   z,__SetListExit    ; End string                      ",
  "                        inc  de                 ; Skip comma                      ",
  "                        inc  c                                                    ",
  "                        jr   __SetListLoop                                        ",
  "__SetListQuotes:        inc de                  ; Skip initial quotes             ",
  "                        ld   b,a                                                  ",
  "                        call __SetListCopy                                        ",
  "                        or   a                                                    ",
  "                        jr   z,__SetListCopyEndQuotes                             ",
  "                        inc  de                                                   ",
  "__SetListCopyEndQuotes: call __SetListSkipSpace                                   ",
  "                        or   a                                                    ",
  "                        jr   z,__SetListEndData ; End string                      ",
  "                        cp   \",\"                                                ",
  "                        jr   z,__SetListEndData ; Comma                           ",
  "                        xor  a                                                    ",
  "                        ret                     ; Comma separator not found       ",
  "__SetListExit:          ld   a,c                                                  ",
  "                        ld   hl,__GetElementData                                  ",
  "                        ld   (__GetElementLoad+1),hl                              ",
  "                        ret                                                       ",
  "__SetListSkipSpace:     ld   a,(de)                                               ",
  "                        cp   \" \"                                                ",
  "                        ret  nz                 ; Found non space                 ",
  "                        inc  de                                                   ",
  "                        jr   __SetListSkipSpace                                   ",
  "__SetListCopy:          ld   a,(de)                                               ",
  "                        or   a                                                    ",
  "                        ret  z                  ; End string                      ",
  "                        cp   b                                                    ",
  "                        ret  z                  ; Delimiter found                 ",
  "                        ld   (hl),a                                               ",
  "                        inc  de                                                   ",
  "                        inc  hl                                                   ",
  "                        jr   __SetListCopy                                        "
} using GetElement;

function word GetElement() // Return the address of next element in list and update pointer
{
  "__GetElementLoad: ld   hl,0                                                               ",
  "                  ld   d,h                                                                ",
  "                  ld   e,l                                                                ",
  "__GetElementLoop: ld   a,(de)                                                             ",
  "                  inc  de                                                                 ",
  "                  or   a                                                                  ",
  "                  jr   nz,__GetElementLoop                                                ",
  "                  ld   (__GetElementLoad+1),de                                            ",
  "                  ret                                                                     ",
  "__GetElementData: defs 256                                                                "
}

function byte GoSubSelector(byte, word) // Call to line number corresponding to selector
{
  "ld   hl,2                                      ",
  "add  hl,sp                                     ",
  "ld   e,(hl)                                    ",
  "inc  hl                                        ",
  "ld   d,(hl) ; Label table to DE                ",
  "inc  hl                                        ",
  "inc  hl                                        ",
  "ld   a,(hl) ; Selector to A                    ",
  "or   a                                         ",
  "ret  z      ; Exit if selector is 0            ",
  "ld   l,a                                       ",
  "ld   h,0    ; Selector to HL (byte value)      ",
  "dec  hl     ; Selector to range 0 .. n-1       ",
  "add  hl,hl  ; Address offset of nth label to HL",
  "add  hl,de  ; Address of nth label to HL       ",
  "ld   a,(hl)                                    ",
  "inc  hl                                        ",
  "ld   h,(hl)                                    ",
  "ld   l,a    ; Line address to HL               ",
  "jp   (hl)                                      "
}

function byte GoToSelector(byte, word) // Jump to line number corresponding to selector
{
  "ld   hl,2                                      ",
  "add  hl,sp                                     ",
  "ld   e,(hl)                                    ",
  "inc  hl                                        ",
  "ld   d,(hl) ; Label table to DE                ",
  "inc  hl                                        ",
  "inc  hl                                        ",
  "ld   a,(hl) ; Selector to A                    ",
  "or   a                                         ",
  "ret  z      ; Exit if selector is 0            ",
  "pop  hl     ; Remove return address from stack ",
  "ld   l,a                                       ",
  "ld   h,0    ; Selector to HL (byte value)      ",
  "dec  hl     ; Selector to range 0 .. n-1       ",
  "add  hl,hl  ; Address offset of nth label to HL",
  "add  hl,de  ; Address of nth label to HL       ",
  "ld   a,(hl)                                    ",
  "inc  hl                                        ",
  "ld   h,(hl)                                    ",
  "ld   l,a    ; Line address to HL               ",
  "jp   (hl)                                      "
}

function byte KeyDefRepeat(byte, byte) // Set the state for a key repeat
{
  "ld   hl,3           ",
  "add  hl,sp          ",
  "ld   b,(hl)         ",
  "inc  hl             ",
  "inc  hl             ",
  "ld   a,(hl)         ",
  "jp   __km_set_repeat"
}

function byte KeyDefNormal(byte, byte) // Set the character that generates a key in normal mode
{
  "ld   hl,3              ",
  "add  hl,sp             ",
  "ld   b,(hl)            ",
  "inc  hl                ",
  "inc  hl                ",
  "ld   a,(hl)            ",
  "jp   __km_set_translate"
}

function byte KeyDefShift(byte, byte) // Set the character that generates a key in shift mode
{
  "ld   hl,3          ",
  "add  hl,sp         ",
  "ld   b,(hl)        ",
  "inc  hl            ",
  "inc  hl            ",
  "ld   a,(hl)        ",
  "jp   __km_set_shift"
}

function byte KeyDefControl(byte, byte) // Set the character that generates a key in control mode
{
  "ld   hl,3            ",
  "add  hl,sp           ",
  "ld   b,(hl)          ",
  "inc  hl              ",
  "inc  hl              ",
  "ld   a,(hl)          ",
  "jp   __km_set_control"
}

function inline byte MaskPattern(byte) // Set the mask pattern for lines
{
  "call __gra_set_line_mask"
}

function inline byte MaskFirst(byte) // Set the first point status for lines
{
  "call __gra_set_first"
}

function byte PrintStreamC(byte, byte) // Print character to stream specified as screen, printer or file
{
  "                       ld   hl,3                   ",
  "                       add  hl,sp                  ",
  "                       ld   b,(hl) ; Character to B",
  "                       inc  hl                     ",
  "                       inc  hl                     ",
  "                       ld   a,(hl) ; Stream to A   ",
  "                       cp   9                      ",
  "                       jr   z,__PrintStreamCFile   ",
  "                       cp   8                      ",
  "                       jr   z,__PrintStreamCPrinter",
  "                       call __txt_str_select       ",
  "                       ld   a,b                    ",
  "                       call __txt_output           ",
  "                       xor  a                      ",
  "                       jp   __txt_str_select       ",
  "__PrintStreamCFile:    ld   a,b                    ",
  "                       jp   __cas_out_char         ",
  "__PrintStreamCPrinter: ld   a,b                    ",
  "                       jp   __mc_print_char        "
}

function byte PrintStreamS(byte, word) // Print string to stream specified as screen, printer or file
{
  "                       ld   hl,2                          ",
  "                       add  hl,sp                         ",
  "                       ld   e,(hl)                        ",
  "                       inc  hl                            ",
  "                       ld   d,(hl) ; String to DE         ",
  "                       inc  hl                            ",
  "                       inc  hl                            ",
  "                       ld   a,(hl) ; Stream to A          ",
  "__PrintStreamSEntry:   cp   9                             ",
  "                       jr   z,__PrintStreamSFile          ",
  "                       cp   8                             ",
  "                       jr   z,__PrintStreamSPrinter       ",
  "                       call __txt_str_select              ",
  "                       ex   de,hl   ; String to HL        ",
  "                       call _PrintS                       ",
  "                       xor  a                             ",
  "                       jp   __txt_str_select              ",
  "__PrintStreamSFile:    ex   de,hl   ; String to HL        ",
  "                       jp   _FPrintS                      ",
  "__PrintStreamSPrinter: ex   de,hl   ; String to HL        ",
  "                       jp   _LPrints                      "
} using PrintS, FPrints, LPrintS;

function word InputStream(byte, word) // Get a line in string from stream specified as screen of file, returning string address
{
  "                   ld   hl,5                             ",
  "                   add  hl,sp                            ",
  "                   ld   a,(hl) ; Stream to A             ",
  "                   dec  hl                               ",
  "                   dec  hl                               ",
  "                   ld   d,(hl)                           ",
  "                   dec  hl                               ",
  "                   ld   e,(hl) ; Variable to DE          ",
  "                   push de     ; Save variable address   ",
  "                   cp   9                                ",
  "                   jr   z,__InputStreamFile              ",
  "                   call __txt_str_select                 ",
  "                   ex   de,hl  ; Variable to HL          ",
  "                   call _Input                           ",
  "                   xor  a                                ",
  "                   call __txt_str_select                 ",
  "                   pop  hl     ; Restore variable address",
  "                   ret                                   ",
  "__InputStreamFile: ex   de,hl  ; Variable to HL          ",
  "                   call _FInputS                         ",
  "                   pop  hl     ; Restore variable address",
  "                   ret                                   "
} using Input, FInputS;

function inline byte SetZone(byte) // Set the zone value
{
  "ld   (__ZoneLoad+1),a"
} using Zone;

function byte Zone() // Get the zone value
{
  "__ZoneLoad: ld   a,13",
  "            ret     "
}

function register byte CopyChrStream(byte)
{
  "call __txt_str_select                       ",
  "ld   b,a              ; Previous stream to B",
  "call __txt_rd_char                          ",
  "ld   c,a              ; Resulto to C        ",
  "ld   a,b              ;                     ",
  "call __txt_str_select ; Restore stream      ",
  "ld   a,c                                    ",
  "ret                                         "
}

function word InStr(word, word, word) // Return the position where the second string is is first string from the specified character, or 0 if not found
{
  "                   ld   hl,7                                                              ",
  "                   add  hl,sp                                                             ",
  "                   ld   b,(hl)                                                            ",
  "                   dec  hl                                                                ",
  "                   ld   c,(hl)              ; Start in BC                                 ",
  "                   dec  hl                                                                ",
  "                   ld   d,(hl)                                                            ",
  "                   dec  hl                                                                ",
  "                   ld   e,(hl)              ; String in DE                                ",
  "                   dec  hl                                                                ",
  "                   ld   a,(hl)                                                            ",
  "                   dec  hl                                                                ",
  "                   ld   l,(hl)                                                            ",
  "                   ld   h,a                 ; Search in HL                                ",
  "                   ld   a,(hl)                                                            ",
  "                   or   a                                                                 ",
  "                   jr   z,__InStrVoidSearch ; Search string is void                       ",
  "                   ex   de,hl               ; String in HL, search in DE                  ",
  "                   push hl                  ; Save string address                         ",
  "                   add  hl,bc                                                             ",
  "                   dec  hl                  ; Calculate address in string for start search",
  "                   pop  bc                  ; Restore string address                      ",
  "                   call __StrStr_1                                                        ",
  "                   ld   a,h                                                               ",
  "                   or   l                                                                 ",
  "                   ret  z                   ; Exit with result 0 if not found             ",
  "                   sbc  hl,bc                                                             ",
  "                   inc  hl                  ; Calculate position of search in string      ",
  "                   ret                                                                    ",
  "__InStrVoidSearch: sbc hl,hl                                                              ",
  "                   ret                                                                    "
} using StrStr;

function register word Rnd(word) // Return a random value according the given parameter
{
  "               call _sgnw        ; Calculate sign of parameter",
  "               ld   a,h                                       ",
  "               or   l                                         ",
  "               jr   z,__RndZero                               ",
  "               bit  7,h                                       ",
  "               jr   z,__RndPositive                           ",
  "               ld   hl,0                                      ",
  "               ld   (_rand+1),hl ; Initialize random sequence ",
  "__RndPositive: call _rand                                     ",
  "               ret                                            ",
  "__RndZero:     ld   hl,(_rand+1)                              ",
  "               ret                                            "
} using SgnW, Rand;

function register byte PosStream(byte)
{
  "call __txt_str_select                       ",
  "ld   b,a              ; Previous stream to B",
  "call __txt_get_cursor                       ",
  "ex   de,hl            ; Result to DE        ",
  "ld   a,b                                    ",
  "call __txt_str_select ; Restore stream      ",
  "ld   a,d                                    ",
  "ret                                         "
  }

function register byte VPosStream(byte)
{
  "call __txt_str_select                       ",
  "ld   b,a              ; Previous stream to B",
  "call __txt_get_cursor                       ",
  "ex   de,hl            ; Result to DE        ",
  "ld   a,b                                    ",
  "call __txt_str_select ; Restore stream      ",
  "ld   a,e                                    ",
  "ret                                         "
}

function register word Val(word) // Return the numeric value of the string
{
  "push hl         ; Save string address               ",
  "call _StrLen                                        ",
  "inc  hl         ; Increment for end string character",
  "call _GetMemory                                     ",
  "ex   de,hl      ; New space address to DE           ",
  "pop  bc         ; Restore string address            ",
  "call __StrCpy_0 ; Create copy of string             ",
  "call _StrUpr                                        ",
  "ld   a,(hl)     ; First character                   ",
  "cp   \"&\"                                          ",
  "jp   nz,_AToW   ; Decimal value                     ",
  "inc  hl                                             ",
  "ld   a,(hl)     ; Second character                  ",
  "inc  hl                                             ",
  "cp   \"X\"                                          ",
  "jp   z,_NToW    ; Binary value prefix &X            ",
  "cp   \"H\"                                          ",
  "jp   z,_HToW    ; Hexadecimal value prefix &        ",
  "dec  hl         ; Not second character for prefix   ",
  "jp   _HToW      ; Hexadecimal value prefix &H       "
} using StrLen, GetMemory, StrCpy, StrUpr, AToW, NToW, HToW;

function register word FormatNumber(word) // Return the address of numeric value as string trimming leading zeros
{
  "__FormatNumberLoop: ld   a,(hl)                                                  ",
  "                    or   a                                                       ",
  "                    jr   z,__FormatNumberEnd ; Jump if end string is found       ",
  "                    cp   \"0\"                                                   ",
  "                    ret  nz                  ; Exit if digit 0 is found          ",
  "                    inc  hl                                                      ",
  "                    jr   __FormatNumberLoop                                      ",
  "__FormatNumberEnd:  dec  hl                  ; Decrement to pointer to last digit",
  "                    ret                                                          "
}

function word FormatPattern(word, word) // Return the address of pattern with the numeric value as string applied over
{
  "                           ld   hl,5                                                                           ",
  "                           add  hl,sp                                                                          ",
  "                           ld   d,(hl)                                                                         ",
  "                           dec  hl                                                                             ",
  "                           ld   e,(hl)                                                                         ",
  "                           ex   de,hl                         ; Parameter pointer to DE, pattern to HL         ",
  "                           push de                            ; Save parameter pointer                         ",
  "                           call __FormatPatternLength         ; End pattern to HL, pattern length to B         ",
  "                           ld   a,b                                                                            ",
  "                           ld   (__FormatPatternLoadCopy+1),a ; Store pattern length                           ",
  "                           ex   (sp),hl                       ; End pattern to stack, restore parameter pointer",
  "                           dec  hl                                                                             ",
  "                           ld   a,(hl)                                                                         ",
  "                           dec  hl                                                                             ",
  "                           ld   l,(hl)                                                                         ",
  "                           ld   h,a                           ; Digits to HL                                   ",
  "                           call __FormatPatternLength         ; End digits to HL, digits length to B           ",
  "__FormatPatternLoadCopy:   ld c,0                             ; Pattern length                                 ",
  "                           pop  de                            ; Restore end pattern                            ",
  "__FormatPatternLoopCopy:   ld a,c                                                                              ",
  "                           or   a                                                                              ",
  "                           jr   z,__FormatPatternEnd          ; End pattern                                    ",
  "                           dec  c                                                                              ",
  "                           dec  de                            ; Previous pattern position                      ",
  "                           ld   a,(de)                        ; Pattern place                                  ",
  "                           cp   \"#\"                                                                          ",
  "                           jr   z,__FormatPatternDigit        ; Is digit place                                 ",
  "                           cp   \"*\"                                                                          ",
  "                           jr   z,__FormatPatternDigit        ; Is digit place                                 ",
  "                           cp   \"0\"                                                                          ",
  "                           jr   nz,__FormatPatternLoopCopy    ; Not digit place                                ",
  "__FormatPatternDigit:      dec hl                             ; Previous digit position                        ",
  "                           ld   a,(hl)                        ; Digit                                          ",
  "                           ld   (de),a                        ; Store digit in patter                          ",
  "                           djnz __FormatPatternLoopCopy                                                        ",
  "__FormatPatternClear:      ld a,c                                                                              ",
  "                           or   a                                                                              ",
  "                           jr   z,__FormatPatternEnd                                                           ",
  "                           dec  c                                                                              ",
  "                           dec  de                            ; Previous pattern position                      ",
  "                           ld   a,(de)                        ; Pattern place                                  ",
  "                           cp   \".\"                                                                          ",
  "                           jr   z,__FormatPatternBlank        ; Is position to replace                         ",
  "                           cp   \",\"                                                                          ",
  "                           jr   z,__FormatPatternBlank        ; Is position to replace                         ",
  "                           cp   \"#\"                                                                          ",
  "                           jr   nz,__FormatPatternClear       ; Not position to replace                        ",
  "__FormatPatternBlank:      ld a,\" \"                                                                          ",
  "                           ld   (de),a                        ; Replace in pattern copy with space             ",
  "                           jr   __FormatPatternClear                                                           ",
  "__FormatPatternEnd:        ex de,hl                           ; Begin of pattern copy to HL                    ",
  "                           ret                                                                                 ",
  "__FormatPatternLength:     ld b,0                                                                              ",
  "__FormatPatternLengthLoop: ld a,(hl)                                                                           ",
  "                           or   a                                                                              ",
  "                           ret  z                                                                              ",
  "                           inc  b                                                                              ",
  "                           inc  hl                                                                             ",
  "                           jr   __FormatPatternLengthLoop                                                      "
}

function register word GetMemory(word) // Return the address of a free memory space of length specified
{
  "                   ld   de,(__GetMemoryFree) ; Get beginning of free memory                          ",
  "                   ex   de,hl                ; Bytes to reserve to DE, beginning of free memory to HL",
  "                   add  hl,de                ; Calculate new beginning of free memory                ",
  "                   ld   bc,__begin_program+1                                                         ",
  "                   or   a                                                                            ",
  "                   sbc  hl,bc                ; Test if exceed the end of the dynamic memory          ",
  "                   jr   nc,__GetMemoryExceed ; Jump if end of dynamic memory exceed                  ",
  "                   add  hl,bc                ; Restore new beginning of free memory                  ",
  "                   ld   (__GetMemoryFree),hl ; Store new beginning of free memory                    ",
  "                   or   a                                                                            ",
  "                   sbc  hl,de                ; Restore previous beginning of free memory             ",
  "                   ret                                                                               ",
  "__GetMemoryExceed: ld hl,__GetMemoryBegin                                                            ",
  "                   add  hl,de                ; Calculate new beginning of free memory                ",
  "                   ld   (__GetMemoryFree),hl ; Store new beginning of free memory                    ",
  "                   sbc  hl,de                ; Restore initial free memory address                   ",
  "                   ret                                                                               ",
  "__GetMemoryFree:   defw __GetMemoryBegin                                                             ",
  "__GetMemoryBegin:  equ #170                                                                          "
}

function register word StringCopy(word) // Copy the string in a new space from dynamic memory, returning address of new space
{
  "push hl         ; Save string address                   ",
  "call _StrLen    ; Get string length                     ",
  "inc  hl         ; Add to length for end string character",
  "call _GetMemory ; Get memory space for copy of string   ",
  "ex   de,hl      ; Move to DE address of new space       ",
  "pop  bc         ; Restore string address                ",
  "jp   __StrCpy_0                                         "
} using StrLen, GetMemory, StrCpy;

function word StringCopyLength(word, word) // Copy n characters of the string in a new space from dynamic memory, returning address of new space
{
  "ld   hl,5                                          ",
  "add  hl,sp                                         ",
  "ld   d,(hl)                                        ",
  "dec  hl                                            ",
  "ld   e,(hl)     ; String address to DE             ",
  "push de         ; Save string address              ",
  "dec  hl                                            ",
  "ld   a,(hl)                                        ",
  "dec  hl                                            ",
  "ld   l,(hl)                                        ",
  "ld   h,a        ; Length to HL                     ",
  "push hl         ; Save length                      ",
  "inc  hl         ; Increment to end string character",
  "call _GetMemory ; New memory space in HL           ",
  "pop  bc         ; Restore length                   ",
  "pop  de         ; Restore string address           ",
  "jp   __StrNCpy_0                                   "
} using GetMemory, StrNCpy;

function word StringCopyLengthEnd(word, word) // Copy n characters of the string at end in a new space from dynamic memory, returning address of new space
{
  "ld   hl,2                                       ",
  "add  hl,sp                                      ",
  "ld   c,(hl)                                     ",
  "inc  hl                                         ",
  "ld   b,(hl)  ; Length to BC                     ",
  "inc  hl                                         ",
  "ld   a,(hl)                                     ",
  "inc  hl                                         ",
  "ld   h,(hl)                                     ",
  "ld   l,a     ; String address to HL             ",
  "call _StrLen ; End string address + 1 to DE     ",
  "dec  de      ; Decrement to point to end string ",
  "ex   de,hl   ; End string address to HL         ",
  "sbc  hl,bc   ; Calculate begin of substring     ",
  "push hl      ; Save begin of substring          ",
  "inc  hl      ; Increment to end string character",
  "call _GetMemory                                 ",
  "ex   de,hl   ; New space address to DE          ",
  "pop  bc      ; Restore begin of substring       ",
  "jp   __StrCpy_0                                 "
} using StrLen, GetMemory, StrCpy;

function word StringSet(byte, word) // Generate a string in a new space with n characters filled with value
{
  "ld   hl,5                                          ",
  "add  hl,sp                                         ",
  "ld   a,(hl)     ; Character to A                   ",
  "push af                                            ",
  "dec  hl                                            ",
  "dec  hl                                            ",
  "ld   a,(hl)                                        ",
  "dec  hl                                            ",
  "ld   l,(hl)                                        ",
  "ld   h,a        ; Length to HL                     ",
  "push hl                                            ",
  "inc  hl         ; Increment to end string character",
  "call _GetMemory ; New space in HL                  ",
  "pop  bc         ; Restore length                   ",
  "pop  de         ; Restore character in D           ",
  "jp   __StrSet_0                                    "
} using GetMemory, StrSet;

function inline word StringCharacter(byte) // Generate a string in a new space with one character
{
  "ld   hl,2                                   ",
  "call _GetMemory ; Get new space for string  ",
  "ld   (hl),a                                 ",
  "inc  hl                                     ",
  "ld   (hl),0                                 ",
  "dec  hl         ; Restore begin of new space"
} using GetMemory;

function word Concat(word, word) // Concat two strings in a new space
{
  "ld   hl,2                                           ",
  "add  hl,sp                                          ",
  "ld   c,(hl)                                         ",
  "inc  hl                                             ",
  "ld   b,(hl)                                         ",
  "inc  hl                                             ",
  "ld   a,(hl)                                         ",
  "inc  hl                                             ",
  "ld   h,(hl)                                         ",
  "ld   l,a        ; First string to HL                ",
  "push bc         ; Save second string                ",
  "push hl         ; Save first string                 ",
  "call _StrLen    ; Length of first string            ",
  "push hl         ; Save length of first string       ",
  "ld   h,b                                            ",
  "ld   l,c        ; Second string to HL               ",
  "call _StrLen                                        ",
  "pop  de         ; Restore length of first string    ",
  "add  hl,de      ; Length of both string to HL       ",
  "inc  hl         ; Increment for end string character",
  "call _GetMemory                                     ",
  "ex   de,hl      ; New space to DE                   ",
  "pop  bc         ; Restore first string              ",
  "call __StrCpy_0 ; Copy first string to new space    ",
  "ex   de,hl      ; New space to DE                   ",
  "pop  bc         ; Restore second string             ",
  "jp   __StrCat_0 ; Concat second string to new space "
} using StrLen, GetMemory, StrCpy, StrCat;

function byte StringCopyValue(word, word, byte) // Copy n bytes or to end without end string character from second string to first string
{
  "                       ld   hl,3                                       ",
  "                       add  hl,sp                                      ",
  "                       ld   b,(hl) ; Characters to copy to B           ",
  "                       inc  hl                                         ",
  "                       ld   e,(hl)                                     ",
  "                       inc  hl                                         ",
  "                       ld   d,(hl) ; Second string to DE               ",
  "                       inc  hl                                         ",
  "                       ld   a,(hl)                                     ",
  "                       inc  hl                                         ",
  "                       ld   h,(hl)                                     ",
  "                       ld   l,a    ; First string to HL                ",
  "__StringCopyValueLoop: ld   a,b                                        ",
  "                       or   a                                          ",
  "                       ret  z      ; Exit if characters to copy is zero",
  "                       ld   a,(de)                                     ",
  "                       or   a                                          ",
  "                       ret  z      ; Exit if end of second string      ",
  "                       ld   (hl),a                                     ",
  "                       inc  de                                         ",
  "                       inc  hl                                         ",
  "                       dec  b                                          ",
  "                       jr   __StringCopyValueLoop                      "
}

function inline word Boolean(word) // Return 0 or -1 depending on condition received
{
  "ld   a,h     ",
  "or   l       ",
  "jr   z,$+5   ",
  "ld   hl,#FFFF"
}

function byte RsxReal()
{
  "                 ld   hl,__RealWorkspace                                                             ",
  "                 ld   bc,__RealJumps                                                                 ",
  "                 jp   __kl_log_ext                                                                   ",
  "__RealWorkspace: defs 4                                                                              ",
  "__RealJumps:     defw __RealNames                                                                    ",
  "                 jp   __RealAbs                                                                      ",
  "                 jp   __RealAdd                                                                      ",
  "                 jp   __RealAtn                                                                      ",
  "                 jp   __RealCint                                                                     ",
  "                 jp   __RealCmp                                                                      ",
  "                 jp   __RealCos                                                                      ",
  "                 jp   __RealCreal                                                                    ",
  "                 jp   __RealDeg                                                                      ",
  "                 jp   __RealDiv                                                                      ",
  "                 jp   __RealExp                                                                      ",
  "                 jp   __RealFix                                                                      ",
  "                 jp   __RealInt                                                                      ",
  "                 jp   __RealLet                                                                      ",
  "                 jp   __RealLog                                                                      ",
  "                 jp   __RealLog10                                                                    ",
  "                 jp   __RealMul                                                                      ",
  "                 jp   __RealPi                                                                       ",
  "                 jp   __RealPow                                                                      ",
  "                 jp   __RealRad                                                                      ",
  "                 jp   __RealRev                                                                      ",
  "                 jp   __RealRound                                                                    ",
  "                 jp   __RealSgn                                                                      ",
  "                 jp   __RealSin                                                                      ",
  "                 jp   __RealSqr                                                                      ",
  "                 jp   __RealStr                                                                      ",
  "                 jp   __RealSub                                                                      ",
  "                 jp   __RealTan                                                                      ",
  "                 jp   __RealVal                                                                      ",
  "__RealNames:     defb \"A\",\"B\",\"S\"+128                                                          ",
  "                 defb \"A\",\"D\",\"D\"+128                                                          ",
  "                 defb \"A\",\"T\",\"N\"+128                                                          ",
  "                 defb \"C\",\"I\",\"N\",\"T\"+128                                                    ",
  "                 defb \"C\",\"M\",\"P\"+128                                                          ",
  "                 defb \"C\",\"O\",\"S\"+128                                                          ",
  "                 defb \"C\",\"R\",\"E\",\"A\",\"L\"+128                                              ",
  "                 defb \"D\",\"E\",\"G\"+128                                                          ",
  "                 defb \"D\",\"I\",\"V\"+128                                                          ",
  "                 defb \"E\",\"X\",\"P\"+128                                                          ",
  "                 defb \"F\",\"I\",\"X\"+128                                                          ",
  "                 defb \"I\",\"N\",\"T\"+128                                                          ",
  "                 defb \"L\",\"E\",\"T\"+128                                                          ",
  "                 defb \"L\",\"O\",\"G\"+128                                                          ",
  "                 defb \"L\",\"O\",\"G\",\"1\",\"0\"+128                                              ",
  "                 defb \"M\",\"U\",\"L\"+128                                                          ",
  "                 defb \"P\",\"I\"+128                                                                ",
  "                 defb \"P\",\"O\",\"W\"+128                                                          ",
  "                 defb \"R\",\"A\",\"D\"+128                                                          ",
  "                 defb \"R\",\"E\",\"V\"+128                                                          ",
  "                 defb \"R\",\"O\",\"U\",\"N\",\"D\"+128                                              ",
  "                 defb \"S\",\"G\",\"N\"+128                                                          ",
  "                 defb \"S\",\"I\",\"N\"+128                                                          ",
  "                 defb \"S\",\"Q\",\"R\"+128                                                          ",
  "                 defb \"S\",\"T\",\"R\"+128                                                          ",
  "                 defb \"S\",\"U\",\"B\"+128                                                          ",
  "                 defb \"T\",\"A\",\"N\"+128                                                          ",
  "                 defb \"V\",\"A\",\"L\"+128                                                          ",
  "                 defb 0                                                                              ",
  "__RealAbs:       call __RealLet       ; Copy second value on first                                   ",
  "                 inc  hl                                                                             ",
  "                 inc  hl                                                                             ",
  "                 inc  hl                                                                             ",
  "                 res  7,(hl)          ; Set positive sign of value                                   ",
  "                 ret                                                                                 ",
  "__RealAdd:       cp 3                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   d,(ix+5)                                                                       ",
  "                 ld   e,(ix+4)        ; Index of destination to DE                                   ",
  "                 ld   h,(ix+3)                                                                       ",
  "                 ld   l,(ix+2)        ; Index of first operand to HL                                 ",
  "                 call __RealCopy      ; Address of destination to HL                                 ",
  "                 ld   d,(ix+1)                                                                       ",
  "                 ld   e,(ix+0)        ; Index of second operand to DE                                ",
  "                 ex   de,hl           ; Address of destination to DE, index of second operand to HL  ",
  "                 call __RealAddress   ; Address of second operand to HL                              ",
  "                 ex   de,hl           ; Address of second operand to DE, address of destination to HL",
  "                 jp   __Real_addition                                                                ",
  "__RealAtn:       call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_arctangent                                                              ",
  "__RealCint:      cp 2                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   h,(ix+3)                                                                       ",
  "                 ld   l,(ix+2)        ; Address of result to HL                                      ",
  "                 push hl              ; Save addres of result                                        ",
  "                 ld   h,(ix+1)                                                                       ",
  "                 ld   l,(ix+0)        ; Index of real value to HL                                    ",
  "                 call __RealAddress   ; Address of real value to HL                                  ",
  "                 call __Real_to_integer                                                              ",
  "                 pop  de              ; Restore address of result                                    ",
  "                 ex   de,hl           ; Result to DE, address of result to HL                        ",
  "                 ld   (hl),e                                                                         ",
  "                 inc  hl                                                                             ",
  "                 ld   (hl),d          ; Store result                                                 ",
  "                 ret                                                                                 ",
  "__RealCmp:       cp 3                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   h,(ix+1)                                                                       ",
  "                 ld   l,(ix+0)        ; Index of second value to HL                                  ",
  "                 call __RealAddress   ; Address of second value to HL                                ",
  "                 ld   d,(ix+3)                                                                       ",
  "                 ld   e,(ix+2)        ; Index of first value to DE                                   ",
  "                 ex   de,hl           ; Address of second value to DE, index of first value to HL    ",
  "                 call __RealAddress   ; Address of first value to HL                                 ",
  "                 ld   b,(ix+5)                                                                       ",
  "                 ld   c,(ix+4)        ; Address of result to BC                                      ",
  "                 call __Real_comparison                                                              ",
  "                 ld   (bc),a          ; Store result                                                 ",
  "                 ret                                                                                 ",
  "__RealCos:       call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_cosine                                                                  ",
  "__RealCreal:     cp 2                                                                                ",
  "                 jp   nz,__RealError  ; Test number or parameters                                    ",
  "                 ld   h,(ix+3)                                                                       ",
  "                 ld   l,(ix+2)        ; Index of destination to HL                                   ",
  "                 call __RealAddress   ; Addres of destination to HL                                  ",
  "                 ld   d,(ix+1)                                                                       ",
  "                 ld   e,(ix+0)        ; Value of origin to DE                                        ",
  "                 ex   de,hl           ; Address of destination to DE, value of origin to HL          ",
  "                 xor  a               ; Set sign positive                                            ",
  "                 jp   __integer_to_real                                                              ",
  "__RealDeg:       or a                                                                                ",
  "                 jp   nz,__RealError  ; Test number or parameters                                    ",
  "                 inc  a                                                                              ",
  "                 jp   __set_angle_mode                                                               ",
  "__RealDiv:       cp 3                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   d,(ix+5)                                                                       ",
  "                 ld   e,(ix+4)        ; Index of destination to DE                                   ",
  "                 ld   h,(ix+3)                                                                       ",
  "                 ld   l,(ix+2)        ; Index of first operand to HL                                 ",
  "                 call __RealCopy      ; Address of destination to HL                                 ",
  "                 ld   d,(ix+1)                                                                       ",
  "                 ld   e,(ix+0)        ; Index of second operand to DE                                ",
  "                 ex   de,hl           ; Address of destination to DE, index of second operand to HL  ",
  "                 call __RealAddress   ; Address of second operand to HL                              ",
  "                 ex   de,hl           ; Address of second operand to DE, address of destination to HL",
  "                 jp   __Real_division                                                                ",
  "__RealExp:       call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_exp                                                                     ",
  "__RealFix:       call __RealLet                                                                      ",
  "                 call __Real_fix                                                                     ",
  "                 ld   a,b                                                                            ",
  "                 jp   __binary_to_real                                                               ",
  "__RealInt:       call __RealLet                                                                      ",
  "                 call __Real_int                                                                     ",
  "                 ld   a,b                                                                            ",
  "                 jp   __binary_to_real                                                               ",
  "__RealLet:       cp 2                                                                                ",
  "                 jp   nz,__RealError  ; Test number or parameters                                    ",
  "                 ld   d,(ix+3)                                                                       ",
  "                 ld   e,(ix+2)        ; Index of destination to DE                                   ",
  "                 ld   h,(ix+1)                                                                       ",
  "                 ld   l,(ix+0)        ; Index of origin to HL                                        ",
  "                 jp   __RealCopy                                                                     ",
  "__RealLog:       call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_log                                                                     ",
  "__RealLog10:     call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_log_10                                                                  ",
  "__RealMul:       cp 3                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   d,(ix+5)                                                                       ",
  "                 ld   e,(ix+4)        ; Index of destination to DE                                   ",
  "                 ld   h,(ix+3)                                                                       ",
  "                 ld   l,(ix+2)        ; Index of first operand to HL                                 ",
  "                 call __RealCopy      ; Address of destination to HL                                 ",
  "                 ld   d,(ix+1)                                                                       ",
  "                 ld   e,(ix+0)        ; Index of second operand to DE                                ",
  "                 ex   de,hl           ; Address of destination to DE, index of second operand to HL  ",
  "                 call __RealAddress   ; Address of second operand to HL                              ",
  "                 ex   de,hl           ; Address of second operand to DE, address of destination to HL",
  "                 jp   __Real_multiplication                                                          ",
  "__RealPi:        cp 1                                                                                ",
  "                 jp   nz,__RealError  ; Test number or parameters                                    ",
  "                 ld   h,(ix+1)                                                                       ",
  "                 ld   l,(ix+0)        ; Index of destination to HL                                   ",
  "                 call __RealAddress                                                                  ",
  "                 jp   __Real_pi                                                                      ",
  "__RealPow:       cp 3                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   d,(ix+5)                                                                       ",
  "                 ld   e,(ix+4)        ; Index of destination to DE                                   ",
  "                 ld   h,(ix+3)                                                                       ",
  "                 ld   l,(ix+2)        ; Index of first operand to HL                                 ",
  "                 call __RealCopy      ; Address of destination to HL                                 ",
  "                 ld   d,(ix+1)                                                                       ",
  "                 ld   e,(ix+0)        ; Index of second operand to DE                                ",
  "                 ex   de,hl           ; Address of destination to DE, index of second operand to HL  ",
  "                 call __RealAddress   ; Address of second operand to HL                              ",
  "                 ex   de,hl           ; Address of second operand to DE, address of destination to HL",
  "                 jp   __Real_power                                                                   ",
  "__RealRad:       or a                                                                                ",
  "                 jp   nz,__RealError  ; Test number or parameters                                    ",
  "                 jp   __set_angle_mode                                                               ",
  "__RealRev:       call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_unary_minus                                                             ",
  "__RealRound:     cp 3                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   d,(ix+5)                                                                       ",
  "                 ld   e,(ix+4)        ; Index of destination to DE                                   ",
  "                 ld   h,(ix+3)                                                                       ",
  "                 ld   l,(ix+2)        ; Index of value to HL                                         ",
  "                 call __RealCopy      ; Address of destination to HL                                 ",
  "                 ld   a,(ix+0)        ; Number of decimals to A on range 0..255                      ",
  "                 push af              ; Save number of decimals                                      ",
  "                 call __Real_10a      ; Multiply value by 10E+<decimals>                             ",
  "                 call __Real_to_binary                                                               ",
  "                 ld   a,b                                                                            ",
  "                 call __binary_to_real                                                               ",
  "                 pop  af              ; Restore number of decimals                                   ",
  "                 neg                  ; Change sign to number of decimals                            ",
  "                 jp   __Real_10a      ; Divide value by 10E+<decimals>                               ",
  "__RealSgn:       cp 2                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   d,(ix+3)                                                                       ",
  "                 ld   e,(ix+2)        ; Address of result to DE                                      ",
  "                 ld   h,(ix+1)                                                                       ",
  "                 ld   l,(ix+0)        ; Index of value to HL                                         ",
  "                 call __RealAddress   ; Address of value to HL                                       ",
  "                 call __Real_signum_sgn                                                              ",
  "                 ld   (de),a          ; Store result                                                 ",
  "                 ret                                                                                 ",
  "__RealSin:       call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_sine                                                                    ",
  "__RealSqr:       call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_sqr                                                                     ",
  "__RealStr:       cp 2                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   h,(ix+3)                                                                       ",
  "                 ld   l,(ix+2)        ; Address of string descriptor to HL                           ",
  "                 inc  hl              ; Skip string length address                                   ",
  "                 ld   e,(hl)                                                                         ",
  "                 inc  hl                                                                             ",
  "                 ld   d,(hl)          ; Address of string value to DE                                ",
  "                 ld   h,(ix+1)                                                                       ",
  "                 ld   l,(ix+0)        ; Index of value to HL                                         ",
  "                 call __RealAddress   ; Address of value to HL                                       ",
  "                 ex   de,hl           ; Address of value to DE, address of string to HL              ",
  "                 jp   __ftoa_0                                                                       ",
  "__RealSub:       cp 3                                                                                ",
  "                 jp   nz,__RealError                                                                 ",
  "                 ld   d,(ix+5)                                                                       ",
  "                 ld   e,(ix+4)        ; Index of destination to DE                                   ",
  "                 ld   h,(ix+1)                                                                       ",
  "                 ld   l,(ix+0)        ; Index of second operand to HL                                ",
  "                 call __RealCopy      ; Address of destination to HL                                 ",
  "                 ld   d,(ix+3)                                                                       ",
  "                 ld   e,(ix+2)        ; Index of first operand to DE                                 ",
  "                 ex   de,hl           ; Address of destination to DE, index of first operand to HL   ",
  "                 call __RealAddress   ; Address of first operand to HL                               ",
  "                 ex   de,hl           ; Address of first operand to DE, address of destination to HL ",
  "                 jp   __Real_reverse_subtraction                                                     ",
  "__RealTan:       call __RealLet       ; Copy second value on first                                   ",
  "                 jp   __Real_tangent                                                                 ",
  "__RealVal:       ld h,(ix+3)                                                                         ",
  "                 ld   l,(ix+2)        ; Index of value to HL                                         ",
  "                 call __RealAddress   ; Address of value to HL                                       ",
  "                 push hl              ; Store address of value                                       ",
  "                 ld   h,(ix+1)                                                                       ",
  "                 ld   l,(ix+0)        ; Address of string descriptor to HL                           ",
  "                 inc  hl                                                                             ",
  "                 ld   e,(hl)                                                                         ",
  "                 inc  hl                                                                             ",
  "                 ld   d,(hl)          ; Address of string value to DE                                ",
  "                 push de              ; Store addres of string value                                 ",
  "                 call _atof                                                                          ",
  "                 inc  sp                                                                             ",
  "                 inc  sp                                                                             ",
  "                 inc  sp                                                                             ",
  "                 inc  sp              ; Restore stack pointer                                        ",
  "                 ret                                                                                 ",
  "__RealCopy:      call __RealAddress   ; Address of second real to HL                                 ",
  "                 ex   de,hl           ; Address of second real to DE, index of first real to HL      ",
  "                 call __RealAddress   ; Address of first real to HL                                  ",
  "                 jp   __move_real                                                                    ",
  "__RealAddress:   ld b,h                                                                              ",
  "                 ld   c,l             ; Copy index of real to BC                                     ",
  "                 add  hl,hl                                                                          ",
  "                 add  hl,hl                                                                          ",
  "                 add  hl,bc           ; Index of real * 5 to HL                                      ",
  "                 ld   bc,_RealValues ; Table of reals to BC                                          ",
  "                 add  hl,bc           ; Address of real to HL                                        ",
  "                 ret                                                                                 ",
  "__RealError:     ld hl,__RealMessage                                                                 ",
  "                 call _prints                                                                        ",
  "__RealErrorLoop: jr __RealErrorLoop                                                                  ",
  "__RealMessage:   defb \"R\",\"S\",\"X\",\" \",\"e\",\"r\",\"r\",\"o\",\"r\",0                        ",
} using AToF, FToA, PrintS;
