/*
-----------------------------------------------------------------------------
This source file is part of OpenSpace3D
For the latest info, see http://www.openspace3d.com

Copyright (c) 2012 I-maginer

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt

-----------------------------------------------------------------------------
*/

/*
applet file generator
origin by Sylvain Huet - oct 2003

Bastien Bourineau - june 2009
*/

struct FtpSetting= [
  AFTP_telnet       : TELNET,
  AFTP_trmTimeout   : Timer,
  AFTP_sDataCmd     : S,
  AFTP_sIp          : S,
  AFTP_sHost        : S,
  AFTP_iport        : I,
  AFTP_sLogin       : S,
  AFTP_sPass        : S,
  AFTP_sDir         : S,
  AFTP_sAppDir      : S,
  AFTP_sUrl         : S,
  AFTP_bWebIn       : I,
  AFTP_lFiles       : [S r1],
  AFTP_lDirs        : [S r1],
  AFTP_wLogFile     : W,
  
  AFTP_ctrlWindow   : EdWindow,
  AFTP_ctrlHost     : EdControl,
  AFTP_ctrlPort     : EdControl,
  AFTP_ctrlLogin    : EdControl,
  AFTP_ctrlPass     : EdControl,
  AFTP_ctrlRoot     : EdControl,
  AFTP_ctrlDir      : EdControl,
  AFTP_ctrlWww      : EdControl,
  AFTP_ctrlInWeb    : EdControl,
  AFTP_ctrlUpload   : EdControl,
  
  AFTP_ctrlLog      : EdControl,
  AFTP_ctrlOk       : EdControl,
  AFTP_ctrlCancel   : EdControl,
  AFTP_bError       : I,
  AFTP_iState       : I,
  AFTP_iLogged      : I
  
  ] mkFtpSetting ;;


var sMkAppletPath    = "os3dlib/res/web/";;
var sMkAppletTmpPath = "tmp/mkapplet/";;

typeof winMkApplet   = EdWindow;;

var iTimeOut         = 60000;;
var iTimeOutCmd      = 10000;;
var iOS3DPackMaxZipBuffer = 268435456;;

var sExportDirectory = "export";;
var lConfidentialMarks = "ftpHost"::"ftpPort"::"ftpLogin"::"ftpRoot"::"ftpDir"::"ftpWWW"::"ftpIntegrated"::"ftpUpload"::nil;;

proto sendFtpCommand = fun[FtpSetting S I] I;;
proto ftpConnect     = fun[FtpSetting] I;;
proto getMkAppletXmlResources = fun [S [S r1]] [[S r1] [S r1]];;
proto getProjectSetting = fun [S] S;;
proto getProjectSettingDef = fun [S S] S;;
proto setProjectSetting = fun [S S] I;;
proto getProjectVersion = fun [] S;;

proto mkAppletAddLog = fun [FtpSetting S] I;;
proto mkPakAll = fun [FtpSetting [S r1] W fun [] I] I;;
proto mkWebPakAll = fun [EdControl [S r1] W fun [] I] I;;

// protos Android
proto makeAndroidAppBundle = fun [S S] [P S];;
proto signAndroidAppBundle = fun [P P S S] [P S];;
proto encryptAndroidSigninKey = fun [P S S P] [P S];;
proto makeAndroidSigninKey = fun [W S S [[S S] r1]] [P S];;
proto makeAndroidAPK = fun [S S] [P S];;
proto signAndroidAPK = fun [P P S S] [P S];;
proto installAndroidAPK = fun [P] I;;

proto mkOS3DPakAll = fun [[S r1] W W fun [] I] I;;

fun checkPlatform(file)=
  _addPartition "./" 2;
  let _checkpack file -> pfile in
  let if (pfile == nil) then 0 else 1 -> ret in
  (
    _removeLastPartition;
    ret;
  );;

var lPlatformPlugins = ["win" "androiddeployer"::"emotiv"::"eyetracking"::"glove"::"joypad"::"leapmotion"::"lib2d24"::
                              "mmedia24"::"myo"::"neurosky"::"nonin"::"oculus"::"openniscol"::"optitrack"::
                              "respirationbelt"::"rpigpio"::"s3drudder"::"scolsql"::"sensor"::"serialio"::"sopenvr"::
                              "spacepointfusion"::"spdf"::"speech"::"sqlite3"::"stuio"::"svrpn"::"tobii"::"usbuirt"::
                              "vuzix"::"wiimote"::"wsystem"::"x10"::"xtension"::"zoogl24"::nil]::
                       ["linux" "joypad"::"rpigpio"::"sensor"::"serialio"::"spdf"::"sqlite3"::"stuio"::"svrpn"::nil]::
                       ["android" "joypad"::"sensor"::"serialio"::"spdf"::"sqlite3"::"svrpn"::nil]::
                       ["ios" "joypad"::"sensor"::"sqlite3"::nil]::
                       ["macOS" "joypad"::"sensor"::"serialio"::"spdf"::"sqlite3"::"stuio"::"svrpn"::nil]::
                       nil;;
var lPluginsBase = "libos2d24"::"so3engine"::"security"::"bitmaptoolkit"::"audio"::"scurl"::"sxml"::nil;;

/* ********************************************************************************************* /
  PAK Functions
/ ********************************************************************************************* */
fun copyFileContentOpt(from, to, case)=
  if (((_checkpack from) == nil) || (to == nil)) then nil else
  let getFileExt from -> ext in
  if (!strcmpi ext "xos") then //test for xos file and remove private content
  (
    let XMLload from -> xmlstr in
    (
      let XMLgetMarkByValue xmlstr "project" -> srcprjmark in
      let XMLgetMarkByValueFromMarkSons srcprjmark "setting" -> srcsettingmark in
      let sizelist lConfidentialMarks -> size in
      let 0 -> i in
      (
        while (i < size) do
        (
          let nth_list lConfidentialMarks i -> key in
          let XMLgetMarkByValueFromMarkSons srcsettingmark key -> mark in
          if (mark == nil) then nil else
            XMLdelMark xmlstr mark;
          
          set i = i + 1;
        );
      );
      
      if (case) then
        _storepack2 XMLserializeZipped xmlstr to
      else
        _storepack XMLserializeZipped xmlstr to;
    );
  )
  else
  (
    if (!case) then
    (
      _CopyFile (_checkpack from) (_getmodifypack to);
      //addLogMessage strcatn "Copy file : "::from::" to "::to::nil;
      /*      
      let _getmodifypack to -> tow in
      let _FILEOpen _channel _checkpack from -> file in
      let _FILESize file -> filesize in
      if (file == nil) then nil else
      (
        while ((_FILETell file) < filesize) do
          _appendpack (_FILERead file 65534) tow;
                
        _FILEClose file;
      );
      */
      0;
    )
    else
    (
      //_getmodifypack is case insensivity only
      //addLogMessage strcatn "Copy file with case : "::from::" to "::to::nil;
      _storepack2 (_getpack _checkpack from) to;
      0;
    );
  );
  0;;


fun copyFileContentC(from, to)=
  copyFileContentOpt from to 1;;


fun copyFileContent(from, to)=
  copyFileContentOpt from to 0;;


fun getFileContent(file)=
  //test for xos file and remove private content
  let getFileExt file -> ext in
  if (!strcmpi ext "xos") then
  (
    let XMLload file -> xmlstr in
    (
      let XMLgetMarkByValue xmlstr "project" -> srcprjmark in
      let XMLgetMarkByValueFromMarkSons srcprjmark "setting" -> srcsettingmark in
      let sizelist lConfidentialMarks -> size in
      let 0 -> i in
      (
        while (i < size) do
        (
          let nth_list lConfidentialMarks i -> key in
          let XMLgetMarkByValueFromMarkSons srcsettingmark key -> mark in
          if (mark == nil) then nil else
            XMLdelMark xmlstr mark;
          
          set i = i + 1;
        );
      );
      
     XMLserializeZipped xmlstr;
    );
  )
  else
  (
    _getpack _checkpack file;
  );;


fun mkDTime(ttime)=
  let ctime ttime -> ftime in
  let substr ftime  4  3 -> mounth in
  let substr ftime  8  2 -> num in
  let substr ftime 20  4 -> an in
  let substr ftime 11  2 -> hour in
  let substr ftime 14  2 -> minutes in
  let substr ftime 17  2 -> sec in
  (
    let "Jan"::"Feb"::"Mar"::"Apr"::"May"::"Jun"::"Jul"::"Aug"::"Sep"::"Oct"::"Nov"::"Dec"::nil -> emounth in
    let "01"::"02"::"03"::"04"::"05"::"06"::"07"::"08"::"09"::"10"::"11"::"12"::nil -> fmounth in
    let 0 -> ok in
    let 0 -> ct in
    (
      while (ok==0) do
    	(
        if (!strcmp mounth nth_list emounth ct) then
    		(
          set mounth = nth_list fmounth ct;
          set ok = 1;
    		)
        else 
          set ct = ct+1;
    	);
    );
    strcatn num::"/"::mounth::"/"::an::" "::hour::":"::minutes::":"::sec::nil;
  );;


fun mkReadFileLine(file)=
  let "" -> buff in
  (
    while (((strfind "\n" buff 0) == nil) && ((_FILETell file) < (_FILESize file))) do
    (
      set buff = strcat buff (_FILERead file 1);
    );
    buff;
  );;


//TODO add APPROTDIR in XOS
//TODO rewrite material / shaders scripts paths
fun relocateOS3DProject(path, ppath, npath)=
  let (_checkpack path) -> pfile in
  let _getpack pfile -> fcont in 
  let if (!strcmp "ZXML" (substr fcont 0 4)) then 1 else 0 -> iszipped in
  let if iszipped then unzip (substr fcont 4 (strlen fcont)-4) else fcont -> fcont in
  let strreplacei fcont ppath npath -> ndata in
  let strreplacei ndata strtoweb ppath strtoweb npath -> ndata in
  let if iszipped then strcat "ZXML" zip ndata else ndata -> content in
    _storepack content path;
  0;;


fun readPakHeader(xmlpath, filecont)=
  let (strfind "#******#" filecont 0) + 8 -> namepos in
  let strfind "|" filecont namepos -> nextpos in
  let substr filecont namepos (nextpos - namepos) -> filename in
  let if (!strcmp "|!Z|" (substr filecont nextpos 4)) then
      (
        set nextpos = strfind "|" filecont (nextpos + 1);
        0;
      )
      else if (!strcmp "|Z|" (substr filecont nextpos 3)) then
      (
        set nextpos = strfind "|" filecont (nextpos + 1);
        1;
      )
      else
        1
  -> iszip in
  let strfind "|" filecont (nextpos + 1) -> nextsignpos in
  let substr filecont (nextpos + 1) (nextsignpos - (nextpos + 1)) -> strsign in
  let strfind "|" filecont (nextsignpos + 1) -> nextsizepos in
  let atoi substr filecont (nextsignpos + 1) (nextsizepos - (nextsignpos + 1)) -> strsize in
  let strreplace filename "APPROOTDIR/" "" -> filename in
    [filename iszip strsign strsize nextsizepos];;


fun mkUnpakProject(path)=
  // date pos
  let _FILEOpen _channel _checkpack path -> file in
  let _FILERead file 19 -> date in
  let _FILESize file -> filesize in
  let "" -> filecont in
  if (file == nil) then nil else
  (
    _FILESeek file 1 1; //remove \n
    
    let strtrim mkReadFileLine file -> xmlpath in
    let nil -> projectContent in
    let 0 -> skip in
    (
      while ((_FILETell file) < filesize) do
      (
        set filecont = strcat filecont (_FILERead file 65534);
        set skip = 0;
        
        while (!skip && ((strfind "#******#" filecont 0) != nil)) do
        (
          let readPakHeader xmlpath filecont -> [filename iszip strsign strsize datapos] in
          
          let substr filecont (datapos + 1) strsize -> thisfile in
          let strlen thisfile -> datalen in
          (
            if (datalen != strsize) then
            (
              set skip = 1;
            )
            else
            (
              set filecont = substr filecont datapos + strsize + 1 (strlen filecont);
              if (!strcmp xmlpath filename) then
              (
                set projectContent = if (iszip) then (unzip thisfile) else thisfile;
                0;
              )
              else
              (
                if (!strcmp (_fileSign _checkpack filename) strsign) then nil else
                let strreplace filename "APPBASEDIR" APPBASEDIR -> filename in
                  _storepack (if (iszip) then (unzip thisfile) else thisfile) filename; 
                
                _freememory;
                0;
              );
            );
          );
        );
      );
      _FILEClose file;
      projectContent;
   );
  );;


fun readOS3DPakHeader(xmlpath, basepath, filecont)=
  let (strfind "#******#" filecont 0) + 8 -> namepos in
  let strfind "|" filecont namepos -> nextpos in
  let substr filecont namepos (nextpos - namepos) -> filename in
  let if (!strcmp "|!Z|" (substr filecont nextpos 4)) then
      (
        set nextpos = strfind "|" filecont (nextpos + 1);
        0;
      )
      else if (!strcmp "|Z|" (substr filecont nextpos 3)) then
      (
        set nextpos = strfind "|" filecont (nextpos + 1);
        1;
      )
      else
        1
  -> iszip in
  let strfind "|" filecont (nextpos + 1) -> nextsignpos in
  let substr filecont (nextpos + 1) (nextsignpos - (nextpos + 1)) -> strsign in
  let strfind "|" filecont (nextsignpos + 1) -> nextsizepos in
  let atoi (substr filecont (nextsignpos + 1) (nextsizepos - (nextsignpos + 1))) -> strsize in
  let getFileDirectory filename -> fdir in
  let getFileExt filename -> ext in
  let !strcmp (strcat "APPROOTDIR/" xmlpath) filename -> isproj in
  let strreplace filename "APPROOTDIR/" basepath -> filename in 
    [filename ext iszip strsign strsize nextsizepos isproj fdir];;


fun mkStoreOS3DPakFile(filename, ext, iszip, fdir, basepath, data)=
  _storepack (if (iszip) then (unzip data) else data) filename;
  
  if ((strcmpi ext "XOS") || (!strcmp basepath "")) then nil else
  (
    relocateOS3DProject filename (strcat fdir "/") (strcatn basepath::fdir::"/"::nil);
    relocateOS3DProject filename "assets/" (strcat basepath "assets/");
  );
  0;;


// mode 0 for all packages, 1 for project resources only
fun mkUnpakOS3DProject(filep, basepath, mode)=
  // date pos
  let if (basepath == nil) then "" else basepath -> basepath in
  let _FILEOpen _channel filep -> file in
  if (file == nil) then nil else
  let _FILERead file 19 -> date in
  let _FILESize file -> filesize in
  let "" -> filecont in
  (
    _FILESeek file 1 1; //remove \n
    
    let strtrim mkReadFileLine file -> xmlpath in
    let nil -> projectFile in
    let 0 -> skip in
    let 0 -> readsize in
    let nil -> curfile in
    let nil -> curext in
    let nil -> cursign in
    let 0 -> curzip in
    let 0 -> curproj in    
    let nil -> curfdir in
    let 0 -> cursize in
    let 0 -> skipfile in
    (
      while ((_FILETell file) < filesize) do
      (
        set filecont = strcat filecont (_FILERead file 65534);
        set skip = 0;
        
        if (curzip || (cursize == 0) || (curfile == nil)) then nil else
        (
          let substr filecont 0 (cursize - readsize) -> data in
          let strlen data -> datalen in
          (
            if (skipfile) then nil else
            (
              //addLogMessage strcat "store next pak :" curfile;
              _appendpack data _getmodifypack curfile;
            );
            
            set readsize = readsize + datalen;
            if (readsize != cursize) then nil else
            (
              set readsize = 0;
              set curfile = nil;
              set curext = nil;
              set curzip = 0;
              set cursign = nil;
              set cursize = 0;
              set curproj = 0;
              set curfdir = nil;
            );
            
            set filecont = substr filecont datalen (strlen filecont);
          );
        );
        
        //do not search new file until we get all data
        while (!skip && ((strfind "#******#" filecont 0) != nil)) do
        (
          let readOS3DPakHeader xmlpath basepath filecont -> [filename ext iszip strsign strsize datapos isproj fdir] in
          let substr filecont (datapos + 1) strsize -> thisfile in          
          let strlen thisfile -> datalen in
          (
            let strreplace filename "APPBASEDIR" APPBASEDIR -> cmpname in
            if ((filename != nil) && (datapos != nil) && (strcmp cmpname curfile)) then
            (
              set curext = ext;
              set curzip = iszip;
              set cursign = strsign;
              set cursize = strsize;
              set curproj = isproj;              
              set curfdir = fdir;
              set readsize = datalen;
              
              if ((mode && ((strfindi "APPBASEDIR" curfile 0) != nil)) || (!strcmp (_fileSign _checkpack filename) cursign)) then
                set skipfile = 1
              else
                set skipfile = 0;
              
              let strreplace filename "APPBASEDIR" APPBASEDIR -> filename in
                set curfile = filename;
              
              //addLogMessage strcat "new unpak found: " curfile;
            );
                              
            if ((curfile == nil) || (datalen != cursize)) then
            (
              set skip = 1;
              if (iszip || (curfile == nil)) then nil else
              (
                set filecont = substr filecont datapos + cursize + 1 (strlen filecont);
                
                //init data
                if (skipfile) then nil else
                (
                  _deletepack _checkpack curfile;
                  _appendpack thisfile _getmodifypack curfile;
                  
                  //addLogMessage strcat "store init pak: " curfile;
                );
              );
              0;
            )
            else
            (
              //addLogMessage strcat "clear pak packet: " curfile;
              set filecont = substr filecont datapos + cursize + 1 (strlen filecont);
              
              if (skipfile) then nil else
              (
                //addLogMessage strcat "store pak is same packet: " curfile;
                //addLogMessage strcat "store is zip: " (itoa curzip);
                if (cursize != 0) then
                (
                  mkStoreOS3DPakFile filename curext curzip curfdir basepath thisfile;
                  0;
                )
                else
                (
                  let getPathFile _PtoScol filep "" -> [path _] in
                  let getPathFile filename "" -> [_ fname] in                  
                    _CopyFile (_checkpack strcatn path::"/"::fname::nil) (_getmodifypack filename);                   
                  0;
                );
              );
              
              if (!curproj) then nil else
                set projectFile = curfile;
              
              set readsize = 0;
              set curfile = nil;
              set curext = nil;
              set curzip = 0;
              set cursign = nil;
              set cursize = 0;
              set curproj = 0;
              set curfdir = nil;
              
              _freememory;
              0;
            );
          );
        );
      );
      _FILEClose file;
      projectFile;
   );
  );;


fun cbPakTrm(trm, wp)=
  let wp -> [ftpstr l wfile cbComplete] in
  (
    _deltimer trm;
    _freememory;
    
    //manage cancel
    if (winMkApplet == nil) then nil else
      mkPakAll ftpstr l wfile cbComplete;
  );
  0;;


fun mkPakAll(ftpstr, l, wfile, cbComplete)=
  if (l == nil) then
  (
    exec cbComplete with [];
    0;
  )
  else
  (
    let l->[name nxt] in
    let getFileContent name -> content in
  	(
  	  let zip content -> ziped in
  	  let if (!strcmpi (substr name 0 (strlen APPBASEDIR)) APPBASEDIR) then strcat "APPBASEDIR" (substr name ((strlen APPBASEDIR) - 1) (strlen name)) else name -> mname in
  	    _appendpack strcatn "#******#"::mname::"|"::(_getlongname content "" "#")::"|"::(itoa (strlen ziped))::"|"::ziped::nil wfile;
  	  
  	  _freememory;
  	  
      mkAppletAddLog ftpstr strcatn "Pack "::name::nil;
      
  	  // use a timer to allow the garbage collector to free some memory in the loop
  	  _rfltimer _starttimer _channel 5 @cbPakTrm [ftpstr nxt wfile cbComplete];
  	  0;
    );
  );
  0;;


fun mkPakProject(ftpstr, lfiles, outpath, xmlpath, cbComplete)=
  let strcatn (mkDTime time)::"\n"::xmlpath::"\n"::nil -> ncontent in
  (
    _storepack ncontent outpath;
    mkPakAll ftpstr lfiles (_getmodifypack outpath) cbComplete;
  );
  0;;


/* ********************************************************************************************* /
  FTP Functions
/ ********************************************************************************************* */


fun mkAppletEnableInterface(ftpstr, mode)=
  setEdCtrlButtonEnable ftpstr.AFTP_ctrlOk mode;
  setEdCtrlTextLineEnable ftpstr.AFTP_ctrlHost mode;
  setEdCtrlFloatEnable ftpstr.AFTP_ctrlPort mode;
  setEdCtrlTextLineEnable ftpstr.AFTP_ctrlLogin mode;
  setEdCtrlTextLineEnable ftpstr.AFTP_ctrlPass mode;
  setEdCtrlTextLineEnable ftpstr.AFTP_ctrlRoot mode;
  setEdCtrlTextLineEnable ftpstr.AFTP_ctrlDir mode;
  setEdCtrlTextLineEnable ftpstr.AFTP_ctrlWww mode;
  setEdCtrlCheckEnable ftpstr.AFTP_ctrlInWeb mode;
  setEdCtrlCheckEnable ftpstr.AFTP_ctrlUpload mode;
  0;;


fun mkAppletAddLog(ftpstr, message)=
  if ((getEdCtrlTextLineCount ftpstr.AFTP_ctrlLog) < 100) then nil else
    removeEdCtrlTextLine ftpstr.AFTP_ctrlLog 0;
    
  addEdCtrlTextValue ftpstr.AFTP_ctrlLog message;
  _appendpack message ftpstr.AFTP_wLogFile;
  
  scrollEdCtrlText ftpstr.AFTP_ctrlLog 0 (getEdCtrlTextLineCount ftpstr.AFTP_ctrlLog);
  0;;


fun cbDlgTimeout (dlg, ftpstr, res)=
  if res == 1 then
    ftpConnect ftpstr
  else 
  (
    mkAppletAddLog ftpstr (loc "OS3D_0514");
    mkAppletEnableInterface ftpstr 1;
    0;
  );
  0;;


fun cbMkAppletTimeOut(timer, ftpstr)=
  _deltimer timer;
  _TELNETClose ftpstr.AFTP_telnet;
  let _DLGMessageBox _channel ftpstr.AFTP_ctrlWindow.EDW_win (loc "OS3D_0541") (loc "OS3D_0515") 1 -> dlgTimeOut in
    _DLGrflmessage dlgTimeOut @cbDlgTimeout ftpstr;
  0;;


fun cbTimeOutCmd (timer, ftpstr)=
  _deltimer timer;
  _TELNETClose ftpstr.AFTP_telnet;
  mkAppletAddLog ftpstr (loc "OS3D_0503");
  ftpConnect ftpstr;
  0;;


fun sendFtpCommand (ftpstr, cmd, log)=
  let strcat (ctoa 13) (ctoa 10) -> lnfeed in
  if (strfind "LIST" cmd 0)!=nil || (strfind "NLST" cmd 0)!=nil || (strfind "STOR" cmd 0)!=nil || (strfind "RETR" cmd 0)!=nil then
  (
    set ftpstr.AFTP_sDataCmd = cmd;
    mkAppletAddLog ftpstr (loc "OS3D_0502");
    _TELNETSend (strcat "PASV" lnfeed) ftpstr.AFTP_telnet;
    0;
  )
  else
  (
    if !log then nil else
      mkAppletAddLog ftpstr strcatn ">> "::cmd::"\n"::nil;
    
    _TELNETSend (strcat cmd lnfeed) ftpstr.AFTP_telnet; 
    0; 
  );
  
  set ftpstr.AFTP_trmTimeout = _starttimer _channel iTimeOutCmd;
  _rfltimer ftpstr.AFTP_trmTimeout @cbTimeOutCmd ftpstr;
  0;;


fun cbDataTimer (t, data)=
  _deltimer t;
  _TELNETClose data;
  0;;


fun cbDataWrite (data, ftpstr)=
  if (strfind "STOR" ftpstr.AFTP_sDataCmd 0)!=nil then
  (
    let (hd ftpstr.AFTP_lFiles) -> file in
    (
      mkAppletAddLog ftpstr strcatn (strcat (loc "OS3D_0505") " ")::file::"\n"::nil;
      _TELNETSend (_getpack _checkpack (strcat sMkAppletTmpPath file)) data;
      set ftpstr.AFTP_lFiles = tl ftpstr.AFTP_lFiles;
    );
    
    // il manque parfois un octet le timer va permetre de lui laisser le temps d'envoyer
    let _starttimer _channel 500 -> datatimer in
      _rfltimer datatimer @cbDataTimer data;
    0;
  )
  else
  (
    _TELNETClose data;
    0;
  );
  0;;


fun cbDataRead(data, ftpstr)=
  let _TELNETGetBuffer data -> ftpecho in
    mkAppletAddLog ftpstr ftpecho;
  _TELNETClose data;
  0;;


fun cbDataConnect(ftpdata, ftpstr)=
  //_SETtext output strcatn (_GETtext output)::"\n"::">> connected data"::"\n"::nil;
  _TELNETrflRead ftpdata @cbDataRead ftpstr;
  _TELNETrflWrite ftpdata @cbDataWrite ftpstr;
  //_SETtext output strcatn (_GETtext output)::">> "::cmd::"\n"::nil; 
  
  let strcat (ctoa 13) (ctoa 10) -> lnfeed in
    _TELNETSend (strcat ftpstr.AFTP_sDataCmd lnfeed) ftpstr.AFTP_telnet;
  0;;


fun cbDataClose(ftpdata, ftpstr)=
  mkAppletAddLog ftpstr (loc "OS3D_0507");
  0;;


// se connecte au port ftp data
fun tryToConnectData(serveur, ftpstr)=
  let _TELNETConnect _channel serveur -> telnetdata in
 	(
 	  mkAppletAddLog ftpstr strcatn (strcat (loc "OS3D_0501") " ")::serveur::"\n"::nil;
 	  _TELNETrflConnect telnetdata @cbDataConnect ftpstr;
 	  _TELNETrflClose telnetdata @cbDataClose ftpstr;
  );
  0;;


fun getPort(str, portpos, pos)=
  let strfind "," str pos -> npos in
    if npos==nil then 
      (
        let substr str pos ((strfind ")" str 0) - pos) -> port in
        let substr str portpos ((pos -1) - portpos) -> coef in
          (
            _fooS strcat ">>>>>>> coef : " coef;
            _fooS strcat ">>>>>>> port : " port;
            itoa ((atoi coef)*256+(atoi port));
          );
      )
    else
      getPort str pos npos+1
  ;;


fun cbMkAppletClose(dlg, ftpstr, rep)=
  dsEdWindow winMkApplet;
  set winMkApplet = nil;
  0;;


fun cbMkAppletOpenBrowser(dlg, ftpstr, rep)=
  if rep then
  (
    let strcatn ftpstr.AFTP_sUrl::"web/index.html"::nil -> url in
      _openbrowserhttp url;
  )
  else nil;
  
  dsEdWindow winMkApplet;
  set winMkApplet = nil;
  0;;


fun getFtpResponse(ftpEcho, ftpstr)=
  let strextr ftpEcho -> echolist in
  let if (sizelist echolist) > 1 then 
        atoi (hd (nth_list echolist ((sizelist echolist)-1)))
      else 
        atoi (hd hd echolist)
  -> cmdid in
//let atoi substr ftpEcho 0 3 -> cmdid in
  if cmdid == 330 then
  (
    // please log in
    set ftpstr.AFTP_iLogged = 1;
    sendFtpCommand ftpstr (strcatn "USER "::ftpstr.AFTP_sLogin::nil) 1;
  )
  else
  if cmdid == 220 then
  (
    // ready
    if (ftpstr.AFTP_iLogged > 0) then nil else
    (
      set ftpstr.AFTP_iLogged = 1;
      sendFtpCommand ftpstr (strcatn "USER "::ftpstr.AFTP_sLogin::nil) 1;
    );
  )
  else if cmdid == 331 then
  (
    let strlen ftpstr.AFTP_sPass -> plen in
    let "" -> pmask in
    (
      while plen > 0 do
      (
        set pmask = strcat pmask "*";
        set plen = plen - 1;
      );
      
      // transfert complete
      mkAppletAddLog ftpstr strcat ">> " (strcatn "PASS "::pmask::"\n"::nil);
      sendFtpCommand ftpstr (strcatn "PASS "::ftpstr.AFTP_sPass::nil) 0;
    );
  )
   else if cmdid == 230 then
  (
    // logged in
    set ftpstr.AFTP_iLogged = 2;
    sendFtpCommand ftpstr (strcatn "SYST"::nil) 1;
  )
  else if cmdid == 215 then
  (
    // System type
    sendFtpCommand ftpstr "TYPE I" 1;
  )
  else if cmdid == 200 then
  (
    // TYPE ok
    sendFtpCommand ftpstr (strcatn "CWD "::ftpstr.AFTP_sDir::nil) 1;
  )
  /*
  else if cmdid == 250 then
  (
    // CWD successful
    sendFtpCommand ftpstr "LIST" 1;
  )
  */
  // upload
  else if cmdid == 250 || cmdid == 226 || cmdid == 257 || cmdid == 550 || cmdid == 521 then
  (
    // MDK ok or exist transfert complete
    // nextCommmand
    if (cmdid == 550) && !ftpstr.AFTP_iState then
    (
      sendFtpCommand ftpstr "QUIT" 1;
      set ftpstr.AFTP_bError = 1;
      0;
    )
    else
    (
      // first CWD passed
      set ftpstr.AFTP_iState = 1;
      
      if ftpstr.AFTP_lDirs != nil then
      (
        sendFtpCommand ftpstr (strcatn "MKD "::(hd ftpstr.AFTP_lDirs)::nil) 1;
        set ftpstr.AFTP_lDirs = tl ftpstr.AFTP_lDirs;
        0;
      )
      else if ftpstr.AFTP_lFiles != nil then 
      (
        //let if (hd ftpstr.AFTP_lFiles) == nil then (hd tl ftpstr.AFTP_lFiles) else (hd ftpstr.AFTP_lFiles) -> fileok in
        sendFtpCommand ftpstr (strcatn "STOR "::((hd ftpstr.AFTP_lFiles))::nil) 1;
        0;
      )
      else
      (
        sendFtpCommand ftpstr "QUIT" 1;
        0;
      );
    );
    0;
  )
  else if cmdid == 227 then
  (
    // pasv
    tryToConnectData (strcatn ftpstr.AFTP_sIp::":"::(getPort ftpEcho 0 0)::nil) ftpstr;
  )
  else if cmdid == 421 then
  (
    // time out
    _DLGMessageBox _channel ftpstr.AFTP_ctrlWindow.EDW_win (loc "OS3D_0541") (loc "OS3D_0547") 0;
    mkAppletEnableInterface ftpstr 1;
    0;
  )
  else if cmdid == 221 then
  (
    set ftpstr.AFTP_iLogged = 0;
    // Quit
    if (!ftpstr.AFTP_bError) then
    (
      _TELNETClose ftpstr.AFTP_telnet;
      let strcatn ftpstr.AFTP_sUrl::"web/index.html"::nil -> url in
        _DLGrflmessage _DLGMessageBox _channel ftpstr.AFTP_ctrlWindow.EDW_win (loc "OS3D_0544") (strcat (strcat (loc "OS3D_0545") " ") url) 1 @cbMkAppletOpenBrowser ftpstr;
      0;
    )
    else
    (
      _TELNETClose ftpstr.AFTP_telnet;
      _DLGMessageBox _channel ftpstr.AFTP_ctrlWindow.EDW_win (loc "OS3D_0543") (loc "OS3D_0510") 0;
      mkAppletEnableInterface ftpstr 1;
      0;
    );
    0;
  )
  else if cmdid == 530 then
  (
    if (ftpstr.AFTP_iLogged != 2) then
    (
      set ftpstr.AFTP_iLogged = 0;
      
      // bad login
      mkAppletAddLog ftpstr (loc "OS3D_0512");
      
      _TELNETClose ftpstr.AFTP_telnet; 
      mkAppletEnableInterface ftpstr 1;
    )
    else
    (
      // strange... replied from "SYST" command ? try to continue
      sendFtpCommand ftpstr "TYPE I" 1;
    );
    0;
  )
  else if cmdid == 150 then
  (
    mkAppletAddLog ftpstr (loc "OS3D_0542");
    0;
  )
  else nil;   
  0;;


fun cbTelnetWrite (tel, ftpstr)=
  mkAppletAddLog ftpstr (loc "OS3D_0506");
  0;;


fun cbTelnetRead(tel, ftpstr)=
  let _TELNETGetBuffer tel -> ftpecho in
  (
    _deltimer ftpstr.AFTP_trmTimeout;

    if (ftpecho == nil) || (!strcmp ftpecho "") then nil else 
    (
      mkAppletAddLog ftpstr ftpecho;
      getFtpResponse ftpecho ftpstr;
    );
  );
  0;;


fun cbTelnetConnect(tel, ftpstr)=
  mkAppletAddLog ftpstr (loc "OS3D_0499");
  _TELNETrflRead tel @cbTelnetRead ftpstr;
  _TELNETrflWrite tel @cbTelnetWrite ftpstr;
  0;;


fun ftpConnect(ftpstr)=
  let (_gethostbyname ftpstr.AFTP_sHost) -> resolvip in
  let (strcatn resolvip::":"::(itoa ftpstr.AFTP_iport)::nil) -> ftpadress in
  let _TELNETConnect _channel ftpadress -> telnetftp in
 	(
 	  set ftpstr.AFTP_telnet = telnetftp;
 	  set ftpstr.AFTP_sIp = resolvip;
    mkAppletAddLog ftpstr strcatn (strcat (loc "OS3D_0500") " ")::ftpstr.AFTP_sHost::(loc "OS3D_0497")::nil;
    
 	  set ftpstr.AFTP_trmTimeout = _starttimer _channel iTimeOut;
    _rfltimer ftpstr.AFTP_trmTimeout @cbMkAppletTimeOut ftpstr;
    _TELNETrflConnect ftpstr.AFTP_telnet @cbTelnetConnect ftpstr;
  );
  0;;


fun addDirToList(l, ftpstr)=
  if l == nil then nil else
  let l -> [elem next] in
  (
    set ftpstr.AFTP_lDirs = elem::ftpstr.AFTP_lDirs;
    addDirToList next ftpstr;
  );
  0;;


fun getInitDirs(initdir, ftpstr)=
  let 0 -> curpos in
  let nil -> newldir in
  let (strfind "/" initdir curpos) -> dirpos in
  (
    while dirpos != nil do
    (
      let (strfind "/" initdir (dirpos +1)) -> nextpos in
      let substr initdir curpos ((dirpos) - curpos) -> newdir in
      (
        if (isStringInList ftpstr.AFTP_lDirs (strlowercase newdir)) then nil else 
          set newldir = (strlowercase newdir)::newldir;
      );
      set dirpos = (strfind "/" initdir dirpos +1);
    );
    addDirToList newldir ftpstr;
  );
  0;;


fun mkAppletGetDirectories(l)=
  let sizelist l -> size in
  let nil -> ndata in
  let 0 -> i in
  (
    while i < size do
    (
      let nth_list l i -> elem in
      let getPathFile elem "" -> [path _] in
        set ndata = path::ndata;
        
      set i = i + 1;
    );
    ndata;
  );;

/*
fun debugStringList(l, file)=
  let sizelist l -> size in
  let "" -> ndata in
  let 0 -> i in
  (
    while i < size do
    (
      let nth_list l i -> elem in
        set ndata = strcatn ndata::elem::"\n"::nil;
      set i = i + 1;
    );
    _storepack ndata file;
  );;
*/

fun mkAppletUploadFiles(ftpstr)=
  apply_on_list (mkAppletGetDirectories ftpstr.AFTP_lFiles) @getInitDirs ftpstr;
  // sort list by alphabetical order
  set ftpstr.AFTP_lDirs = sortlist ftpstr.AFTP_lDirs @isSmaller;
  //debugStringList ftpstr.AFTP_lFiles strcat sMkAppletTmpPath "debug.txt";
  
  ftpConnect ftpstr;
  0;;


/* ********************************************************************************************* /
  Make Applet files
/ ********************************************************************************************* */
fun mkAppletCpWebfiles(l, path)=
  if l == nil then nil else
  (
    let getPathFile (hd l) "" -> [_ filename] in
    if !strcmpi "index.html" filename then nil else
      copyFileContent (hd l) strcatn path::"web/"::filename::nil;
    mkAppletCpWebfiles (tl l) path;
  );
  0;;


fun mkAppletPhpInc(ftpstr, projname, filename, xmlpath)=
  let if ftpstr.AFTP_sAppDir == nil then sMkAppletTmpPath else strcatn sMkAppletTmpPath::ftpstr.AFTP_sAppDir::"/"::nil -> tmppath in
  let _listoffiles strcat APPBASEDIR sMkAppletPath -> lwebfiles in
  let _checkpack (getProjectSetting "splashpath") -> psplash in
  let if (psplash == nil) then lwebfiles else (getProjectSetting "splashpath")::lwebfiles -> lwebfiles in
    
  let XMLload xmlpath -> xmlscenestr in
  let XMLgetMarkByValue xmlscenestr "environment" -> envmark in
  let XMLgetMarkByValueFromMarkSons envmark "colourBackground" -> backstr in
  let make_rgb (ftoi ((atof XMLgetParam backstr "b") *. 255.0)) (ftoi ((atof XMLgetParam backstr "g") *. 255.0)) (ftoi ((atof XMLgetParam backstr "r") *. 255.0)) -> bgcolor in
  (
    mkAppletCpWebfiles lwebfiles tmppath;
    let strreplace strcatn "scol://applet?app="::ftpstr.AFTP_sUrl::filename::nil " " "%20" -> appurl in
    let strreplace strcatn "scol://applet:"::ftpstr.AFTP_sUrl::filename::nil " " "%20" -> oldappurl in
    let getVoyagerVersionS -> svoyver in
    let _getpack _checkpack strcatn APPBASEDIR::sMkAppletPath::"index.html"::nil -> html in
    (
      if (psplash == nil) then
      (
        set html = strreplace html "$BGSPLASH" "";
      )
      else
      (
        let getPathFile (_PtoScol psplash) "" -> [_ splashimg] in
        set html = strreplace html "$BGSPLASH" strcatn "style=\"background-image:url('"::splashimg::"'); background-repeat:no-repeat; background-position:center;\""::nil;
      );
      
      set html = strreplace html "$TITLE" projname;
      set html = strreplace html "$BGCOLOR" (if bgcolor == 0 then "000000" else (itoh bgcolor));
      set html = strreplace html "$SCOL_SITE_URL_OLD" oldappurl;
      set html = strreplace html "$SCOL_SITE_URL" appurl;
      set html = strreplace html "$WIN_32_PLUGIN_URL" "http://www.scolring.org/rsc/scol_plugin.exe";
      set html = strreplace html "$MINIMUMSCOLVERSION" svoyver;
      set html = strreplace html "$WEBINTEGRATED" (itoa ftpstr.AFTP_bWebIn);
      set html = strreplace html "$WIDTH" (getProjectSettingDef "defaultWidth" "1280");
      set html = strreplace html "$HEIGHT" (getProjectSettingDef "defaultHeight" "720");
      _storepack html strcatn tmppath::"web/index.html"::nil;
    );
    
    let sizelist lwebfiles -> size in
    let nil -> ndata in
    let 0 -> i in
    (
      while i < size do
      (
        let nth_list lwebfiles i -> elem in
        let getPathFile elem "" -> [_ wname] in
          set ndata = (strcatn ftpstr.AFTP_sAppDir::"/web/"::wname::nil)::ndata;
          
        set i = i + 1;
      );
      (strcat ftpstr.AFTP_sAppDir "/web/index.html")::ndata;
    );
  );;


fun strright(s, i) = substr s (strlen s)-i i;;


fun mkAppletFilter(l, path)=
  if (l == nil) then nil else
  let if path == nil then sMkAppletTmpPath else strcatn sMkAppletTmpPath::path::"/"::nil -> tmppath in
  let l->[x nxt] in
  let x->[url [name[size[type[sgn _]]]]] in
  if url!=nil && ((!strcmp "http://" substr url 0 7) || (!strcmp "https://" substr url 0 8) || (!strcmp "ftp://" substr url 0 6)) then
  (
    let if (_checkpack name) == nil then strcat tmppath name else name -> gname in
    let getFileExt gname -> ext in
    //do not compress pak files
    if (!strcmpi ext "pak") then
    (
      (url::name::(itoa (_fileSize _checkpack gname))::"0"::(_fileSign _checkpack gname)::nil)::(mkAppletFilter nxt path);
    )
    else
    let getFileContent gname -> content in
    let zip content -> zipfile in
  	(
  	  _storepack zipfile strcatn tmppath::name::".zp"::nil;
  		((if !strcmpi strright url 3 ".zp" then url else strcat url ".zp")::name::(itoa strlen zipfile)::"2"::(_getlongname content "" "#")::nil)::(mkAppletFilter nxt path);
    );
  )
  else
  	x::(mkAppletFilter nxt path);;


fun mkAppletCrypt(ftpstr, projname, name, cont, lfiles, xmlpath, bupload)=
  let if (ftpstr.AFTP_sAppDir == nil) then name else strlowercase strcatn ftpstr.AFTP_sAppDir::"/"::name::nil -> destfile in
  let strbuild mkAppletFilter strextr cont ftpstr.AFTP_sAppDir -> newcontent in
  (
    _storepack newcontent strcat sMkAppletTmpPath destfile;
    
    let mkAppletPhpInc ftpstr projname name xmlpath -> lwebfiles in
    let listLowercase (destfile::(lcat lwebfiles lfiles)) -> lupfiles in
      set ftpstr.AFTP_lFiles = lupfiles;
    
    if (!bupload) then 
    (
      let getFileDirectory (_PtoS _checkpack (strcat sMkAppletTmpPath destfile)) -> fullpath in
        _startExe "launch" "openExplorer" fullpath;
        
      _DLGrflmessage _DLGMessageBox _channel ftpstr.AFTP_ctrlWindow.EDW_win (loc "OS3D_0532") (loc "OS3D_0525") 0 @cbMkAppletClose ftpstr;
      0;
    )
    else
    (
      mkAppletUploadFiles ftpstr;
      0;
    );
  );
  0;;


fun fileExist(l, file)=
if l ==nil then 0 else
  if (!strcmp (hd l) file) then 
    1
  else fileExist (tl l) file;;


fun findExcluFile(lfiles)=
  let sizelist lfiles -> size in
  let nil -> nlist in
  let 0 -> i in
  (
    while i < size do
    (
      let nth_list lfiles i -> file in
      let getFileExt file -> ext in 
        if (!strcmpi "bak" ext) || 
          (!strcmpi "scol" ext) ||
          (!strcmpi "max" ext) ||
          (!strcmpi "psd" ext) ||
          (!strcmpi "exe" ext) ||
          (!strcmpi "php" ext) ||
          (fileExist nlist file)
        then nil else
          set nlist = file::nlist;
      
      set i = i + 1;
    );
    nlist;
  );;


fun excludeFilesBase(lfiles, exbase)=
  let sizelist lfiles -> size in
  let nil -> nlist in
  let 0 -> i in
  (
    while i < size do
    (
      let nth_list lfiles i -> file in
      let getFileNameWithoutExt file -> bname in 
        if (isStringInListi exbase bname) then nil else
          set nlist = file::nlist;
      
      set i = i + 1;
    );
    nlist;
  );;


fun keepFilesBase(lfiles, exbase, prefix)=
  let strlen prefix -> prefixlen in
  let sizelist lfiles -> size in
  let nil -> nlist in
  let 0 -> i in
  (
    while i < size do
    (
      let nth_list lfiles i -> file in
      let getFileNameWithoutExt file -> bname in 
      if ((prefixlen != 0) && (strcmpi prefix (substr bname 0 prefixlen))) then nil else
        if (!isStringInListi exbase (substr bname prefixlen ((strlen bname) - prefixlen))) then nil else
          set nlist = file::nlist;
      
      set i = i + 1;
    );
    nlist;
  );;


// get default player lib and plugin resources
fun getMkAppletXmlResources(xmlpath, lin)=
  let XMLload xmlpath -> xmlscenestr in
  let XMLgetMarksByValue xmlscenestr "resource" -> lresourcemarks in
  let XMLgetMarksByValue xmlscenestr "plugin" -> lpluginsmarks in
  let nil -> lout in
  let nil -> ldeps in
  (
    let sizelist lresourcemarks -> size in
    let 0 -> i in
    while i < size do
    (
      let nth_list lresourcemarks i -> resourcemark in
      let XMLgetParam resourcemark "type" -> type in
      let XMLgetParam resourcemark "path" -> path in
        set lout = path::lout;
      
      set i = i + 1;
    );
    
    // get project theme resource
    let XMLgetMarkByValue xmlscenestr "project" -> srcprjmark in
    let XMLgetMarkByValueFromMarkSons srcprjmark "setting" -> srcsettingmark in
    let XMLgetData (XMLgetMarkByValueFromMarkSons srcsettingmark "themeName") -> data in
    let if ((data == nil) || (!strcmp "default" (strtrim data))) then nil else
          VUIgetThemePath data
    -> themepath in
    if (themepath == nil) then nil else
    (
      let XMLload themepath -> xmlthemestr in
      let XMLgetMarkByValue xmlthemestr "UITheme" -> thememark in
      let XMLgetMarksDataByValueFromMark thememark "UIResource" -> lthemeres in
        set lout = lcat themepath::lout lthemeres;
    );
    
    let sizelist lpluginsmarks -> size in
    let 0 -> i in
    while i < size do
    (
      let nth_list lpluginsmarks i -> pluginmark in
      let strcat strcat APPBASEDIR "os3dplugins/" XMLgetParam pluginmark "source" -> source in
      let getPathFile source "" -> [plugdir _] in
      let getDirectoryWithoutLastSlash plugdir -> plugdir in
      let XMLload source -> xmlpluginstr in
      let XMLgetMarkByValue xmlpluginstr "dependencies" -> depsmark in
      let XMLgetMarksByValueFromMark depsmark "scolplugin" -> lpluginsmarks in 
      let XMLgetMarkByValue xmlpluginstr "resource" -> resourcemark in
      let XMLgetMarksByValueFromMark resourcemark "file" -> lfilemarks in 
      let XMLgetMarkByValue xmlpluginstr "client" -> clientmark in
      let XMLgetMarkByValue xmlpluginstr "editor" -> editormark in
      let XMLgetMarksByValueFromMark clientmark "script" -> lscripmarks in
      let XMLgetMarksByValueFromMark editormark "param" -> lparams in
      let getFilesFromDir (strcat plugdir "/lang") "lang"::nil -> llangs in
      (
        set lout = lcat llangs source::lout;

        let sizelist lpluginsmarks -> size in
        let 0 -> i2 in
        while i2 < size do
        (
          let nth_list lpluginsmarks i2 -> depmark in
          let XMLgetParam depmark "name" -> scolplug in
            set ldeps = scolplug::ldeps;
          set i2 = i2 + 1;
        );
        
        let sizelist lfilemarks -> size in
        let 0 -> i2 in
        while i2 < size do
        (
          let nth_list lfilemarks i2 -> filemark in
          let getRelativePath plugdir (XMLgetParam filemark "path") -> file in
            set lout = file::lout;
          set i2 = i2 + 1;
        );
        
        let sizelist lscripmarks -> size in
        let 0 -> i2 in
        while i2 < size do
        (
          let nth_list lscripmarks i2 -> scriptmark in
          let getRelativePath plugdir (XMLgetParam scriptmark "path") -> file in
            set lout = file::lout;
          set i2 = i2 + 1;
        );
        
        let sizelist lparams -> size3 in
        let 0 -> i3 in
        while i3 < size3 do
        (
          let nth_list lparams i3 -> parammark in
          let XMLgetParam parammark "name" -> pname in
          let XMLgetParam parammark "type" -> ptype in
          if (!strcmpi ptype "file") then
          (
            let if (!strcmp "_" (substr pname ((strlen pname) - 1) 1)) then
                  XMLgetMarksByValueAndParamPrefixValueFromMark pluginmark "param" "name" pname
                else
                  XMLgetMarksByValueAndParamValueFromMark pluginmark "param" "name" pname
            -> liparam in
            while liparam != nil do
            (
              let XMLgetData (hd liparam) -> path in
              if (!strcmp "" strtrim path) || (path == nil) || ((_checkpack path) == nil) then nil else
              (
                let getFileExt path -> ext in
                // check recursive xos references in plugits to avoid infinite loop
                let xmlpath::(lcat lout lin) -> fl in
                if ((!strcmpi ext "xos") && (strcmpi path xmlpath) && !(isStringInListi fl path)) then
                let getMkAppletXmlResources path fl -> [no nd] in
                (                  
                  set ldeps = lcat nd ldeps;
                  set lout = lcat no lout;
                )
                else
                  set lout = path::lout;
              );
              
              set liparam = tl liparam;
            );
          )
          else nil;
            
          set i3 = i3 + 1;
        );
        
        XMLclose xmlpluginstr;
      );
      
      set i = i + 1;
    );
    
    XMLclose xmlscenestr;
    [xmlpath::lout ldeps];
  );;


fun mkAppletAddFile(url, l, ls)=
  if l ==nil then ls else 
  let l -> [elem next] in
  (
    let (strreplace (strcat url elem) " " "%20") -> nurl in
    let (strcatn nurl::"\ "::(strreplace elem " " "\\ ")::"\n"::ls::nil) -> newstring in
    mkAppletAddFile url next newstring;
  );;


fun mkAppletUpdateZpFilesName(l, path)=
  let if path == nil then "" else strcatn path::"/"::nil -> tmppath in
  let sizelist l -> size in
  let nil -> ndata in
  let 0 -> i in
  (
    while i < size do
    (
      let nth_list l i -> elem in
      let getFileExt elem -> ext in
      //do not compress pak files
      if (!strcmpi ext "pak") then
        set ndata = (strcatn tmppath::elem::nil)::ndata
      else
        set ndata = (strcatn tmppath::elem::".zp"::nil)::ndata;
        
      set i = i + 1;
    );
    ndata;
  );;


fun mkAppletGetFilesMd5(lfiles)=
  let sizelist lfiles -> size in
  let nil -> ndata in
  let 0 -> i in
  (
    while i < size do
    (
      let nth_list lfiles i -> elem in
      let _filemd5 _checkpack elem -> fmd5 in
      if fmd5 == nil then nil else
        set ndata = fmd5::ndata;
      
      set i = i + 1;
    );
    ndata;
  );;


fun makeUsmIni(dir, platform, renderer, antialias, pfx, pext, ldeps, lp)=
  let "# Scol Configuration\n# DO NOT MODIFY !!!!!!!!!\n\n" -> baseusm in
  let if (platform != nil) then strcatn baseusm::"platform "::platform::"\n\n"::nil else baseusm -> baseusm in
  let lcat strextr baseusm ("standalone"::"yes"::nil)::("log"::"no"::nil)::("#echo"::"ffffff"::nil)::(""::nil)::nil -> pusm in
  let switchstr lPlatformPlugins platform -> lavailableplugs in
  let lPluginsBase -> baseplugs in
  (
    if (strcmp platform "win") then nil else
    (
      set pusm = lcat pusm ("scol"::"scol.dll"::"SCOLWinMain"::nil)::(""::nil)::nil;
      set baseplugs = lcat baseplugs "lib2d24"::nil; 
    );
    
    set pusm = lcat pusm ("#"::"Plugins"::nil)::nil;
    while baseplugs != nil do
    (
      let hd baseplugs -> elem in
        set pusm = lcat pusm ("plugin"::(strcatn pfx::elem::pext::nil)::nil)::nil;
      set baseplugs = tl baseplugs;
    );
    
    while ldeps != nil do
    (
      let hd ldeps -> elem in
      if (!isStringInListi lavailableplugs elem) then nil else
        set pusm = lcat pusm ("plugin"::(strcatn pfx::elem::pext::nil)::nil)::nil;
      set ldeps = tl ldeps;
    );
    
    set pusm = lcat pusm
      (""::nil)::
      ("#"::"Partitions"::nil)::
      ("cache"::"./Cache"::"256"::nil)::nil;
    
    // add user partition for other platforms
    if (!strcmp platform "win") || (!strcmp platform "linux") || (!strcmp platform "macOS") then
    (
      set pusm = lcat pusm ("diska"::"./partition"::"0"::nil)::nil;
    )
    else
    (
      set pusm = lcat pusm
      ("disku"::"./partition"::"0"::nil)::
      ("diska"::"./partition"::"0"::nil)::
      nil;
    );
    
    set pusm = lcat pusm      
      ("logsp"::"./logs"::"0"::nil)::
      (""::nil)::
      ("#"::"Rendering"::nil)::
      ("SO3Renderer"::renderer::nil)::
      ("3DFSAA"::antialias::nil)::
      ("FocalLength"::"1"::nil)::
      ("EyeSeparation"::"0.06"::nil)::
      (""::nil)::
      lp;
    
    _storepack (strbuild pusm) strcatn dir::"/"::"usm.ini"::nil;
    
    let "AutoSetup No\nLaunchCommutron No\nOrigin __\nvideocapture -1\nWizard\nDefaultLanguage English\nRegistering Yes\nLicense\nlocalIPindex 0" -> defusmress in
      _storepack defusmress strcatn dir::"/"::"usmress.ini"::nil;
    
    _addPartition "./" 2;
    let _getpack (_checkpack "ext.ini") -> extini in
    let if (extini != nil) then extini else "[launch]\nexe explore .\nexe openExplorer explorer" -> extini in
    (
      _removeLastPartition;
      _storepack extini strcatn dir::"/"::"ext.ini"::nil;
    );
  );
  0;;


fun copyFilesToExportDirectory(dir, lfiles, ldeps, xmlpath, fname, archname, renderer, antialias)=
  let strlen archname -> srclen in
  (
    while lfiles != nil do
    (
      let hd lfiles -> file in
        copyFileContent file strcatn dir::"/partition/"::file::nil;
      
      set lfiles = tl lfiles;    
    );
    
    //copy scol voyager
    let getFilesFromDir archname "dll"::"ini"::"ocx"::"ico"::"bin"::"dat"::nil -> lroot in
    while lroot != nil do
    (
      let hd lroot -> file in
      let substr file srclen ((strlen file) - srclen) -> dstfile in
        copyFileContent file strcatn dir::"/"::dstfile::nil;
      
      set lroot = tl lroot;
    );
    
    //copy plugins
    let getFilesFromDir strcat archname "/plugins" "dll"::nil -> lplugins in
    let lcat lPluginsBase "lib2d24"::ldeps -> fulldeps in
    let keepFilesBase lplugins fulldeps "" -> lplugins in
    while lplugins != nil do
    (
      let hd lplugins -> file in
      let substr file srclen ((strlen file) - srclen) -> dstfile in
        copyFileContent file strcatn dir::"/"::dstfile::nil;
      
      set lplugins = tl lplugins;
    );
    
    //copy OpenNI redist
    if (!isStringInListi ldeps "openniscol") then nil else
    (
      let getFilesFromDirRecursive strcat archname "/plugins/NiTE2" -> lni in
      let strlen strcat archname "/plugins" -> plen in
      while lni != nil do
      (
        let hd lni -> file in
        let substr file plen ((strlen file) - plen) -> dstfile in
          copyFileContent file strcatn dir::"/plugins/"::dstfile::nil;
        
        set lni = tl lni;
      );
      
      let getFilesFromDirRecursive strcat archname "/plugins/OpenNI2" -> lni in
      let strlen strcat archname "/plugins" -> plen in
      while lni != nil do
      (
        let hd lni -> file in
        let substr file plen ((strlen file) - plen) -> dstfile in
          copyFileContent file strcatn dir::"/plugins/"::dstfile::nil;
        
        set lni = tl lni;
      );
    );
    
    //copy scol base
    let getFilesFromDirRecursive "btdata" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/plugins/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    let getFilesFromDir "ogre_redist" "zip"::nil -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/plugins/"::file::nil;
      
      set lbase = tl lbase;
    );
        
    let getFilesFromDirRecursive "cefres" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/plugins/"::file::nil;
      
      set lbase = tl lbase;
    );
        
    copyFileContent (strcat archname "/Scol.exe") strcatn dir::"/"::(strcat fname ".exe")::nil;
    copyFileContent "logo.bmp" strcatn dir::"/partition/"::"logo.bmp"::nil;
    
    let getProjectSetting "iconpath" -> iconpath in
    let getFileExt getProjectSetting "iconpath" -> ext in
    let nil -> icon_src in
    if ((strcmpi ext "ico") && (set icon_src = G2DloadBmp _channel iconpath) != nil) then
    (
      let _CRbitmap _channel 128 128 -> bmp in
      let _BTSCALEbitmap bmp icon_src 2 -> icon in
      (
        _SAVEbitmap icon _getmodifypack strcatn dir::"/partition/"::APPBASEDIR::"os3dplayer/os3dplayer.ico"::nil;
        _DSbitmap bmp;
      );
      0;
    )
    else
    (
      if ((_checkpack iconpath) == nil) then nil else
        copyFileContent iconpath strcatn dir::"/partition/"::APPBASEDIR::"os3dplayer/os3dplayer.ico"::nil;
      0;
    );
    
    let getProjectSetting "splashpath" -> psplash in
    if ((_checkpack psplash) == nil) then nil else
      copyFileContent psplash strcatn dir::"/partition/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    
    //make usm.ini
    makeUsmIni dir "win" renderer antialias "plugins/" ".dll" ldeps nil;    
    
    //make master.pkg
    let ("typeof"::"env_ref=Env;;"::nil)::
        ("defcom"::"Smain=main"::"S"::"S"::"S"::"S"::"I;;"::nil)::
        ("fun"::"multiress(res)="::nil)::
        ("if"::"res==nil"::"then"::nil)::
        ("0"::nil)::
        ("else"::nil)::
        ("let"::"res"::"->"::"[l"::"nxt]"::"in"::nil)::
        ("("::nil)::
        ("_setress"::"hd"::"l"::"hd"::"tl"::"l;"::nil)::
        ("multiress"::"nxt;"::nil)::
        (");;"::nil)::
        
        ("fun"::"main(p)="::nil)::
        ("set"::"env_ref=_envchannel"::"_channel;"::nil)::
        ("multiress"::"strextr"::"_loadressini;"::nil)::  
        ("srand"::"time;"::nil)::
        ("_load"::(strcatn "\""::APPBASEDIR::"os3dplayer/os3dload.pkg\";"::nil)::nil)::
        ("_script"::"mkscript"::"Smain"::(strcatn "[\""::xmlpath::"\""::nil)::(strcatn "\""::fname::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultWidth" "1280")::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultHeight" "720")::"\""::nil)::"0];"::nil)::
        ("0;;"::nil)::nil
    -> pmaster in
    _storepack (strbuild pmaster) strcatn dir::"/partition/locked/master.pkg"::nil;
  );
  0;;


fun mkStandAloneListFiles(xmlpath)=
  let getFilesFromDir "locked" nil -> locked in
  let getFilesFromDirRecursive "locked/etc" -> etc in
  let getFilesFromDirRecursive "locked/lib" -> lcklib in
  let getFilesFromDirRecursive strcat APPBASEDIR "os3dlib" -> lib in
  let getFilesFromDirRecursive strcat APPBASEDIR "os3dplayer" -> player in
  let getMkAppletXmlResources xmlpath nil -> [lres ldeps] in
  let getProjectSetting "iconpath" -> icon in
  let if icon != nil then icon::(getProjectSetting "splashpath")::nil else (getProjectSetting "splashpath")::nil -> nres in
    [listLowercase findExcluFile (lcat (lcat (lcat (lcat (lcat (lcat locked etc) lcklib) lib) player) lres) nres) (quicksort ldeps @suppDoublon)];;


fun mkStandAloneProjectListFiles(xmlpath)=
  let getMkAppletXmlResources xmlpath nil -> [lres ldeps] in
  let getProjectSetting "iconpath" -> icon in
  let if icon != nil then icon::(getProjectSetting "splashpath")::nil else (getProjectSetting "splashpath")::nil -> nres in
    [listLowercase (quicksort findExcluFile (lcat lres nres) @suppDoublon) (quicksort ldeps @suppDoublon)];;


fun mkAppletListFiles(xmlpath)=
  let getFilesFromDirRecursive strcat APPBASEDIR "os3dlib" -> files in
  let lcat files (getFilesFromDirRecursive strcat APPBASEDIR "os3dplayer") -> files in
  let lcat files let (getMkAppletXmlResources xmlpath nil) -> [lf _] in lf -> files in
  let if (getProjectSetting "splashpath") != nil then (getProjectSetting "splashpath")::files else files -> files in
    listLowercase findExcluFile files;;


fun mkAppletListOS3DFiles(xmlpath)=
  let getFilesFromDirRecursive strcat APPBASEDIR "os3dlib" -> files in
  let lcat files (getFilesFromDirRecursive strcat APPBASEDIR "os3dplayer") -> files in
  let if (getProjectSetting "splashpath") != nil then (getProjectSetting "splashpath")::files else files -> files in
    listLowercase findExcluFile files;;


fun mkAppletGetAppMd5(xmlpath)=
  mkAppletGetFilesMd5 mkAppletListFiles xmlpath;;


fun cbProjectPacked(p)=
  let p -> [projname fname xmlpath lpakfiles cont bupload ftpstr] in
  (
    mkAppletCrypt ftpstr projname (strlowercase (strcat fname ".txt")) cont (mkAppletUpdateZpFilesName lpakfiles ftpstr.AFTP_sAppDir) xmlpath bupload;
    mkAppletAddLog ftpstr (loc "OS3D_0538");
  );
  0;;


fun cbMkAppletOkBtn(ctrlbtn, p)=
  let p -> [xmlpath projname script ftpstr] in
  let getDirectoryWithoutLastSlash (getEdCtrlTextLineValue ftpstr.AFTP_ctrlWww) -> www in
  let getDirectoryWithoutFirstSlash getDirectoryWithoutLastSlash (getEdCtrlTextLineValue ftpstr.AFTP_ctrlDir) -> appdir in
  let if (!strcmpi "" (strtrim appdir)) then nil else strlowercase appdir -> appdir in
  let getDirectoryWithoutLastSlash (getEdCtrlTextLineValue ftpstr.AFTP_ctrlRoot) -> ftproot in
  let if !strcmp (strtrim ftproot) "" then "/" else (strcat ftproot "/") -> ftproot in
  let (getEdCtrlTextLineValue ftpstr.AFTP_ctrlHost) -> ftphost in
  let ftoi (getEdCtrlFloatValue ftpstr.AFTP_ctrlPort) -> ftpport in
  let (getEdCtrlTextLineValue ftpstr.AFTP_ctrlLogin) -> ftplogin in
  let (getEdCtrlTextLineValue ftpstr.AFTP_ctrlPass) -> ftppass in
  let (getEdCtrlCheckState ftpstr.AFTP_ctrlInWeb) -> webin in
  let (getEdCtrlCheckState ftpstr.AFTP_ctrlUpload) -> bupload in
  let if appdir == nil then
        strcatn (if (!strcmp "http://" substr www 0 7) || (!strcmp "https://" substr www 0 8) then nil else "http://")::www::"/"::nil
      else
        strcatn (if (!strcmp "http://" substr www 0 7) || (!strcmp "https://" substr www 0 8) then nil else "http://")::www::"/"::appdir::"/"::nil
  -> url in
  if ((!strcmp (strtrim ftphost) "") || (ftpport == nil) || (!strcmp (strtrim ftplogin) "") || (!strcmp (strtrim ftppass) "") && bupload) || (!strcmp (strtrim www) "") then
  (
    _DLGMessageBox _channel ftpstr.AFTP_ctrlWindow.EDW_win (loc "OS3D_0519") (loc "OS3D_0537") 0;
    0;
  )
  else
  (
    set ftpstr.AFTP_bError = 0;
    set ftpstr.AFTP_iState = 0;
    set ftpstr.AFTP_sHost = ftphost;
    set ftpstr.AFTP_iport = ftpport;
    set ftpstr.AFTP_sLogin = ftplogin;
    set ftpstr.AFTP_sPass = ftppass;
    set ftpstr.AFTP_sDir = ftproot;
    set ftpstr.AFTP_sAppDir = appdir;
    set ftpstr.AFTP_sUrl = strreplace url " " "%20";
    set ftpstr.AFTP_bWebIn = webin;
    
    //save ftp configuration
    setProjectSetting "ftpHost" ftphost;
    setProjectSetting "ftpPort" itoa ftpport;
    setProjectSetting "ftpLogin" ftplogin;
    setProjectSetting "ftpRoot" ftproot;
    setProjectSetting "ftpDir" appdir;
    setProjectSetting "ftpWWW" www;
    setProjectSetting "ftpIntegrated" itoa webin;
    setProjectSetting "ftpUpload" itoa bupload;
    
    setEdCtrlTextValue ftpstr.AFTP_ctrlLog "";
    mkAppletEnableInterface ftpstr 0;
    
    if (!bupload) then nil else
    let ctime time -> date in
    let if ftpstr.AFTP_sAppDir == nil then strcatn sMkAppletTmpPath::"ftp.log"::nil else strcatn sMkAppletTmpPath::ftpstr.AFTP_sAppDir::"/"::"ftp.log"::nil -> logpath in
    (
      _storepack strcatn "OS3D FTP Upload on "::date::"\n"::nil logpath;
      set ftpstr.AFTP_wLogFile = _getmodifypack logpath;
    );
    
    let getFileNameWithoutExt xmlpath -> fname in
    let getFileDirectory xmlpath -> prjdir in
    let strlowercase strcatn prjdir::fname::".pak"::nil -> pakpath in
    let mkAppletListOS3DFiles xmlpath -> lfiles in
    let getMkAppletXmlResources xmlpath nil -> [resfiles _] in
    let if ftpstr.AFTP_sAppDir == nil then sMkAppletTmpPath else strcatn sMkAppletTmpPath::ftpstr.AFTP_sAppDir::"/"::nil -> tmppath in
    let pakpath::lfiles -> lpakfiles in
    let strcatn (mkAppletAddFile url lpakfiles nil)::"\nscript\n"::script::nil -> cont in
      mkPakProject ftpstr resfiles (strcat tmppath pakpath) xmlpath mkfun1 @cbProjectPacked [projname fname xmlpath lpakfiles cont bupload ftpstr];
  );
  0;;


fun cbMkAppletCancelBtn(ctrlbtn, p)=
  let p -> [winstr ftpstr] in
  (
    _TELNETClose ftpstr.AFTP_telnet;
    dsEdWindow winstr;
    set winMkApplet = nil;
  );
  0;;


fun cbDestroyExportAppletWin(winstr, ftpstr)=
  _TELNETClose ftpstr.AFTP_telnet;
  set winMkApplet = nil;
  0;;


fun mkApplet(fatherstr, projname, xmlpath, script)=
  if winMkApplet != nil then nil else
  (
    let _GETscreenSize -> [sw sh] in
    let [530 430] -> [iw ih] in
    let getFileNameWithoutExt xmlpath -> fname in
    
    //get the user ftp preference
    let getProjectSetting "ftpHost" -> ftphost in
    let itof (atoi getProjectSetting "ftpPort") -> ftpPort in
    let if (ftpPort == nil) then 21.0 else ftpPort -> ftpPort in
    let getProjectSetting "ftpLogin" -> ftpLogin in
    let getProjectSetting "ftpRoot" -> ftpRoot in
    let if (ftpRoot == nil) then "/" else ftpRoot -> ftpRoot in
    let getProjectSetting "ftpDir" -> ftpDir in
    let if (ftpDir == nil) then fname else ftpDir -> ftpDir in
    let getProjectSetting "ftpWWW" -> ftpWWW in
    let atoi (getProjectSetting "ftpIntegrated") -> ftpIntegrated in
    let if (ftpIntegrated == nil) then 1 else ftpIntegrated -> ftpIntegrated in
    let atoi (getProjectSetting "ftpUpload") -> ftpUpload in
    let if (ftpUpload == nil) then 1 else ftpUpload -> ftpUpload in
    
    let 10 -> ypos in
    let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0523") -> winstr in
    let crEdCtrlLabel winstr 10 ypos + 2 300 20 (loc "OS3D_0527") nil -> labelhost in
    let crEdCtrlTextLine winstr 320 ypos (iw - 330) 20 ftphost nil EDWIN_RESIZE_MW -> ctrlhost in
    let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 300 20 (loc "OS3D_0530") nil -> labelport in
    let crEdCtrlFloat winstr 320 ypos 60 20 ftpPort 1.0 65535.0 1.0 0 nil EDWIN_RESIZE_MW -> ctrlport in
    let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 300 20 (loc "OS3D_0528") nil -> labellogin in
    let crEdCtrlTextLine winstr 320 ypos (iw - 330) 20 ftpLogin nil EDWIN_RESIZE_MW -> ctrllogin in
    let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 300 20 (loc "OS3D_0529") nil -> labelpass in
    let crEdCtrlTextLine winstr 320 ypos (iw - 330) 20 "" ET_BORDER|ET_AHSCROLL|ET_TABFOCUS|ET_PASSWORD EDWIN_RESIZE_MW -> ctrlpass in
    let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 300 20 (loc "OS3D_0531") nil -> labelroot in
    let crEdCtrlTextLine winstr 320 ypos (iw - 330) 20 ftpRoot nil EDWIN_RESIZE_MW -> ctrlroot in
    let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 300 20 (loc "OS3D_0526") nil -> labeldir in
    let crEdCtrlTextLine winstr 320 ypos (iw - 330) 20 ftpDir nil EDWIN_RESIZE_MW -> ctrldir in
    let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 300 20 (loc "OS3D_0533") nil -> labelwww in
    let crEdCtrlTextLine winstr 320 ypos (iw - 330) 20 ftpWWW nil EDWIN_RESIZE_MW -> ctrlwww in
    let crEdCtrlCheck winstr 10 (set ypos = ypos + 25) (iw - 20) 20 (loc "OS3D_0535") EDWIN_RESIZE_MW -> ctrlwebin in
    let crEdCtrlCheck winstr 10 (set ypos = ypos + 25) (iw - 20) 20 (loc "OS3D_0546") EDWIN_RESIZE_MW -> ctrlupload in
    let crEdCtrlText winstr 10 (set ypos = ypos + 25) (iw - 20) 150 "" ET_BORDER|ET_AVSCROLL|ET_VSCROLL|ET_TABFOCUS EDWIN_RESIZE_MW -> ctrlinfos in
    let crEdCtrlButton winstr 10 (ih - 30) 90 20 (loc "OS3D_0536") EDWIN_RESIZE_MW -> ctrlok in
    let crEdCtrlButton winstr (iw - 100) (ih - 30) 90 20 (loc "OS3D_0513") EDWIN_RESIZE_MW -> ctrlcancel in
    let mkFtpSetting [nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil winstr ctrlhost ctrlport ctrllogin ctrlpass ctrlroot ctrldir ctrlwww ctrlwebin ctrlupload ctrlinfos ctrlok ctrlcancel 0 0 0] -> ftpstr in    
    (
      set winMkApplet = winstr;
      setEdCtrlCheckState ctrlwebin ftpIntegrated;
      setEdCtrlCheckState ctrlupload ftpUpload;
      setEdCtrlButtonCb ctrlok mkfun2 @cbMkAppletOkBtn [xmlpath projname script ftpstr];
      setEdCtrlButtonCb ctrlcancel mkfun2 @cbMkAppletCancelBtn [winstr ftpstr];
      
      setEdwindowCbDestroy winstr mkfun2 @cbDestroyExportAppletWin ftpstr;
    );
  );
  0;;


fun cbMkStandAloneDoneBtn(ctrlbtn, p)=
  let p -> [winstr exportdir archname xmlpath projname] in
  (
    dsEdWindow winstr;
    set winMkApplet = nil;
    let strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\Windows\\"::archname::"\\"::projname::nil -> fullpath in
    (
      _startExe "launch" "openExplorer" strcatn "\""::fullpath::"\""::nil;
    );
  );
  0;;


fun cbMkStandAloneCancelBtn(ctrlbtn, winstr)=
  dsEdWindow winstr;
  0;;


fun cbMkStandAloneOk(ctrlbtn, p)=
  let p -> [pwinstr fatherstr projname xmlpath script ctrlarch ctrlrenderer ctrlantialias] in
  let getSelectedEdCtrlSelectPos ctrlarch -> arch in
  let if (arch == 0) then "x86" else "x64" -> archname in
  let getSelectedEdCtrlSelect ctrlrenderer -> renderer in
  let getSelectedEdCtrlSelect ctrlantialias -> antialias in
  let _GETscreenSize -> [sw sh] in
  let [430 120] -> [iw ih] in
  let getDirectoryWithoutLastSlash (getFileDirectory xmlpath) -> projdir in
  let if (projdir == nil) || (!strcmp projdir "") then (strcatn sExportDirectory::"/Windows/"::archname::"/"::projname::nil) else (strcatn projdir::"/"::sExportDirectory::"/Windows/"::archname::"/"::projname::nil) -> exportdir in
  (
    dsEdWindow pwinstr;
    let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0522") -> winstr in
    let crEdCtrlLabelEx winstr 10 12 iw-20 50 (loc "OS3D_0524") ET_ALIGN_CENTER nil -> labelport in
    let crEdCtrlButton winstr ((iw /2) - 45) (ih - 30) 90 20 (loc "OS3D_0518") EDWIN_RESIZE_MW -> ctrldone in
    (
      set winMkApplet = winstr;
      setEdCtrlButtonEnable ctrldone 0;
      _addPartition "./windows" 2;
      let mkStandAloneListFiles xmlpath -> [lfiles ldeps] in
      (
        cleanDirectory exportdir;
        copyFilesToExportDirectory exportdir lfiles ldeps xmlpath projname archname renderer antialias;
      );
      
      _removeLastPartition;
      setEdCtrlLabelValue labelport strcatn (loc "OS3D_0520")::exportdir::(loc "OS3D_0548")::nil;
      setEdCtrlButtonCb ctrldone mkfun2 @cbMkStandAloneDoneBtn [winstr exportdir archname xmlpath projname];
      setEdCtrlButtonEnable ctrldone 1;
      setEdWindowFocus pwinstr;
    );
  );
  0;;


fun cbStandAloneRenderer(ctrlselect, pos, elem, ctrlantialias)=
  fillEdCtrlSelect ctrlantialias (SO3GetMultisamplingMode (if (!strcmp elem "DirectX9") then SO3_DIRECTX9_RENDERER else if (!strcmp elem "DirectX11") then SO3_DIRECTX11_RENDERER else SO3_OPENGL_RENDERER));
  0;;


fun mkStandAlone(fatherstr, projname, xmlpath, script)=
  _refreshExe;
  let _GETscreenSize -> [sw sh] in
  let [430 120] -> [iw ih] in
  let 10 -> ipos in
  let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0522") -> winstr in
  let crEdCtrlLabel winstr 10 (ipos + 2) 160 20 (loc "OS3D_0575") nil -> labelarch in
  let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 EDWIN_RESIZE_MW -> ctrlarch in
  let crEdCtrlLabel winstr 10 ((set ipos = ipos + 25) + 2) 160 20 (loc "OS3D_0539") nil -> labelrenderer in
  let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 CB_AHSCROLL -> ctrlrenderer in
  let crEdCtrlLabel winstr 10 ((set ipos = ipos + 25) + 2) 160 20 (loc "OS3D_0511") nil -> labelantialias in
  let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 CB_AHSCROLL -> ctrlantialias in
  
  let crEdCtrlButton winstr 10 (ih - 30) 90 20 (loc "OS3D_0536") EDWIN_RESIZE_MW -> ctrlok in
  let crEdCtrlButton winstr (iw - 100) (ih - 30) 90 20 (loc "OS3D_0513") EDWIN_RESIZE_MW -> ctrlcancel in
  let [winstr fatherstr projname xmlpath script ctrlarch ctrlrenderer ctrlantialias] -> p in
  (
    set winMkApplet = winstr;
    
    fillEdCtrlSelect ctrlarch "Windows 32bits"::"Windows 64bits"::nil;
    selectEdCtrlSelectByPos ctrlarch 0;
    
    fillEdCtrlSelect ctrlrenderer "DirectX9"/*::"DirectX11"*/::"OpenGL"::nil;
    selectEdCtrlSelect ctrlrenderer "OpenGL";
    setEdCtrlSelectCb ctrlrenderer mkfun4 @cbStandAloneRenderer ctrlantialias;
    fillEdCtrlSelect ctrlantialias (SO3GetMultisamplingMode SO3_OPENGL_RENDERER);
    selectEdCtrlSelectByPos ctrlantialias 1;
    setEdCtrlButtonCb ctrlok mkfun2 @cbMkStandAloneOk p;
    setEdCtrlButtonCb ctrlcancel mkfun2 @cbMkStandAloneCancelBtn winstr;
  );
  0;;


fun checkAndroidPkgName(name)=
  let name -> cpname in
  //do strlowercase on the copied string, this modify the original string otherwise
  let (strreplace (strreplace (strreplace strlowercase cpname " " "") "-" "") "_" "") -> nname in
  (
    let "0"::"1"::"2"::"3"::"4"::"5"::"6"::"7"::"8"::"9"::nil -> nums in
    let 0 -> dotpos in
    while ((set dotpos = strfind "." nname dotpos) != nil) do
    (
      //no number after a dot!
      if (!isStringInList nums (substr nname (dotpos + 1) 1)) then nil else
        set nname = strcat (substr nname 0 dotpos + 1) (substr nname (dotpos + 2) strlen nname);
      
      set dotpos = dotpos + 1;
    );
    
    let "."::"a"::"b"::"c"::"d"::"e"::"f"::"g"::"h"::"i"::"j"::"k"::"l"::"m"::"n"::"o"::"p"::"q"::"r"::"s"::"t"::"u"::"v"::"w"::"x"::"y"::"z"::"0"::"1"::"2"::"3"::"4"::"5"::"6"::"7"::"8"::"9"::nil -> alphanum in
    let 0 -> pos in
    let "" -> fname in
    (
      while ((strlen nname) > 0) do
      (
        let substr nname 0 1 -> letter in
        if (!isStringInList alphanum letter) then nil else
          set fname = strcat fname letter;
        set nname = substr nname 1 strlen nname;
      );
      
      //addLogMessage strcatn name::" > "::fname::nil;
      if (!strcmp name fname) && (fname != nil) && ((strlen fname) > 4) && ((strfind "." fname (strfind "." fname 0) + 1) != nil) then
        1
      else
        0;
    );
  );;


fun getAndroidShortName(name)=
  let strdup name -> cpname in
  //do strlowercase on the copied string, this modify the original string otherwise
  let strlowercase cpname -> nname in
  (   
    let "a"::"b"::"c"::"d"::"e"::"f"::"g"::"h"::"i"::"j"::"k"::"l"::"m"::"n"::"o"::"p"::"q"::"r"::"s"::"t"::"u"::"v"::"w"::"x"::"y"::"z"::"0"::"1"::"2"::"3"::"4"::"5"::"6"::"7"::"8"::"9"::nil -> alphanum in
    let 0 -> pos in
    let "" -> fname in
    (
      while ((strlen nname) > 0) do
      (
        let substr nname 0 1 -> letter in
        if (!isStringInList alphanum letter) then nil else
          set fname = strcat fname letter;
        set nname = substr nname 1 strlen nname;
      );
      fname;
    );
  );;


//// ANDROID
fun copyAndroidFilesToExportDirectory(dir, lfiles, ldeps, xmlpath, fname, keystorepath, pass, arch)=
  let getAndroidShortName fname -> shortname in
  (
    //copy scol base
    let getFilesFromDirRecursive "bin" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    let getFilesFromDirRecursive "dex" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    let getFilesFromDirRecursive "package/assets" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );

    //copy plugins and kernel
    if (!strcmpi arch "all") then
    (
      let getDirListFromPath "package/lib" -> larch in
      while larch != nil do
      (
        let hd larch -> darch in
        let getFilesFromDir darch "so"::nil -> lroot in
        let lcat lPluginsBase "kernel"::ldeps -> fulldeps in
        let keepFilesBase lroot fulldeps "lib" -> lroot in
        while lroot != nil do
        (
          let hd lroot -> file in
            copyFileContent file strcatn dir::"/"::file::nil;
          
          set lroot = tl lroot;
        );
        set larch = tl larch;
      );
    )
    else
    (
      let getFilesFromDir strcat "package/lib/" arch "so"::nil -> lroot in
      let lcat lPluginsBase "kernel"::ldeps -> fulldeps in
      let keepFilesBase lroot fulldeps "lib" -> lroot in
      while lroot != nil do
      (
        let hd lroot -> file in
          copyFileContent file strcatn dir::"/"::file::nil;
        
        set lroot = tl lroot;
      );
    );
      
    let getFilesFromDirRecursive "res" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    while lfiles != nil do
    (
      let hd lfiles -> file in
        copyFileContent file strcatn dir::"/package/assets/partition/"::file::nil;
      
      set lfiles = tl lfiles;
    );
    
    copyFileContent "logo.bmp" strcatn dir::"/package/assets/partition/"::"logo.bmp"::nil;
    
    let _checkpack getProjectSetting "iconpath" -> iconpath in
    if (iconpath == nil) then nil else
    (
      let G2DloadAlphaBmp _channel _PtoScol iconpath -> icon_src in
      (
        // XXXHDPI ICON 
        let _CRbitmap _channel 192 192 -> bmp in
        let _CRbitmap8 _channel 192 192 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xxxhdpi in
        (
          _BTSAVEalphaBitmap icon_xxxhdpi _getmodifypack strcatn dir::"/res/drawable-xxhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XXHDPI ICON 
        let _CRbitmap _channel 144 144 -> bmp in
        let _CRbitmap8 _channel 144 144 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xxhdpi in
        (
          _BTSAVEalphaBitmap icon_xxhdpi _getmodifypack strcatn dir::"/res/drawable-xxhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XHDPI ICON 
        let _CRbitmap _channel 96 96 -> bmp in
        let _CRbitmap8 _channel 96 96 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xhdpi in
        (
          _BTSAVEalphaBitmap icon_xhdpi _getmodifypack strcatn dir::"/res/drawable-xhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XHDPI BANNER 
        let _FILLbitmap _CRbitmap _channel 320 180 0xffffff -> bmp in
        let _FILLbitmap8 _CRbitmap8 _channel 320 180 255 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _GETalphaBitmapSize icon_src -> [sw sh] in
        let _BTBLENDalphaBitmaps abmp [80 10 160 160] icon_src [0 0 sw sh] 1.0 -> banner_xhdpi in
        (
          _BTSAVEalphaBitmap banner_xhdpi _getmodifypack strcatn dir::"/res/drawable-xhdpi/banner.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // HDPI ICON
        let _CRbitmap _channel 72 72 -> bmp in
        let _CRbitmap8 _channel 72 72 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_hdpi in
        (
          _BTSAVEalphaBitmap icon_hdpi _getmodifypack strcatn dir::"/res/drawable-hdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        // MDPI ICON
        let _CRbitmap _channel 48 48 -> bmp in
        let _CRbitmap8 _channel 48 48 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_mdpi in
        (
          _BTSAVEalphaBitmap icon_mdpi _getmodifypack strcatn dir::"/res/drawable-mdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        // LDPI ICON
        let _CRbitmap _channel 36 36 -> bmp in
        let _CRbitmap8 _channel 36 36 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_ldpi in
        (
          _BTSAVEalphaBitmap icon_ldpi _getmodifypack strcatn dir::"/res/drawable-ldpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        _DSalphaBitmap icon_src;
      );
    );
    
    let (getProjectSetting "splashpath") -> psplash in
    if ((_checkpack psplash) == nil) then
    (
      let getProjectSettingDef "appOrientation" "landscape" -> corient in
      let if (!strcmpi corient "landscape") || (!strcmpi corient "reverseLandscape") then 0 else 1 -> vert in
      if (!vert) then nil else        
        copyFileContent (strcatn APPBASEDIR::"os3dplayer/splash_vert.png"::nil) strcatn dir::"/package/assets/partition/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    )
    else
      copyFileContent psplash strcatn dir::"/package/assets/partition/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    
    // add splash path in usm.ini for android splash managed in java
    //make usm.ini
    makeUsmIni strcat dir "/package/assets" "android" "OpenGLES2" "2" "lib" ".so" ldeps ("backgroundTask"::"no"::nil)::("splash"::(strcat APPBASEDIR "os3dplayer/splash.png")::nil)::nil;
    
    //make manifest
    let _getpack _checkpack "AndroidManifest.xml.in" -> manifest in
    (
      set manifest = strreplace manifest "@ANDROID_PKG_NAME@" getProjectSettingDef "appPkgName" (strcat "os3d.app." shortname);
      set manifest = strreplace manifest "@ANDROID_APP_NAME@" fname;
      set manifest = strreplace manifest "@ANDROID_VERSION@" itoa (time + 100000000000);
      set manifest = strreplace manifest "@ANDROID_VERSION_NAME@" getProjectVersion;
      set manifest = strreplace manifest "@ANDROID_USE_SDK@" "<uses-sdk android:minSdkVersion=\"19\" android:targetSdkVersion=\"28\" />";
      set manifest = strreplace manifest "@ANDROID_ORIENTATION@" getProjectSettingDef "appOrientation" "landscape";
      
      _storepack manifest strcatn dir::"/AndroidManifest.xml"::nil;
    );
    
    //make master.pkg
    let ("typeof"::"env_ref=Env;;"::nil)::
        ("defcom"::"Smain=main"::"S"::"S"::"S"::"S"::"I;;"::nil)::
        ("fun"::"multiress(res)="::nil)::
        ("if"::"res==nil"::"then"::nil)::
        ("0"::nil)::
        ("else"::nil)::
        ("let"::"res"::"->"::"[l"::"nxt]"::"in"::nil)::
        ("("::nil)::
        ("_setress"::"hd"::"l"::"hd"::"tl"::"l;"::nil)::
        ("multiress"::"nxt;"::nil)::
        (");;"::nil)::
        
        ("fun"::"main(p)="::nil)::
        ("set"::"env_ref=_envchannel"::"_channel;"::nil)::
        ("multiress"::"strextr"::"_loadressini;"::nil)::  
        ("srand"::"time;"::nil)::
        ("_load"::(strcatn "\""::APPBASEDIR::"os3dplayer/os3dload.pkg\";"::nil)::nil)::
        ("_script"::"mkscript"::"Smain"::(strcatn "[\""::xmlpath::"\""::nil)::(strcatn "\""::fname::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultWidth" "1280")::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultHeight" "720")::"\""::nil)::"0];"::nil)::
        ("0;;"::nil)::nil
    -> pmaster in
    _storepack (strbuild pmaster) strcatn dir::"/package/assets/partition/locked/master.pkg"::nil;
    
    if (keystorepath != nil) then nil else
    let makeAndroidSigninKey _getmodifypack "keystores/default.keystore" shortname "password" ["CN" "I-Maginer"]::["C" "FR"]::nil -> [kpath output] in
      set keystorepath = kpath;
    
    if (pass != nil && strcmp pass "") then nil else
      set pass = "password";
    
    let makeAndroidAPK shortname (strcat dir "/AndroidManifest.xml") -> [unsignedapk output] in
    if unsignedapk == nil then [unsignedapk output] else
      signAndroidAPK unsignedapk keystorepath shortname pass;
  );;


fun copyAndroidBundleFilesToExportDirectory(dir, lfiles, ldeps, xmlpath, fname, keystorepath, pass, arch)=
  let getAndroidShortName fname -> shortname in
  let if keystorepath != nil then 1 else 0 -> encryptkey in
  (
    //copy scol base
    let getFilesFromDirRecursive "bin" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    let getFilesFromDirRecursive "dex" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    let getFilesFromDirRecursive "package/assets" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );

    //copy plugins and kernel
    if (!strcmpi arch "all") then
    (
      let getDirListFromPath "package/lib" -> larch in
      while larch != nil do
      (
        let hd larch -> darch in
        let getFilesFromDir darch "so"::nil -> lroot in
        let lcat lPluginsBase "kernel"::ldeps -> fulldeps in
        let keepFilesBase lroot fulldeps "lib" -> lroot in
        while lroot != nil do
        (
          let hd lroot -> file in
            copyFileContent file strcatn dir::"/"::file::nil;
          
          set lroot = tl lroot;
        );
        set larch = tl larch;
      );
    )
    else
    (
      let getFilesFromDir strcat "package/lib/" arch "so"::nil -> lroot in
      let lcat lPluginsBase "kernel"::ldeps -> fulldeps in
      let keepFilesBase lroot fulldeps "lib" -> lroot in
      while lroot != nil do
      (
        let hd lroot -> file in
          copyFileContent file strcatn dir::"/"::file::nil;
        
        set lroot = tl lroot;
      );
    );
    
    let getFilesFromDirRecursive2 "res" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContentC file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    while lfiles != nil do
    (
      let hd lfiles -> file in
        copyFileContent file strcatn dir::"/package/assets/partition/"::file::nil;
      
      set lfiles = tl lfiles;
    );    
    
    copyFileContent "logo.bmp" strcatn dir::"/package/assets/partition/"::"logo.bmp"::nil;
    
    let _checkpack getProjectSetting "iconpath" -> iconpath in
    if (iconpath == nil) then nil else
    (
      let G2DloadAlphaBmp _channel _PtoScol iconpath -> icon_src in
      (
        // XXXHDPI ICON 
        let _CRbitmap _channel 192 192 -> bmp in
        let _CRbitmap8 _channel 192 192 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xxxhdpi in
        (
          _BTSAVEalphaBitmap icon_xxxhdpi _getmodifypack strcatn dir::"/res/drawable-xxhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XXHDPI ICON 
        let _CRbitmap _channel 144 144 -> bmp in
        let _CRbitmap8 _channel 144 144 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xxhdpi in
        (
          _BTSAVEalphaBitmap icon_xxhdpi _getmodifypack strcatn dir::"/res/drawable-xxhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XHDPI ICON 
        let _CRbitmap _channel 96 96 -> bmp in
        let _CRbitmap8 _channel 96 96 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xhdpi in
        (
          _BTSAVEalphaBitmap icon_xhdpi _getmodifypack strcatn dir::"/res/drawable-xhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XHDPI BANNER 
        let _FILLbitmap _CRbitmap _channel 320 180 0xffffff -> bmp in
        let _FILLbitmap8 _CRbitmap8 _channel 320 180 255 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _GETalphaBitmapSize icon_src -> [sw sh] in
        let _BTBLENDalphaBitmaps abmp [80 10 160 160] icon_src [0 0 sw sh] 1.0 -> banner_xhdpi in
        (
          _BTSAVEalphaBitmap banner_xhdpi _getmodifypack strcatn dir::"/res/drawable-xhdpi/banner.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // HDPI ICON
        let _CRbitmap _channel 72 72 -> bmp in
        let _CRbitmap8 _channel 72 72 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_hdpi in
        (
          _BTSAVEalphaBitmap icon_hdpi _getmodifypack strcatn dir::"/res/drawable-hdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        // MDPI ICON
        let _CRbitmap _channel 48 48 -> bmp in
        let _CRbitmap8 _channel 48 48 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_mdpi in
        (
          _BTSAVEalphaBitmap icon_mdpi _getmodifypack strcatn dir::"/res/drawable-mdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        // LDPI ICON
        let _CRbitmap _channel 36 36 -> bmp in
        let _CRbitmap8 _channel 36 36 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_ldpi in
        (
          _BTSAVEalphaBitmap icon_ldpi _getmodifypack strcatn dir::"/res/drawable-ldpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        _DSalphaBitmap icon_src;
      );
    );
    
    let (getProjectSetting "splashpath") -> psplash in
    if ((_checkpack psplash) == nil) then
    (
      let getProjectSettingDef "appOrientation" "landscape" -> corient in
      let if (!strcmpi corient "landscape") || (!strcmpi corient "reverseLandscape") then 0 else 1 -> vert in
      if (!vert) then nil else        
        copyFileContent (strcatn APPBASEDIR::"os3dplayer/splash_vert.png"::nil) strcatn dir::"/package/assets/partition/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    )
    else
      copyFileContent psplash strcatn dir::"/package/assets/partition/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    
    // add splash path in usm.ini for android splash managed in java
    //make usm.ini
    makeUsmIni strcat dir "/package/assets" "android" "OpenGLES2" "2" "lib" ".so" ldeps ("backgroundTask"::"no"::nil)::("splash"::(strcat APPBASEDIR "os3dplayer/splash.png")::nil)::nil;
    
    //make manifest
    let _getpack _checkpack "AndroidManifest.xml.in" -> manifest in
    (
      set manifest = strreplace manifest "@ANDROID_PKG_NAME@" getProjectSettingDef "appPkgName" (strcat "os3d.app." shortname);
      set manifest = strreplace manifest "@ANDROID_APP_NAME@" fname;
      set manifest = strreplace manifest "@ANDROID_VERSION@" itoa (time + 100000000000);
      set manifest = strreplace manifest "@ANDROID_VERSION_NAME@" getProjectVersion;
      set manifest = strreplace manifest "@ANDROID_USE_SDK@" "<uses-sdk android:minSdkVersion=\"19\" android:targetSdkVersion=\"28\" />";
      set manifest = strreplace manifest "@ANDROID_ORIENTATION@" getProjectSettingDef "appOrientation" "landscape";
      
      _storepack manifest strcatn dir::"/AndroidManifest.xml"::nil;
    );
    
    //make master.pkg
    let ("typeof"::"env_ref=Env;;"::nil)::
        ("defcom"::"Smain=main"::"S"::"S"::"S"::"S"::"I;;"::nil)::
        ("fun"::"multiress(res)="::nil)::
        ("if"::"res==nil"::"then"::nil)::
        ("0"::nil)::
        ("else"::nil)::
        ("let"::"res"::"->"::"[l"::"nxt]"::"in"::nil)::
        ("("::nil)::
        ("_setress"::"hd"::"l"::"hd"::"tl"::"l;"::nil)::
        ("multiress"::"nxt;"::nil)::
        (");;"::nil)::
        
        ("fun"::"main(p)="::nil)::
        ("set"::"env_ref=_envchannel"::"_channel;"::nil)::
        ("multiress"::"strextr"::"_loadressini;"::nil)::  
        ("srand"::"time;"::nil)::
        ("_load"::(strcatn "\""::APPBASEDIR::"os3dplayer/os3dload.pkg\";"::nil)::nil)::
        ("_script"::"mkscript"::"Smain"::(strcatn "[\""::xmlpath::"\""::nil)::(strcatn "\""::fname::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultWidth" "1280")::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultHeight" "720")::"\""::nil)::"0];"::nil)::
        ("0;;"::nil)::nil
    -> pmaster in
    _storepack (strbuild pmaster) strcatn dir::"/package/assets/partition/locked/master.pkg"::nil;
    
    if (keystorepath != nil) then nil else
    let makeAndroidSigninKey _getmodifypack "keystores/default.keystore" shortname "password" ["CN" "I-Maginer"]::["C" "FR"]::nil -> [kpath output] in
      set keystorepath = kpath;
    
    if (pass != nil && strcmp pass "") then nil else
      set pass = "password";
      
    //encryptAndroidSigninKey keystorepath shortname pass dir;
    
    let makeAndroidAppBundle shortname (strcat dir "/AndroidManifest.xml") -> [unsignedbundle output] in
    if unsignedbundle == nil then [unsignedbundle output] else
    (
      if !encryptkey then nil else
        encryptAndroidSigninKey keystorepath shortname pass unsignedbundle;
      signAndroidAppBundle unsignedbundle keystorepath shortname pass;
    );
  );;


fun copyAndroidProjectFilesToExportDirectory(dir, lfiles, ldeps, xmlpath, fname, arch)=
  let getAndroidShortName fname -> shortname in  
  let strcat dir "/app/src/main" -> appdir in
  (
    //copy scol base
    let getFilesFromDirRecursive "bin" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    let getFilesFromDirRecursive "package/assets" -> lbase in
    let strlen "package" -> bsize in
    while lbase != nil do
    (
      let hd lbase -> file in
      let substr file bsize ((strlen file) - bsize) -> nfile in
        copyFileContent file strcatn appdir::"/"::nfile::nil;
      
      set lbase = tl lbase;
    );

    //copy plugins and kernel
    let strlen "package/lib" -> bsize in
    if (!strcmpi arch "all") then
    (
      let getDirListFromPath "package/lib" -> larch in
      while larch != nil do
      (
        let hd larch -> darch in
        let getFilesFromDir darch "so"::nil -> lroot in
        let lcat lPluginsBase "kernel"::ldeps -> fulldeps in
        let keepFilesBase lroot fulldeps "lib" -> lroot in
        while lroot != nil do
        (
          let hd lroot -> file in
          let substr file bsize ((strlen file) - bsize) -> nfile in
            copyFileContent file strcatn appdir::"/jniLibs/"::nfile::nil;
          
          set lroot = tl lroot;
        );
        set larch = tl larch;
      );
    )
    else
    (
      let getFilesFromDir strcat "package/lib/" arch "so"::nil -> lroot in
      let lcat lPluginsBase "kernel"::ldeps -> fulldeps in
      let keepFilesBase lroot fulldeps "lib" -> lroot in
      while lroot != nil do
      (
        let hd lroot -> file in
        let substr file bsize ((strlen file) - bsize) -> nfile in
          copyFileContent file strcatn appdir::"/jniLibs/"::nfile::nil;
        
        set lroot = tl lroot;
      );
    );
    
    let getFilesFromDirRecursive2 "res" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContentC file strcatn appdir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    //java
    let getFilesFromDirRecursive2 "java" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContentC file strcatn appdir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    while lfiles != nil do
    (
      let hd lfiles -> file in
        copyFileContent file strcatn appdir::"/assets/partition/"::file::nil;
      
      set lfiles = tl lfiles;
    );    
    
    copyFileContent "logo.bmp" strcatn appdir::"/assets/partition/"::"logo.bmp"::nil;
    
    let _checkpack getProjectSetting "iconpath" -> iconpath in
    if (iconpath == nil) then nil else
    (
      let G2DloadAlphaBmp _channel _PtoScol iconpath -> icon_src in
      (
        // XXXHDPI ICON 
        let _CRbitmap _channel 192 192 -> bmp in
        let _CRbitmap8 _channel 192 192 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xxxhdpi in
        (
          _BTSAVEalphaBitmap icon_xxxhdpi _getmodifypack strcatn appdir::"/res/drawable-xxhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XXHDPI ICON 
        let _CRbitmap _channel 144 144 -> bmp in
        let _CRbitmap8 _channel 144 144 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xxhdpi in
        (
          _BTSAVEalphaBitmap icon_xxhdpi _getmodifypack strcatn appdir::"/res/drawable-xxhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XHDPI ICON 
        let _CRbitmap _channel 96 96 -> bmp in
        let _CRbitmap8 _channel 96 96 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xhdpi in
        (
          _BTSAVEalphaBitmap icon_xhdpi _getmodifypack strcatn appdir::"/res/drawable-xhdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // XHDPI BANNER 
        let _FILLbitmap _CRbitmap _channel 320 180 0xffffff -> bmp in
        let _FILLbitmap8 _CRbitmap8 _channel 320 180 255 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _GETalphaBitmapSize icon_src -> [sw sh] in
        let _BTBLENDalphaBitmaps abmp [80 10 160 160] icon_src [0 0 sw sh] 1.0 -> banner_xhdpi in
        (
          _BTSAVEalphaBitmap banner_xhdpi _getmodifypack strcatn appdir::"/res/drawable-xhdpi/banner.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // HDPI ICON
        let _CRbitmap _channel 72 72 -> bmp in
        let _CRbitmap8 _channel 72 72 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_hdpi in
        (
          _BTSAVEalphaBitmap icon_hdpi _getmodifypack strcatn appdir::"/res/drawable-hdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        // MDPI ICON
        let _CRbitmap _channel 48 48 -> bmp in
        let _CRbitmap8 _channel 48 48 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_mdpi in
        (
          _BTSAVEalphaBitmap icon_mdpi _getmodifypack strcatn appdir::"/res/drawable-mdpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        // LDPI ICON
        let _CRbitmap _channel 36 36 -> bmp in
        let _CRbitmap8 _channel 36 36 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_ldpi in
        (
          _BTSAVEalphaBitmap icon_ldpi _getmodifypack strcatn appdir::"/res/drawable-ldpi/ic_launcher.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        _DSalphaBitmap icon_src;
      );
    );
    
    let (getProjectSetting "splashpath") -> psplash in
    if ((_checkpack psplash) == nil) then
    (
      let getProjectSettingDef "appOrientation" "landscape" -> corient in
      let if (!strcmpi corient "landscape") || (!strcmpi corient "reverseLandscape") then 0 else 1 -> vert in
      if (!vert) then nil else        
        copyFileContent (strcatn APPBASEDIR::"os3dplayer/splash_vert.png"::nil) strcatn appdir::"/assets/partition/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    )
    else
      copyFileContent psplash strcatn appdir::"/assets/partition/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    
    // add splash path in usm.ini for android splash managed in java
    //make usm.ini
    makeUsmIni strcat appdir "/assets" "android" "OpenGLES2" "2" "lib" ".so" ldeps ("backgroundTask"::"no"::nil)::("splash"::(strcat APPBASEDIR "os3dplayer/splash.png")::nil)::nil;
    
    //make manifest
    let _getpack _checkpack "AndroidManifest.xml.in" -> manifest in
    (
      set manifest = strreplace manifest "@ANDROID_PKG_NAME@" getProjectSettingDef "appPkgName" (strcat "os3d.app." shortname);
      set manifest = strreplace manifest "@ANDROID_APP_NAME@" fname;
      set manifest = strreplace manifest "@ANDROID_VERSION@" itoa (time + 100000000000);
      set manifest = strreplace manifest "@ANDROID_VERSION_NAME@" getProjectVersion;
      set manifest = strreplace manifest "@ANDROID_USE_SDK@" "";
      set manifest = strreplace manifest "@ANDROID_ORIENTATION@" getProjectSettingDef "appOrientation" "landscape";
      
      _storepack manifest strcatn appdir::"/AndroidManifest.xml"::nil;
    );
    
    //make gradle
    let _getpack _checkpack "build.gradle.in" -> gradle in
    (
      set gradle = strreplace gradle "@ANDROID_PKG_NAME@" getProjectSettingDef "appPkgName" (strcat "os3d.app." shortname);
            
      _storepack gradle strcatn dir::"/app/build.gradle"::nil;
    );
    
    _storepack "include ':app'\n" strcatn dir::"/settings.gradle"::nil;
    
    copyFileContent "build.gradle.root.in" strcatn dir::"/build.gradle"::nil;
    
    //make master.pkg
    let ("typeof"::"env_ref=Env;;"::nil)::
        ("defcom"::"Smain=main"::"S"::"S"::"S"::"S"::"I;;"::nil)::
        ("fun"::"multiress(res)="::nil)::
        ("if"::"res==nil"::"then"::nil)::
        ("0"::nil)::
        ("else"::nil)::
        ("let"::"res"::"->"::"[l"::"nxt]"::"in"::nil)::
        ("("::nil)::
        ("_setress"::"hd"::"l"::"hd"::"tl"::"l;"::nil)::
        ("multiress"::"nxt;"::nil)::
        (");;"::nil)::
        
        ("fun"::"main(p)="::nil)::
        ("set"::"env_ref=_envchannel"::"_channel;"::nil)::
        ("multiress"::"strextr"::"_loadressini;"::nil)::  
        ("srand"::"time;"::nil)::
        ("_load"::(strcatn "\""::APPBASEDIR::"os3dplayer/os3dload.pkg\";"::nil)::nil)::
        ("_script"::"mkscript"::"Smain"::(strcatn "[\""::xmlpath::"\""::nil)::(strcatn "\""::fname::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultWidth" "1280")::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultHeight" "720")::"\""::nil)::"0];"::nil)::
        ("0;;"::nil)::nil
    -> pmaster in
    _storepack (strbuild pmaster) strcatn appdir::"/assets/partition/locked/master.pkg"::nil;
    0;    
  );;


fun cbMkAndroidDoneBtn(ctrlbtn, p)=
  let p -> [winstr pwinstr exportdir xmlpath projname arch mode] in
  (
    dsEdWindow winstr;
    dsEdWindow pwinstr;
    set winMkApplet = nil;
    let if (mode == 2) then 
          strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\Android_"::"project"::"\\"::projname::nil
        else if (mode == 1) then
          strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\Android_"::"bundle"::"\\"::projname::nil
        else
          strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\Android_"::arch::"\\"::projname::nil
    -> fullpath in
    (
      _startExe "launch" "openExplorer" strcatn "\""::fullpath::"\""::nil;
    );
  );
  0;;


fun cbMkAndroidCancelBtn(ctrlbtn, winstr)=
  dsEdWindow winstr;
  0;;


fun cbDestroyAndroidExportWin(winstr, pwinstr)=
  dsEdWindow2 pwinstr;
  0;;


fun cbMkAndroidOk(ctrlbtn, p)=
  let p -> [pwinstr fatherstr projname xmlpath script keystorepath ctrlexport ctrlarch ctrlkeystorepath ctrlkeystorepass ctrldeploy ctrlorient ctrlpkgname] in
  let _GETscreenSize -> [sw sh] in
  let [430 120] -> [iw ih] in
  let getDirectoryWithoutLastSlash (getFileDirectory xmlpath) -> projdir in
  let getEdCtrlCheckState ctrldeploy -> deploy in
  let getEdCtrlTextLineValue ctrlkeystorepass -> pass in
  let getSelectedEdCtrlSelectPos ctrlexport -> mode in
  let getSelectedEdCtrlSelect ctrlarch -> arch in
  let if ((!strcmp arch "default") || mode != 0) then "all" else arch -> arch in
  let getSelectedEdCtrlSelectPos ctrlorient -> orientation in
  let getEdCtrlTextLineValue ctrlpkgname -> pkgname in
  let if (mode == 2) then "project" else if (mode == 1) then "bundle" else arch -> archdir in
  let if (projdir == nil) || (!strcmp projdir "") then (strcatn sExportDirectory::"/Android_"::archdir::"/"::projname::nil) else (strcatn projdir::"/"::sExportDirectory::"/Android_"::archdir::"/"::projname::nil) -> exportdir in
  (
    //set conf
    let if (orientation == 0) then
          "landscape"
        else if (orientation == 1) then
          "portrait"
        else if (orientation == 2) then
          "reverseLandscape"
        else
          "reversePortrait"
    -> orientmode in
    setProjectSetting "appOrientation" orientmode;    
    setProjectSetting "appAndroidType" (itoa mode);
    setProjectSetting "appAndroidArch" itoa (getSelectedEdCtrlSelectPos ctrlarch);
    
    if (!checkAndroidPkgName(pkgname)) then
    (
      _DLGMessageBox _channel pwinstr.EDW_win (loc "OS3D_0155") strcatn (loc "OS3D_0586")::nil 0;
      0;
    )
    else
    (
      setProjectSetting "appPkgName" strlowercase pkgname;
    
      let crEdModalDialogWindow _channel pwinstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
      let crEdCtrlLabelEx winstr 10 12 iw-20 50 (loc "OS3D_0524") ET_ALIGN_CENTER nil -> labelport in
      let crEdCtrlButton winstr ((iw /2) - 45) (ih - 30) 90 20 (loc "OS3D_0518") EDWIN_RESIZE_MW -> ctrldone in
      (
        set winMkApplet = winstr;
        
        setEdCtrlButtonEnable ctrldone 0;
        _addPartition "./androidDeployerTools/scolbase" 2;
        let mkStandAloneListFiles xmlpath -> [lfiles ldeps] in
        (
          cleanDirectory exportdir;
          if (mode == 2) then
          (
            copyAndroidProjectFilesToExportDirectory exportdir lfiles ldeps xmlpath projname arch;
            setEdCtrlButtonCb ctrldone mkfun2 @cbMkAndroidDoneBtn [winstr pwinstr exportdir xmlpath projname arch mode];
            setEdwindowCbDestroy winstr mkfun2 @cbDestroyAndroidExportWin pwinstr;
  
            setEdWindowFocus winstr;
            0;
          )
          else if (mode == 1) then
          (
            let copyAndroidBundleFilesToExportDirectory exportdir lfiles ldeps xmlpath projname keystorepath pass arch -> [signedapk output] in
            if (signedapk != nil) then
            (
            setEdCtrlButtonCb ctrldone mkfun2 @cbMkAndroidDoneBtn [winstr pwinstr exportdir xmlpath projname arch mode];
            setEdwindowCbDestroy winstr mkfun2 @cbDestroyAndroidExportWin pwinstr;
  
            setEdWindowFocus winstr;
            0;
            )
            else
            (
              dsEdWindow winstr;
              _DLGMessageBox _channel pwinstr.EDW_win (loc "OS3D_0155") strcatn (loc "OS3D_0560")::"\n\n"::output::nil 0;
              0;
            );
          )
          else
          (
            let copyAndroidFilesToExportDirectory exportdir lfiles ldeps xmlpath projname keystorepath pass arch -> [signedapk output] in
            if (signedapk != nil) then
            (
              if (!deploy) then nil else
                installAndroidAPK signedapk;
              
              setEdCtrlButtonCb ctrldone mkfun2 @cbMkAndroidDoneBtn [winstr pwinstr exportdir xmlpath projname arch mode];
              setEdwindowCbDestroy winstr mkfun2 @cbDestroyAndroidExportWin pwinstr;
    
              setEdWindowFocus winstr;
              0;
            )
            else
            (
              dsEdWindow winstr;
              _DLGMessageBox _channel pwinstr.EDW_win (loc "OS3D_0155") strcatn (loc "OS3D_0560")::"\n\n"::output::nil 0;
              0;
            );
          );
        );
        
        _removeLastPartition;
        setEdCtrlLabelValue labelport strcatn (loc "OS3D_0520")::exportdir::(loc "OS3D_0548")::nil;
        setEdCtrlButtonEnable ctrldone 1;
      );
      
      0;
    );
  );
  0;;


fun cbMkAndroidValidate(ctrl, val, p)=
  cbMkAndroidOk nil p;
  0;;


fun cbDlgAndroidGetKeyStorePath(dlg, p, pfile)=
  let p -> [ctrlbtn p1] in
  let p1 -> [pwinstr fatherstr projname xmlpath script keystorepath ctrlexport ctrlarch ctrlkeystorepath ctrlkeystorepass ctrldeploy ctrlorient ctrlpkgname] in
  (
    if pfile == nil then nil else
    let _GetFileNameFromP pfile -> fname in
      setEdCtrlTextLineValue ctrlkeystorepath fname;

    setEdCtrlButtonEnable ctrlbtn 1;
    setProjectSetting "keystorepath" _PtoScol pfile;
    mutate p1 <- [_ _ _ _ _ pfile _ _ _ _ _ _ _];
  );
  0;;
 
 
fun cbBtnAndroidPickKeyStorePath(ctrlbtn, p)=
  let p -> [winstr _ _ xmlpath _ _ _ _ _ _ _ _ _] in
  (
    setEdCtrlButtonEnable ctrlbtn 0;
    
    let getFileDirectory xmlpath -> dir in
      _DLGrflopen _DLGOpenFile _channel winstr.EDW_win nil nil "Key Store (*.keystore)\0*.keystore\0All\0*.*\0\0" @cbDlgAndroidGetKeyStorePath [ctrlbtn p];
  );
  0;;


fun cbMkAndroidCancelKeyStoreBtn(ctrlbtn, p)=
  let p -> [winstr ctrlbtn] in
  (
    dsEdWindow winstr;
    setEdCtrlButtonEnable ctrlbtn 1;
  );
  0;;


fun cbAndroidCreateKeyStoreOk(ctrlbtn, p)=
  let p -> [p1 winstr wfile ctrlbtn1 ctrlcn ctrlo ctrlcity ctrlcountry ctrlpass ctrlpass2] in
  let p1 -> [pwinstr fatherstr projname xmlpath script keystorepath ctrlexport ctrlarch ctrlkeystorepath ctrlkeystorepass ctrldeploy ctrlorient ctrlpkgname] in

  let _WtoP wfile -> pfile in
  let getAndroidShortName projname -> shortname in
  let getEdCtrlTextLineValue ctrlpass -> pass in
  let getEdCtrlTextLineValue ctrlpass2 -> pass2 in
  let getEdCtrlTextLineValue ctrlcn -> author in
  let getEdCtrlTextLineValue ctrlo -> compagny in
  let getEdCtrlTextLineValue ctrlcountry -> country in
  let getEdCtrlTextLineValue ctrlcity -> city in
  
  if (!strcmp pass pass2) && (strcmp strtrim pass "") && (strcmp strtrim country "") then
  (
    let makeAndroidSigninKey wfile shortname pass ["CN" author]::["O" compagny]::["C" country]::["L" city]::nil -> [keystore output] in
    if (keystore != nil) then
    (
      dsEdWindow winstr;
      let _GetFileNameFromP pfile -> fname in
        setEdCtrlTextLineValue ctrlkeystorepath fname;
      
      setEdCtrlTextLineValue ctrlkeystorepass pass;
      setEdCtrlButtonEnable ctrlbtn1 1;
      setProjectSetting "keystorepath" _PtoScol pfile;
      mutate p1 <- [_ _ _ _ _ pfile _ _ _ _ _ _ _];
      setEdWindowFocus pwinstr;
      0;
    )
    else
    (
      // error
      _DLGMessageBox _channel fatherstr.EDW_win (loc "OS3D_0155") strcatn (loc "OS3D_0563")::"\n\n"::output::nil 0;
      0;
    );
  )
  else
  (
    //error password or country empty
    _DLGMessageBox _channel fatherstr.EDW_win (loc "OS3D_0155") (loc "OS3D_0564") 0;
    0;
  );
  0;;


fun cbDlgAndroidSetKeyStorePath(dlg, p, wfile)=
  let p -> [ctrlbtn p1] in
  let p1 -> [pwinstr fatherstr projname xmlpath script keystorepath ctrlexport ctrlarch ctrlkeystorepath ctrlkeystorepass ctrldeploy ctrlorient ctrlpkgname] in
  (
    if wfile == nil then
    (
      setEdCtrlButtonEnable ctrlbtn 1;
      0;
    )
    else
    (
      let _WtoP wfile -> pfile in
      if ((_PtoScol pfile) == nil) then
      (
        setEdCtrlButtonEnable ctrlbtn 1;
        0;
      )
      else
      (
        let getFileExt _PtoScol pfile -> ext in
        if (!strcmpi ext "keystore") then nil else
          set wfile = _getmodifypack strcat _PtoScol pfile ".keystore";
        0;
      );
       
      let _GETscreenSize -> [sw sh] in
      let [430 205] -> [iw ih] in
      let 10 -> ypos in
      (
        let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0562") -> winstr in
        let crEdCtrlLabel winstr 10 ypos + 2 200 20 (loc "OS3D_0565") nil -> labelcn in
        let crEdCtrlTextLine winstr 220 ypos (iw - 230) 20 getProjectSetting "authorName" nil EDWIN_RESIZE_MW -> ctrlcn in
        let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 200 20 (loc "OS3D_0566") nil -> labelo in
        let crEdCtrlTextLine winstr 220 ypos (iw - 230) 20 getProjectSetting "authorCompany" nil EDWIN_RESIZE_MW -> ctrlo in
        let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 200 20 (loc "OS3D_0567") nil -> labelcity in
        let crEdCtrlTextLine winstr 220 ypos (iw - 230) 20 "" nil EDWIN_RESIZE_MW -> ctrlcity in
        let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 200 20 (loc "OS3D_0568") nil -> labelcountry in
        let crEdCtrlTextLine winstr 220 ypos (iw - 230) 20 "" nil EDWIN_RESIZE_MW -> ctrlcountry in
        let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 200 20 (loc "OS3D_0569") nil -> labelpass in
        let crEdCtrlTextLine winstr 220 ypos (iw - 230) 20 "" ET_BORDER|ET_AHSCROLL|ET_TABFOCUS|ET_PASSWORD EDWIN_RESIZE_MW -> ctrlpass in
        let crEdCtrlLabel winstr 10 (set ypos = ypos + 25) + 2 200 20 (loc "OS3D_0570") nil -> labelpass2 in
        let crEdCtrlTextLine winstr 220 ypos (iw - 230) 20 "" ET_BORDER|ET_AHSCROLL|ET_TABFOCUS|ET_PASSWORD EDWIN_RESIZE_MW -> ctrlpass2 in
        
        let crEdCtrlButton winstr 10 (ih - 30) 90 20 (loc "OS3D_0536") EDWIN_RESIZE_MW -> ctrlok in
        let crEdCtrlButton winstr (iw - 100) (ih - 30) 90 20 (loc "OS3D_0513") EDWIN_RESIZE_MW -> ctrlcancel in
        (
          setEdCtrlButtonCb ctrlok mkfun2 @cbAndroidCreateKeyStoreOk [p1 winstr wfile ctrlbtn ctrlcn ctrlo ctrlcity ctrlcountry ctrlpass ctrlpass2];
          setEdCtrlButtonCb ctrlcancel mkfun2 @cbMkAndroidCancelKeyStoreBtn [winstr ctrlbtn];
        );        
      );
      0;
    );
  );
  0;;


fun cbBtnAndroidCreateKeyStore(ctrlbtn, p)=
  let p -> [winstr _ _ xmlpath _ _ _ _ _ _ _ _ _] in
  (
    setEdCtrlButtonEnable ctrlbtn 0;
    let getFileDirectory xmlpath -> dir in
      _DLGrflsave _DLGSaveFile _channel winstr.EDW_win dir nil "Key Store (*.keystore)\0*.keystore\0All\0*.*\0\0" @cbDlgAndroidSetKeyStorePath [ctrlbtn p];
  );
  0;;


fun cbAndroidProjMode(ctrlstr, pos, value, p)=
  let p -> [labelarch ctrlarch labelkeystore pickkeystorebtn newkeystorebtn labelpass ctrlkeystorepass ctrldeploy] in
  (
    if (pos != 0) then nil else
      setEdCtrlCheckState ctrldeploy 0;
    
    setEdCtrlLabelEnable labelarch (pos == 0);
    setEdCtrlSelectEnable ctrlarch (pos == 0);

    setEdCtrlLabelEnable labelkeystore !(pos == 2);
    setEdCtrlButtonEnable pickkeystorebtn !(pos == 2);
    setEdCtrlButtonEnable newkeystorebtn !(pos == 2);

    setEdCtrlLabelEnable labelpass !(pos == 2);
    setEdCtrlTextLineEnable ctrlkeystorepass !(pos == 2);

    setEdCtrlCheckEnable ctrldeploy (pos == 0);
  );
  0;;

  
fun mkAndroidApp(fatherstr, projname, xmlpath, script)=
  _refreshExe;
  let _GETscreenSize -> [sw sh] in
  let [430 220] -> [iw ih] in
  let 10 -> ipos in
  let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
  
  let getAndroidShortName projname -> shortname in
  let getProjectSettingDef "appPkgName" if ((getProjectSetting "authorCompany") != nil) then strcatn "com."::(getAndroidShortName (getProjectSetting "authorCompany"))::"."::shortname::nil else strcat "os3d.app." shortname -> pkgname in
  let crEdCtrlLabel winstr 10 (ipos + 2) 160 20 (loc "OS3D_0585") nil -> labelpkg in
  let crEdCtrlTextLine winstr 180 ipos (iw - 190) 20 pkgname nil EDWIN_RESIZE_MW -> ctrlpkgname in
  let crEdCtrlLabel winstr 10 ((set ipos = ipos + 25) + 2) 160 20 (loc "OS3D_0582") nil -> labelorient in
  let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 EDWIN_RESIZE_MW -> ctrlorient in
  let crEdCtrlLabel winstr 10 ((set ipos = ipos + 25) + 2) 160 20 (loc "OS3D_0680") nil -> labelexport in
  let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 EDWIN_RESIZE_MW -> ctrlexport in
  let crEdCtrlLabel winstr 10 ((set ipos = ipos + 25) + 2) 160 20 (loc "OS3D_0575") nil -> labelarch in
  let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 EDWIN_RESIZE_MW -> ctrlarch in 
  let crEdCtrlLabel winstr 10 ((set ipos = ipos + 25) + 2) 160 20 (loc "OS3D_0558") nil -> labelkeystore in
  let crEdCtrlTextLine winstr 180 ipos (iw - 270) 20 nil nil EDWIN_RESIZE_MW -> ctrlkeystorepath in
  let crEdCtrlButton winstr (iw - 85) ipos 35 20 "..." nil -> pickkeystorebtn in
  let crEdCtrlButton winstr (iw - 45) ipos 35 20 "+" nil -> newkeystorebtn in
  let crEdCtrlLabel winstr 10 ((set ipos = ipos + 25) + 2) 160 20 (loc "OS3D_0559") nil -> labelpass in
  let crEdCtrlTextLine winstr 180 ipos (iw - 190) 20 nil ET_BORDER|ET_AHSCROLL|ET_TABFOCUS|ET_PASSWORD EDWIN_RESIZE_MW -> ctrlkeystorepass in
  let crEdCtrlCheck winstr 10 (set ipos = ipos + 25) (iw - 35) 20 (loc "OS3D_0561") EDWIN_RESIZE_MW -> ctrldeploy in

  let crEdCtrlButton winstr 10 (ih - 30) 90 20 (loc "OS3D_0536") EDWIN_RESIZE_MW -> ctrlok in
  let crEdCtrlButton winstr (iw - 100) (ih - 30) 90 20 (loc "OS3D_0513") EDWIN_RESIZE_MW -> ctrlcancel in
  let [winstr fatherstr projname xmlpath script (_checkpack getProjectSetting "keystorepath") ctrlexport ctrlarch ctrlkeystorepath ctrlkeystorepass ctrldeploy ctrlorient ctrlpkgname] -> p in
  (
    set winMkApplet = winstr;
    
    fillEdCtrlSelect ctrlorient (loc "OS3D_0583")::(loc "OS3D_0584")::(loc "OS3D_0633")::(loc "OS3D_0634")::nil;
    
    fillEdCtrlSelect ctrlexport (loc "OS3D_0681")::(loc "OS3D_0682")::(loc "OS3D_0683")::nil;
    
    setEdCtrlSelectCb ctrlexport mkfun4 @cbAndroidProjMode [labelarch ctrlarch labelkeystore pickkeystorebtn newkeystorebtn labelpass ctrlkeystorepass ctrldeploy];
    let atoi (getProjectSettingDef "appAndroidType" "0") -> typeselect in
    (
      selectEdCtrlSelectByPos ctrlexport typeselect;
      cbAndroidProjMode nil typeselect nil [labelarch ctrlarch labelkeystore pickkeystorebtn newkeystorebtn labelpass ctrlkeystorepass ctrldeploy];
    );
    
    fillEdCtrlSelect ctrlarch "default"::"all"::"armeabi-v7a"::"x86"::"arm64-v8a"::"x86_64"::nil;
    let getProjectSettingDef "appAndroidArch" "0" -> archselect in
      selectEdCtrlSelectByPos ctrlarch (atoi archselect);
    
    let getProjectSettingDef "appOrientation" "landscape" -> orientselect in
    let if (!strcmpi orientselect "landscape") then
          0
        else if (!strcmpi orientselect "portrait") then
          1
        else if (!strcmpi orientselect "reverseLandscape") then
          2
        else
          3
    -> opos in
      selectEdCtrlSelectByPos ctrlorient opos;
    
    setEdCtrlTextLineEnable ctrlkeystorepath 0;
    setEdCtrlTextLineValue ctrlkeystorepath (let getPathFile getProjectSetting "keystorepath" nil -> [_ filename] in filename);
    setEdCtrlTextLineCbValidate ctrlkeystorepass mkfun3 @cbMkAndroidValidate p;
    
    setEdCtrlButtonCb pickkeystorebtn mkfun2 @cbBtnAndroidPickKeyStorePath p;
    setEdCtrlButtonCb newkeystorebtn mkfun2 @cbBtnAndroidCreateKeyStore p;
    
    setEdCtrlButtonCb ctrlok mkfun2 @cbMkAndroidOk p;
    setEdCtrlButtonCb ctrlcancel mkfun2 @cbMkAndroidCancelBtn winstr;
  );
  0;;


///// LOCAL WEB APP
fun mkAppletCpLocalWebfiles(l, path)=
  if l == nil then nil else
  (
    let getPathFile (hd l) "" -> [_ filename] in
    if !strcmpi "index.html" filename then nil else
      copyFileContent (hd l) (strcatn path::filename::nil);
    mkAppletCpLocalWebfiles (tl l) path;
  );
  0;;


fun mkAppletLocalWeb(exportdir, projname, xmlpath, pakpath)=
  let _listoffiles strcat APPBASEDIR sMkAppletPath -> lwebfiles in
  let _checkpack (getProjectSetting "splashpath") -> psplash in
  let if (psplash == nil) then lwebfiles else (getProjectSetting "splashpath")::lwebfiles -> lwebfiles in
  
  let XMLload xmlpath -> xmlscenestr in
  let XMLgetMarkByValue xmlscenestr "environment" -> envmark in
  let XMLgetMarkByValueFromMarkSons envmark "colourBackground" -> backstr in
  let make_rgb (ftoi ((atof XMLgetParam backstr "b") *. 255.0)) (ftoi ((atof XMLgetParam backstr "g") *. 255.0)) (ftoi ((atof XMLgetParam backstr "r") *. 255.0)) -> bgcolor in
  (
    mkAppletCpLocalWebfiles lwebfiles exportdir;
    let strreplace (strreplace pakpath " " "+") "/" "%2F" -> pakpath in
    let strcatn "%5fload+%22"::(strreplace (strreplace exportdir " " "+") "/" "%2F")::"os3dplayer%2Fos3dload%2Epkg%22%0amain+%22"::pakpath::"%22+%22"::(strreplace projname " " "+")::"%22+%22"::(getProjectSettingDef "defaultWidth" "1280")::"%22+%22"::(getProjectSettingDef "defaultHeight" "720")::"%22+0"::nil -> appurl in
    let getVoyagerVersionS -> svoyver in
    let _getpack _checkpack strcatn APPBASEDIR::sMkAppletPath::"index.html"::nil -> html in
    (
      if (psplash == nil) then
      (
        set html = strreplace html "$BGSPLASH" "";
      )
      else
      (
        let getPathFile (_PtoScol psplash) "" -> [_ splashimg] in
        set html = strreplace html "$BGSPLASH" strcatn "style=\"background-image:url('"::splashimg::"'); background-repeat:no-repeat; background-position:center;\""::nil;
      );
      
      set html = strreplace html "$TITLE" projname;
      set html = strreplace html "$BGCOLOR" (if bgcolor == 0 then "000000" else (itoh bgcolor));
      set html = strreplace html "$SCOL_SITE_URL_OLD" appurl;
      set html = strreplace html "$SCOL_SITE_URL" appurl;
      set html = strreplace html "$WIN_32_PLUGIN_URL" "http://www.scolring.org/rsc/scol_plugin.exe";
      set html = strreplace html "$MINIMUMSCOLVERSION" svoyver;
      set html = strreplace html "$WEBINTEGRATED" (itoa 2);
      set html = strreplace html "$WIDTH" (getProjectSettingDef "defaultWidth" "1280");
      set html = strreplace html "$HEIGHT" (getProjectSettingDef "defaultHeight" "720");
      _storepack html strcatn exportdir::"index.html"::nil;
    );
    
    XMLclose xmlscenestr;
    
    let sizelist lwebfiles -> size in
    let nil -> ndata in
    let 0 -> i in
    (
      while i < size do
      (
        let nth_list lwebfiles i -> elem in
        let getPathFile elem "" -> [_ wname] in
          set ndata = (strcatn exportdir::wname::nil)::ndata;
          
        set i = i + 1;
      );
      (strcat exportdir "index.html")::ndata;
    );
  );;


fun cbWebPakTrm(trm, wp)=
  let wp -> [tctrl l wfile cbComplete] in
  (
    _deltimer trm;
    _freememory;
    
    //manage cancel
    if (winMkApplet == nil) then nil else
      mkWebPakAll tctrl l wfile cbComplete;
  );
  0;;


fun mkWebPakAll(tctrl, l, wfile, cbComplete)=
  if (l == nil) then
  (
    exec cbComplete with [];
    0;
  )
  else
  (
    let l->[name nxt] in
    let getFileContent name -> content in
  	(
  	  let zip content -> ziped in
  	  let if (!strcmpi (substr name 0 (strlen APPBASEDIR)) APPBASEDIR) then strcat "APPBASEDIR" (substr name ((strlen APPBASEDIR) - 1) (strlen name)) else name -> mname in
  	    _appendpack strcatn "#******#"::mname::"|"::(_getlongname content "" "#")::"|"::(itoa (strlen ziped))::"|"::ziped::nil wfile;
  	  
  	  _freememory;
  	  
  	  setEdCtrlLabelValue tctrl strcatn "Pack "::name::nil;
      
  	  // use a timer to allow the garbage collector to free some memory in the loop
  	  _rfltimer _starttimer _channel 5 @cbWebPakTrm [tctrl nxt wfile cbComplete];
  	  0;
    );
  );
  0;;


fun cpLocalWebFiles(exportdir, l)=
  if (l == nil) then nil else
  (
    let hd l -> file in
    let if (!strcmpi (substr file 0 (strlen APPBASEDIR)) APPBASEDIR) then (substr file ((strlen APPBASEDIR) - 1) (strlen file)) else file -> nfile in
      copyFileContent file strcat exportdir nfile;
    
    cpLocalWebFiles exportdir tl l;
    0;
  );;


fun cbWebPakComplete(p)=
  let p -> [exportdir lfiles xmlpath projname pakpath ctrldone labelport] in
  (
    mkAppletLocalWeb exportdir projname xmlpath pakpath;
    cpLocalWebFiles exportdir lfiles;
    setEdCtrlLabelValue labelport strcatn (loc "OS3D_0520")::exportdir::(loc "OS3D_0548")::nil;
    setEdCtrlButtonEnable ctrldone 1;
  );
  0;;


fun copyFilesToExportWebDirectory(exportdir, lfiles, resfiles, xmlpath, projname, ctrldone, labelport)=
  let getFileNameWithoutExt xmlpath -> fname in
  let strcatn exportdir::fname::".pak"::nil -> pakpath in
  let strcatn (mkDTime time)::"\n"::xmlpath::"\n"::nil -> ncontent in
  (
    _storepack ncontent pakpath;
    mkWebPakAll labelport resfiles (_getmodifypack pakpath) mkfun1 @cbWebPakComplete [exportdir lfiles xmlpath projname pakpath ctrldone labelport];
  );
  0;;
  

fun cbMkStandAloneWebCancelBtn(ctrlbtn, winstr)=
  dsEdWindow winstr;
  set winMkApplet = nil;
  0;;


fun mkStandAloneWeb(fatherstr, projname, xmlpath, script)=
  let _GETscreenSize -> [sw sh] in
  let [430 120] -> [iw ih] in
  let getDirectoryWithoutLastSlash (getFileDirectory xmlpath) -> projdir in
  let if (projdir == nil) || (!strcmp projdir "") then (strcatn sExportDirectory::"/"::projname::"/"::nil) else (strcatn projdir::"/"::sExportDirectory::"/"::projname::"/"::nil) -> exportdir in
  (
    let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0521") -> winstr in
    let crEdCtrlLabelEx winstr 10 12 iw-20 50 (loc "OS3D_0524") ET_ALIGN_CENTER nil -> labelport in
    let crEdCtrlButton winstr ((iw /2) - 110) (ih - 30) 90 20 (loc "OS3D_0518") EDWIN_RESIZE_MW -> ctrldone in
    let crEdCtrlButton winstr ((iw /2) + 20) (ih - 30) 90 20 (loc "OS3D_0513") EDWIN_RESIZE_MW -> ctrlcancel in
    (
      set winMkApplet = winstr;
      setEdCtrlButtonEnable ctrldone 0;
      let mkAppletListOS3DFiles xmlpath -> lfiles in
      let getMkAppletXmlResources xmlpath nil -> [resfiles _] in
      (
        cleanDirectory exportdir;
        copyFilesToExportWebDirectory exportdir lfiles resfiles xmlpath projname ctrldone labelport;
      );
      
      setEdCtrlButtonCb ctrldone mkfun2 @cbMkStandAloneDoneBtn [winstr exportdir "" xmlpath projname];
      setEdCtrlButtonCb ctrlcancel mkfun2 @cbMkStandAloneWebCancelBtn winstr;
    );
  );
  0;;


fun getShortName(name)=
  let strToWordList strreplace (strreplace name "_" "-") " " "-" -> lw in
  let "" -> nname in
  (
    while (lw != nil) do
    (
      //no number after a dot!
      let hd lw -> word in
      if ((atoi (substr word 0 1)) == nil) then
        set nname = strcatn nname::"."::word::nil
      else
        set nname = strcat nname word;
      set lw = tl lw; 
    );
    //do strlowercase on the copied string, this modify the original string otherwise
    strlowercase nname;
  );;


//// Raspberry PI
fun cbDestroyRpiExportWin(winstr, pwinstr)=
  dsEdWindow2 pwinstr;
  0;;


fun cbMkRpiDoneBtn(ctrlbtn, p)=
  let p -> [winstr exportdir xmlpath projname foldername] in
  (
    dsEdWindow winstr;
    set winMkApplet = nil;
    let getShortName projname -> shortname in
    let strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\RaspberryPi"::foldername::"\\"::shortname::nil -> fullpath in
    (
      addLogMessage fullpath;
      _startExe "launch" "openExplorer" strcatn "\""::fullpath::"\""::nil;
    );
  );
  0;;


fun copyRpiFilesToExportDirectory(dir, lfiles, ldeps, xmlpath, fname, archconf)=
  let getShortName fname -> shortname in
  (
    //copy scol base
    let getFilesFromDirRecursive "btdata" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    let getFilesFromDirRecursive "ogre_redist" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    copyFileContent "logo.bmp" strcatn dir::"/partition/"::"logo.bmp"::nil;
    
    //make usm.ini
    makeUsmIni dir "linux" "OpenGL" "2" "" "" ldeps ("backgroundTask"::"no"::nil)::("splash"::(strcat APPBASEDIR "os3dplayer/splash.png")::nil)::nil;
    
    copyFileContent (strcat "scol." archconf) strcatn dir::"/"::shortname::nil;
    
    while lfiles != nil do
    (
      let hd lfiles -> file in
        copyFileContent file strcatn dir::"/partition/"::file::nil;
      
      set lfiles = tl lfiles;
    );
    
    let getProjectSetting "splashpath" -> psplash in
    if ((_checkpack psplash) == nil) then nil else
      copyFileContent psplash strcatn dir::"/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    
    //make script
    let _getpack _checkpack "README.txt.in" -> preadme in
    (
      set preadme = strreplace preadme "@APP_NAME@" shortname;
      set preadme = strreplace preadme "@APP_DIR@" shortname;
      set preadme = strreplace preadme "@APP_DISPLAY_NAME@" fname;
      set preadme = strreplace preadme "@APP_VERSION@" getProjectVersion;    
      set preadme = strreplace preadme "@APP_AUTHOR@" (getProjectSettingDef "authorName" "Undefined");
      set preadme = strreplace preadme "@APP_URL@" (getProjectSettingDef "projectWebsite" "http://www.openspace3d.com");
      set preadme = strreplace preadme "@APP_DESCRIPTION@" (getProjectSettingDef "projectDescription" fname);
      
      let _getpack _checkpack "make_package.sh.in" -> pscript in
      (
        set pscript = strreplace pscript "@APP_NAME@" shortname;
        set pscript = strreplace pscript "@APP_DIR@" shortname;
        set pscript = strreplace pscript "@APP_DISPLAY_NAME@" shortname;
        set pscript = strreplace pscript "@APP_VERSION@" getProjectVersion;    
        set pscript = strreplace pscript "@APP_AUTHOR@" (getProjectSettingDef "authorName" "Undefined");
        set pscript = strreplace pscript "@APP_URL@" (getProjectSettingDef "projectWebsite" "http://www.openspace3d.com");
        set pscript = strreplace pscript "@APP_DESCRIPTION@" oneLineTransform (addSlashes (getProjectSettingDef "projectDescription" fname)) " ";
        set pscript = strreplace pscript "@APP_README@" addSlashes preadme;
        
        _storepack pscript strcatn dir::"/make_package.sh"::nil;
      );
      
      _storepack2 preadme strcatn dir::"/README.txt"::nil;
    );
    
    //make master.pkg
    let ("typeof"::"env_ref=Env;;"::nil)::
        ("defcom"::"Smain=main"::"S"::"S"::"S"::"S"::"I;;"::nil)::
        ("fun"::"multiress(res)="::nil)::
        ("if"::"res==nil"::"then"::nil)::
        ("0"::nil)::
        ("else"::nil)::
        ("let"::"res"::"->"::"[l"::"nxt]"::"in"::nil)::
        ("("::nil)::
        ("_setress"::"hd"::"l"::"hd"::"tl"::"l;"::nil)::
        ("multiress"::"nxt;"::nil)::
        (");;"::nil)::
        
        ("fun"::"main(p)="::nil)::
        ("set"::"env_ref=_envchannel"::"_channel;"::nil)::
        ("multiress"::"strextr"::"_loadressini;"::nil)::  
        ("srand"::"time;"::nil)::
        ("_load"::(strcatn "\""::APPBASEDIR::"os3dplayer/os3dload.pkg\";"::nil)::nil)::
        ("_script"::"mkscript"::"Smain"::(strcatn "[\""::xmlpath::"\""::nil)::(strcatn "\""::fname::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultWidth" "1280")::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultHeight" "720")::"\""::nil)::"0];"::nil)::
        ("0;;"::nil)::nil
    -> pmaster in
    _storepack (strbuild pmaster) strcatn dir::"/partition/locked/master.pkg"::nil;
  );
  0;;


fun cbMkRpiCancelBtn(ctrlbtn, winstr)=
  dsEdWindow winstr;
  0;;


fun cbMkRpiOk(ctrlbtn, p)=
  let p -> [pwinstr fatherstr projname xmlpath script ctrlarch] in
  let _GETscreenSize -> [sw sh] in
  let [430 120] -> [iw ih] in
  let getDirectoryWithoutLastSlash (getFileDirectory xmlpath) -> projdir in
  let getShortName projname -> shortname in
  let getSelectedEdCtrlSelectPos ctrlarch -> arch in
  let if (arch == 0) then "armv7" else "armv6" -> archname in
  let if (arch == 0) then "_2_3" else "_1_zero" -> foldername in
  let if (projdir == nil) || (!strcmp projdir "") then (strcatn sExportDirectory::"/RaspberryPi"::foldername::"/"::shortname::nil) else (strcatn projdir::"/"::sExportDirectory::"/RaspberryPi"::foldername::"/"::shortname::nil) -> exportdir in
  (
    setProjectSetting "appRpiArch" itoa (getSelectedEdCtrlSelectPos ctrlarch);
     
    let crEdModalDialogWindow _channel pwinstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
    let crEdCtrlLabelEx winstr 10 12 iw-20 50 (loc "OS3D_0524") ET_ALIGN_CENTER nil -> labelport in
    let crEdCtrlButton winstr ((iw /2) - 45) (ih - 30) 90 20 (loc "OS3D_0518") EDWIN_RESIZE_MW -> ctrldone in
    (
      set winMkApplet = winstr;
      
      setEdCtrlButtonEnable ctrldone 0;
      _addPartition "./RaspberryPi" 2;
      let mkStandAloneListFiles xmlpath -> [lfiles ldeps] in
      (
        cleanDirectory exportdir;
        copyRpiFilesToExportDirectory exportdir lfiles ldeps xmlpath projname archname;
        
        setEdCtrlButtonCb ctrldone mkfun2 @cbMkRpiDoneBtn [winstr exportdir xmlpath projname foldername];
        setEdwindowCbDestroy winstr mkfun2 @cbDestroyRpiExportWin pwinstr;

        setEdWindowFocus winstr;        
      );
      
      _removeLastPartition;
      setEdCtrlLabelValue labelport strcatn (loc "OS3D_0520")::exportdir::(loc "OS3D_0548")::nil;
      setEdCtrlButtonEnable ctrldone 1;
    );
  );
  0;;


fun mkRpiApp(fatherstr, projname, xmlpath, script)=
  _refreshExe;
  let _GETscreenSize -> [sw sh] in
  let [430 90] -> [iw ih] in
  let 10 -> ipos in
  let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
  let crEdCtrlLabel winstr 10 (ipos + 2) 160 20 (loc "OS3D_0575") nil -> labelarch in
  let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 EDWIN_RESIZE_MW -> ctrlarch in
  
  let crEdCtrlButton winstr 10 (ih - 30) 90 20 (loc "OS3D_0536") EDWIN_RESIZE_MW -> ctrlok in
  let crEdCtrlButton winstr (iw - 100) (ih - 30) 90 20 (loc "OS3D_0513") EDWIN_RESIZE_MW -> ctrlcancel in
  let [winstr fatherstr projname xmlpath script ctrlarch] -> p in
  (
    set winMkApplet = winstr;
    
    fillEdCtrlSelect ctrlarch "Raspberry pi 2/3 (armv7)"::"Raspberry pi 1/Zero (armv6)"::nil;
    let getProjectSettingDef "appRpiArch" "0" -> archselect in
      selectEdCtrlSelectByPos ctrlarch (atoi archselect);

    setEdCtrlButtonCb ctrlok mkfun2 @cbMkRpiOk p;
    setEdCtrlButtonCb ctrlcancel mkfun2 @cbMkRpiCancelBtn winstr;
  );
  0;;
  
  
//// Linux
fun cbDestroyLinuxExportWin(winstr, pwinstr)=
  dsEdWindow2 pwinstr;
  0;;


fun cbMkLinuxDoneBtn(ctrlbtn, p)=
  let p -> [winstr exportdir xmlpath projname archname] in
  (
    dsEdWindow winstr;
    set winMkApplet = nil;
    let getShortName projname -> shortname in
    let strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\Linux"::archname::"\\"::shortname::nil -> fullpath in
    (
      addLogMessage fullpath;
      _startExe "launch" "openExplorer" strcatn "\""::fullpath::"\""::nil;
    );
  );
  0;;


fun copyLinuxFilesToExportDirectory(dir, lfiles, ldeps, xmlpath, fname, archname)=
  let if !strcmp archname "32" then "i386" else "amd64" -> archconf in
  let getShortName fname -> shortname in
  let "" -> iconfile in
  (
    //copy scole base
    let getFilesFromDirRecursive "btdata" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    let getFilesFromDirRecursive "ogre_redist" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContent file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    copyFileContent "logo.bmp" strcatn dir::"/partition/"::"logo.bmp"::nil;
    
    copyFileContentC (strcatn "libCg"::archname::".so"::nil) strcatn dir::"/libCg.so"::nil;
    copyFileContentC (strcatn "libCgGL"::archname::".so"::nil) strcatn dir::"/libCgGL.so"::nil;
    
    //make usm.ini
    makeUsmIni dir "linux" "OpenGL" "2" "" "" ldeps ("backgroundTask"::"no"::nil)::("splash"::(strcat APPBASEDIR "os3dplayer/splash.png")::nil)::nil;
    
    copyFileContent (strcat "scol." archconf) strcatn dir::"/"::shortname::nil;
    
    let getProjectSetting "iconpath" -> iconpath in
    let getFileExt getProjectSetting "iconpath" -> ext in
    let nil -> icon_src in
    if ((strcmpi ext "ico") && (set icon_src = G2DloadAlphaBmp _channel iconpath) != nil) then
    (
      let _CRbitmap _channel 128 128 -> bmp in
      let _CRbitmap8 _channel 128 128 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp icon_src 2 -> icon in
      (
        set iconfile = strcatn shortname::".png"::nil;
        _BTSAVEalphaBitmap icon _getmodifypack strcatn dir::"/"::iconfile::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );      
      0;
    )
    else
    (
      if ((_checkpack iconpath) == nil) then nil else
      (
        set iconfile = strcatn shortname::"."::ext::nil;
          copyFileContent iconpath strcatn dir::"/"::iconfile::nil;
      );
      0;
    );

    while lfiles != nil do
    (
      let hd lfiles -> file in
        copyFileContent file strcatn dir::"/partition/"::file::nil;
      
      set lfiles = tl lfiles;
    );
    
    let (getProjectSetting "splashpath") -> psplash in
    if ((_checkpack psplash) == nil) then nil else
      copyFileContent psplash strcatn dir::"/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    
    //make script
    let _getpack _checkpack "README.txt.in" -> preadme in
    (
      set preadme = strreplace preadme "@APP_NAME@" shortname;
      set preadme = strreplace preadme "@APP_DIR@" shortname;
      set preadme = strreplace preadme "@APP_DISPLAY_NAME@" fname;
      set preadme = strreplace preadme "@APP_VERSION@" getProjectVersion;    
      set preadme = strreplace preadme "@APP_AUTHOR@" (getProjectSettingDef "authorName" "Undefined");
      set preadme = strreplace preadme "@APP_URL@" (getProjectSettingDef "projectWebsite" "http://www.openspace3d.com");
      set preadme = strreplace preadme "@APP_DESCRIPTION@" (getProjectSettingDef "projectDescription" fname);
      
      let _getpack _checkpack "make_package.sh.in" -> pscript in
      (
        set pscript = strreplace pscript "@APP_NAME@" shortname;
        set pscript = strreplace pscript "@APP_DIR@" shortname;
        set pscript = strreplace pscript "@APP_DISPLAY_NAME@" shortname;
        set pscript = strreplace pscript "@APP_VERSION@" getProjectVersion;    
        set pscript = strreplace pscript "@APP_AUTHOR@" (getProjectSettingDef "authorName" "Undefined");
        set pscript = strreplace pscript "@APP_URL@" (getProjectSettingDef "projectWebsite" "http://www.openspace3d.com");
        set pscript = strreplace pscript "@APP_DESCRIPTION@" oneLineTransform (addSlashes (getProjectSettingDef "projectDescription" fname)) " ";
        set pscript = strreplace pscript "@APP_README@" addSlashes preadme;
        set pscript = strreplace pscript "@APP_ICON@" iconfile;
        set pscript = strreplace pscript "@APP_ARCH@" archconf;
        
        _storepack pscript strcatn dir::"/make_package.sh"::nil;
      );
      
      _storepack2 preadme strcatn dir::"/README.txt"::nil;
    );
    
    //make master.pkg
    let ("typeof"::"env_ref=Env;;"::nil)::
        ("defcom"::"Smain=main"::"S"::"S"::"S"::"S"::"I;;"::nil)::
        ("fun"::"multiress(res)="::nil)::
        ("if"::"res==nil"::"then"::nil)::
        ("0"::nil)::
        ("else"::nil)::
        ("let"::"res"::"->"::"[l"::"nxt]"::"in"::nil)::
        ("("::nil)::
        ("_setress"::"hd"::"l"::"hd"::"tl"::"l;"::nil)::
        ("multiress"::"nxt;"::nil)::
        (");;"::nil)::
        
        ("fun"::"main(p)="::nil)::
        ("set"::"env_ref=_envchannel"::"_channel;"::nil)::
        ("multiress"::"strextr"::"_loadressini;"::nil)::  
        ("srand"::"time;"::nil)::
        ("_load"::(strcatn "\""::APPBASEDIR::"os3dplayer/os3dload.pkg\";"::nil)::nil)::
        ("_script"::"mkscript"::"Smain"::(strcatn "[\""::xmlpath::"\""::nil)::(strcatn "\""::fname::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultWidth" "1280")::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultHeight" "720")::"\""::nil)::"0];"::nil)::
        ("0;;"::nil)::nil
    -> pmaster in
    _storepack (strbuild pmaster) strcatn dir::"/partition/locked/master.pkg"::nil;
  );
  0;;


fun cbMkLinuxCancelBtn(ctrlbtn, winstr)=
  dsEdWindow winstr;
  0;;


fun cbMkLinuxOk(ctrlbtn, p)=
  let p -> [pwinstr fatherstr projname xmlpath script ctrlarch] in
  let _GETscreenSize -> [sw sh] in
  let [430 120] -> [iw ih] in
  let getSelectedEdCtrlSelectPos ctrlarch -> arch in
  let if (arch == 0) then "64" else "32" -> archname in
  let getDirectoryWithoutLastSlash (getFileDirectory xmlpath) -> projdir in
  let getShortName projname -> shortname in
  let if (projdir == nil) || (!strcmp projdir "") then (strcatn sExportDirectory::"/Linux"::archname::"/"::shortname::nil) else (strcatn projdir::"/"::sExportDirectory::"/Linux"::archname::"/"::shortname::nil) -> exportdir in
  (
    setProjectSetting "appLinuxArch" itoa (getSelectedEdCtrlSelectPos ctrlarch);
    
    let crEdModalDialogWindow _channel pwinstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
    let crEdCtrlLabelEx winstr 10 12 iw-20 50 (loc "OS3D_0524") ET_ALIGN_CENTER nil -> labelport in
    let crEdCtrlButton winstr ((iw /2) - 45) (ih - 30) 90 20 (loc "OS3D_0518") EDWIN_RESIZE_MW -> ctrldone in
    (
      set winMkApplet = winstr;
      
      setEdCtrlButtonEnable ctrldone 0;
      _addPartition "./Linux" 2;
      let mkStandAloneListFiles xmlpath -> [lfiles ldeps] in
      (
        cleanDirectory exportdir;
        copyLinuxFilesToExportDirectory exportdir lfiles ldeps xmlpath projname archname;
        
        setEdCtrlButtonCb ctrldone mkfun2 @cbMkLinuxDoneBtn [winstr exportdir xmlpath projname archname];
        setEdwindowCbDestroy winstr mkfun2 @cbDestroyLinuxExportWin pwinstr;
        
        setEdWindowFocus winstr;
      );
      
      _removeLastPartition;
      setEdCtrlLabelValue labelport strcatn (loc "OS3D_0520")::exportdir::(loc "OS3D_0548")::nil;
      setEdCtrlButtonEnable ctrldone 1;
    );
  );
  0;;


fun mkLinuxApp(fatherstr, projname, xmlpath, script)=
  _refreshExe;
  let _GETscreenSize -> [sw sh] in
  let [430 90] -> [iw ih] in
  let 10 -> ipos in
  let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
  let crEdCtrlLabel winstr 10 (ipos + 2) 160 20 (loc "OS3D_0575") nil -> labelarch in
  let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 EDWIN_RESIZE_MW -> ctrlarch in
  
  let crEdCtrlButton winstr 10 (ih - 30) 90 20 (loc "OS3D_0536") EDWIN_RESIZE_MW -> ctrlok in
  let crEdCtrlButton winstr (iw - 100) (ih - 30) 90 20 (loc "OS3D_0513") EDWIN_RESIZE_MW -> ctrlcancel in
  let [winstr fatherstr projname xmlpath script ctrlarch] -> p in
  (
    set winMkApplet = winstr;    
    
    fillEdCtrlSelect ctrlarch "Linux64 (x86-64|amd64)"::"Linux32 (i686)"::nil;
    let getProjectSettingDef "appLinuxArch" "0" -> archselect in
      selectEdCtrlSelectByPos ctrlarch (atoi archselect);

    setEdCtrlButtonCb ctrlok mkfun2 @cbMkLinuxOk p;
    setEdCtrlButtonCb ctrlcancel mkfun2 @cbMkLinuxCancelBtn winstr;
  );
  0;;
  
  
//// MacOS / OSX  
fun cbDestroyMacOsExportWin(winstr, pwinstr)=
  0;;


fun cbMkMacOsDoneBtn(ctrlbtn, p)=
  let p -> [winstr exportdir xmlpath projname] in
  (
    dsEdWindow winstr;
    set winMkApplet = nil;
    let getShortName projname -> shortname in
    let strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\MacOS"::"\\"::shortname::nil -> fullpath in
    (
      addLogMessage fullpath;
      _startExe "launch" "openExplorer" strcatn "\""::fullpath::"\""::nil;
    );
  );
  0;;


fun copyMacOsFilesToExportDirectory(dir, lfiles, ldeps, xmlpath, fname)=
  let getShortName fname -> shortname in
  (
    //copy scole base
    let getFilesFromDirRecursive2 "scol.app/Contents/MacOS" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContentC file strcatn dir::"/"::shortname::".app/Contents/MacOS/"::(substr file (strlen "scol.app/Contents/MacOS") (strlen file))::nil;
      
      set lbase = tl lbase;
    );
    
    copyFileContentC "scol.app/Contents/PkgInfo" strcatn dir::"/"::shortname::".app/Contents/PkgInfo"::nil;
    
    while lfiles != nil do
    (
      let hd lfiles -> file in
        copyFileContent file strcatn dir::"/"::shortname::".app/Contents/MacOS/partition/"::file::nil;
      
      set lfiles = tl lfiles;
    );
    
    copyFileContent "logo.bmp" strcatn dir::"/"::shortname::".app/Contents/MacOS/partition/"::"logo.bmp"::nil;
    
    let getProjectSetting "splashpath" -> psplash in
    if ((_checkpack psplash) == nil) then nil else
      copyFileContent psplash strcatn dir::"/"::shortname::".app/Contents/MacOS/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
    
    //make script
    let _getpack _checkpack "scol.app/Contents/info.plist.in" -> pinfoplist in
    (
      set pinfoplist = strreplace pinfoplist "@APP_NAME@" strtoutf8 shortname;
      set pinfoplist = strreplace pinfoplist "@APP_DIR@" strtoutf8 shortname;
      set pinfoplist = strreplace pinfoplist "@APP_DISPLAY_NAME@" strtoutf8 fname;
      set pinfoplist = strreplace pinfoplist "@APP_VERSION@" strtoutf8 getProjectVersion;    
      set pinfoplist = strreplace pinfoplist "@APP_AUTHOR@" strtoutf8 (getProjectSettingDef "authorName" "Undefined");
      set pinfoplist = strreplace pinfoplist "@APP_URL@" strtoutf8 (getProjectSettingDef "projectWebsite" "http://www.openspace3d.com");
      set pinfoplist = strreplace pinfoplist "@APP_DESCRIPTION@" strtoutf8 (getProjectSettingDef "projectDescription" fname);
      
      _storepack2 pinfoplist strcatn dir::"/"::shortname::".app/Contents/info.plist"::nil;
    );
    
    let _checkpack getProjectSetting "iconpath" -> iconpath in
    if (iconpath == nil) then
    (
      copyFileContentC "scol.app/Contents/Resources/icon.icns" strcatn dir::"/"::shortname::".app/Contents/Resources/"::shortname::".icns"::nil;
    )
    else
    (
      let G2DloadAlphaBmp _channel _PtoScol iconpath -> icon_src in
      (
        // XHDPI ICON 
        let _CRbitmap _channel 512 512 -> bmp in
        let _CRbitmap8 _channel 512 512 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_xhdpi in
        (
          _BTSAVEalphaBitmap icon_xhdpi _getmodifypack strcatn dir::"/"::shortname::".app/Contents/MacOS/"::shortname::".png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        _DSalphaBitmap icon_src;
      );
      
      let _getpack _checkpack "makeicon.sh.in" -> pmakeicon in
      (
        set pmakeicon = strreplace pmakeicon "@APP_NAME@" shortname;
        
        _storepack2 pmakeicon strcat dir "/makeicon.sh";
      );
      
      let _getpack _checkpack "README.txt.in" -> preadme in
      (
        set preadme = strreplace preadme "@APP_NAME@" shortname;
        set preadme = strreplace preadme "@APP_DIR@" shortname;
        set preadme = strreplace preadme "@APP_DISPLAY_NAME@" fname;
        set preadme = strreplace preadme "@APP_VERSION@" getProjectVersion;    
        set preadme = strreplace preadme "@APP_AUTHOR@" (getProjectSettingDef "authorName" "Undefined");
        set preadme = strreplace preadme "@APP_URL@" (getProjectSettingDef "projectWebsite" "http://www.openspace3d.com");
        set preadme = strreplace preadme "@APP_DESCRIPTION@" (getProjectSettingDef "projectDescription" fname);
        
        _storepack2 preadme strcatn dir::"/README.txt"::nil;
      );
    );
    
    //make usm.ini
    makeUsmIni strcatn dir::"/"::shortname::".app/Contents/MacOS/"::nil "macOS" "OpenGL" "2" "" "" ldeps ("backgroundTask"::"no"::nil)::("splash"::(strcat APPBASEDIR "os3dplayer/splash.png")::nil)::nil;
    
    //make master.pkg
    let ("typeof"::"env_ref=Env;;"::nil)::
        ("defcom"::"Smain=main"::"S"::"S"::"S"::"S"::"I;;"::nil)::
        ("fun"::"multiress(res)="::nil)::
        ("if"::"res==nil"::"then"::nil)::
        ("0"::nil)::
        ("else"::nil)::
        ("let"::"res"::"->"::"[l"::"nxt]"::"in"::nil)::
        ("("::nil)::
        ("_setress"::"hd"::"l"::"hd"::"tl"::"l;"::nil)::
        ("multiress"::"nxt;"::nil)::
        (");;"::nil)::
        
        ("fun"::"main(p)="::nil)::
        ("set"::"env_ref=_envchannel"::"_channel;"::nil)::
        ("multiress"::"strextr"::"_loadressini;"::nil)::  
        ("srand"::"time;"::nil)::
        ("_load"::(strcatn "\""::APPBASEDIR::"os3dplayer/os3dload.pkg\";"::nil)::nil)::
        ("_script"::"mkscript"::"Smain"::(strcatn "[\""::xmlpath::"\""::nil)::(strcatn "\""::fname::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultWidth" "1280")::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultHeight" "720")::"\""::nil)::"0];"::nil)::
        ("0;;"::nil)::nil
    -> pmaster in
    _storepack (strbuild pmaster) strcatn dir::"/"::shortname::".app/Contents/MacOS/"::"/partition/locked/master.pkg"::nil;
  );
  0;;


fun mkMacOsApp(fatherstr, projname, xmlpath, script)=
  _refreshExe;
  let _GETscreenSize -> [sw sh] in
  let [430 120] -> [iw ih] in
  let getDirectoryWithoutLastSlash (getFileDirectory xmlpath) -> projdir in
  let getShortName projname -> shortname in
  let if (projdir == nil) || (!strcmp projdir "") then (strcatn sExportDirectory::"/MacOS"::"/"::shortname::nil) else (strcatn projdir::"/"::sExportDirectory::"/MacOS"::"/"::shortname::nil) -> exportdir in
  (
    let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
    let crEdCtrlLabelEx winstr 10 12 iw-20 50 (loc "OS3D_0524") ET_ALIGN_CENTER nil -> labelport in
    let crEdCtrlButton winstr ((iw /2) - 45) (ih - 30) 90 20 (loc "OS3D_0518") EDWIN_RESIZE_MW -> ctrldone in
    (
      set winMkApplet = winstr;
      
      setEdCtrlButtonEnable ctrldone 0;
      _addPartition "./macos" 2;
      let mkStandAloneListFiles xmlpath -> [lfiles ldeps] in
      (
        cleanDirectory exportdir;
        copyMacOsFilesToExportDirectory exportdir lfiles ldeps xmlpath projname;
        
        setEdCtrlButtonCb ctrldone mkfun2 @cbMkMacOsDoneBtn [winstr exportdir xmlpath projname];
        setEdwindowCbDestroy winstr mkfun2 @cbDestroyMacOsExportWin fatherstr;

        setEdWindowFocus winstr;        
      );
      
      _removeLastPartition;
      setEdCtrlLabelValue labelport strcatn (loc "OS3D_0520")::exportdir::(loc "OS3D_0548")::nil;
      setEdCtrlButtonEnable ctrldone 1;
    );
  );
  0;;
  

//// IOS
fun copyIosFilesToExportDirectory(dir, lfiles, ldeps, xmlpath, fname)=
  let getAndroidShortName fname -> shortname in
  (
    //copy scol base
    let getFilesFromDirRecursive2 "scol/resources" -> lbase in
    while lbase != nil do
    (
      let hd lbase -> file in
        copyFileContentC file strcatn dir::"/"::file::nil;
      
      set lbase = tl lbase;
    );
    
    while lfiles != nil do
    (
      let hd lfiles -> file in
        copyFileContent file strcatn dir::"/scol/resources/partition/"::file::nil;
      
      set lfiles = tl lfiles;
    );
    
    //scol binary
    copyFileContentC "scol/scol" strcatn dir::"/scol/"::shortname::nil;
    copyFileContent "logo.bmp" strcatn dir::"/scol/resources/partition/"::"logo.bmp"::nil;
    
    let getProjectSetting "iconpath" -> iconpath in
    if ((_checkpack iconpath) == nil) then nil else
    (
      let G2DloadAlphaBmp _channel iconpath -> icon_src in
      (
        // 60 ICON
        let _CRbitmap _channel 60 60 -> bmp in
        let _CRbitmap8 _channel 60 60 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-60.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 120 ICON
        let _CRbitmap _channel 120 120 -> bmp in
        let _CRbitmap8 _channel 120 120 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-60@2x~iphone.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 180 ICON
        let _CRbitmap _channel 180 180 -> bmp in
        let _CRbitmap8 _channel 180 180 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-60@3x~iphone.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 76 ICON 
        let _CRbitmap _channel 76 76 -> bmp in
        let _CRbitmap8 _channel 76 76 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-76~ipad.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 152 ICON
        let _CRbitmap _channel 152 152 -> bmp in
        let _CRbitmap8 _channel 152 152 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-76@2x~ipad.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 167 ICON
        let _CRbitmap _channel 167 167 -> bmp in
        let _CRbitmap8 _channel 167 167 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-83.5@2x~ipad.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 40 ICON 
        let _CRbitmap _channel 40 40 -> bmp in
        let _CRbitmap8 _channel 40 40 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-Small-40.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 80 ICON 
        let _CRbitmap _channel 80 80 -> bmp in
        let _CRbitmap8 _channel 80 80 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-Small-40@2x.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 120 ICON 
        let _CRbitmap _channel 120 120 -> bmp in
        let _CRbitmap8 _channel 120 120 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-Small-40@3x.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 29 ICON 
        let _CRbitmap _channel 29 29 -> bmp in
        let _CRbitmap8 _channel 29 29 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-Small.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );        
        
        // 58 ICON 
        let _CRbitmap _channel 58 58 -> bmp in
        let _CRbitmap8 _channel 58 58 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-Small@2x.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        // 87 ICON 
        let _CRbitmap _channel 87 87 -> bmp in
        let _CRbitmap8 _channel 87 87 -> bmp8 in
        let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
        let _BTSCALEalphaBitmap abmp icon_src 2 -> icon_png in
        (
          _BTSAVEalphaBitmap icon_png _getmodifypack strcatn dir::"/scol/resources/Icon-Small@3x.png"::nil;
          _DSbitmap bmp;
          _DSbitmap8 bmp8;
          _DSalphaBitmap abmp;
        );
        
        _DSalphaBitmap icon_src;
      );
    );
    
    let _checkpack (getProjectSetting "splashpath") -> psplash in
    let if (psplash == nil) then
          //let if !strcmpi (getProjectSettingDef "appOrientation" "landscape") "landscape" then 0 else 1 -> vert in
          //if (!vert) then
            _checkpack (strcatn APPBASEDIR::"os3dplayer/splash.png"::nil)
          //else
          //  _checkpack (strcatn APPBASEDIR::"os3dplayer/splash_vert.png"::nil)
        else
          psplash
    -> splashpath in
    let G2DloadAlphaBmp _channel _PtoScol splashpath -> splash_src in
    (
      // 2436x1125 Splash
      let _CRbitmap _channel 2436 1125 -> bmp in
      let _CRbitmap8 _channel 2436 1125 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-812h-Landscape@3x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 2208x1242 Splash
      let _CRbitmap _channel 2208 1242 -> bmp in
      let _CRbitmap8 _channel 2208 1242 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-736h-Landscape@3x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 1334x750 Splash 
      let _CRbitmap _channel 1334 750 -> bmp in
      let _CRbitmap8 _channel 1334 750 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-667h-Landscape@2x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 1136x640 Splash 
      let _CRbitmap _channel 1136 640 -> bmp in
      let _CRbitmap8 _channel 1136 640 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-568h-Landscape@2x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 1024x768 Splash 
      let _CRbitmap _channel 1024 768 -> bmp in
      let _CRbitmap8 _channel 1024 768 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-Landscape~ipad.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 960x640 Splash 
      let _CRbitmap _channel 960 640 -> bmp in
      let _CRbitmap8 _channel 960 640 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-Landscape@2x.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 480x320 Splash 
      let _CRbitmap _channel 480 320 -> bmp in
      let _CRbitmap8 _channel 480 320 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-Landscape.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      //main splash
      let _GETalphaBitmapSize splash_src -> [aw ah] in
      let _CRbitmap _channel aw ah -> bmp in
      let _CRbitmap8 _channel aw ah -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/partition/"::APPBASEDIR::"os3dplayer/splash.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      _DSalphaBitmap splash_src;
    );
    
    //portrait
    let _checkpack (getProjectSetting "splashpath") -> psplash in
    let if (psplash == nil) then
          _checkpack (strcatn APPBASEDIR::"os3dplayer/splash_vert.png"::nil)
        else
          psplash
    -> splashpath in
    let G2DloadAlphaBmp _channel _PtoScol splashpath -> splash_src in
    (
      // 1125x2436 Splash
      let _CRbitmap _channel 1125 2436 -> bmp in
      let _CRbitmap8 _channel 1125 2436 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-812h@3x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 1242x2208 Splash
      let _CRbitmap _channel 1242 2208 -> bmp in
      let _CRbitmap8 _channel 1242 2208 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-414w-736h@3x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 750x1334 Splash 
      let _CRbitmap _channel 750 1334 -> bmp in
      let _CRbitmap8 _channel 750 1334 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-375w-667h@2x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 640x1136 Splash 
      let _CRbitmap _channel 640 1136 -> bmp in
      let _CRbitmap8 _channel 640 1136 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-568h@2x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 768x1024 Splash 
      let _CRbitmap _channel 768 1024 -> bmp in
      let _CRbitmap8 _channel 768 1024 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d-Portrait~ipad.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 640x960 Splash 
      let _CRbitmap _channel 640 960 -> bmp in
      let _CRbitmap8 _channel 640 960 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d@2x~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      // 640x960 Splash 
      let _CRbitmap _channel 640 960 -> bmp in
      let _CRbitmap8 _channel 640 960 -> bmp8 in
      let _CRalphaBitmap _channel bmp bmp8 nil nil -> abmp in
      let _BTSCALEalphaBitmap abmp splash_src 2 -> splash_png in
      (
        _BTSAVEalphaBitmap splash_png _getmodifypack strcatn dir::"/scol/resources/os3d~iphone.png"::nil;
        _DSbitmap bmp;
        _DSbitmap8 bmp8;
        _DSalphaBitmap abmp;
      );
      
      _DSalphaBitmap splash_src;
    );
    
    // add splash path in usm.ini for android splash managed in java
    //make usm.ini
    makeUsmIni strcat dir "/scol/resources" "ios" "OpenGLES2" "0" "" "" ldeps ("backgroundTask"::"no"::nil)::("splash"::(strcat APPBASEDIR "os3dplayer/splash.png")::nil)::nil;
    
    //make xcode project
    let _getpack _checkpack "scol.xcodeproj/project.pbxproj.in" -> xcodeprj in
    (
      set xcodeprj = strreplace xcodeprj "@IOS_PKG_NAME@" getProjectSettingDef "appPkgName" (strcat "os3d.app." shortname);
      set xcodeprj = strreplace xcodeprj "@IOS_PRODUCT_NAME@" strtoutf8 fname;
      set xcodeprj = strreplace xcodeprj "@IOS_PRJ_NAME@" strtoutf8 shortname;
      set xcodeprj = strreplace xcodeprj "@IOS_AUTHOR@" strtoutf8 (getProjectSettingDef "authorName" "Undefined");
      set xcodeprj = strreplace xcodeprj "@IOS_VERSION@" itoa (time + 100000000000);
      set xcodeprj = strreplace xcodeprj "@IOS_VERSION_NAME@" getProjectVersion;
      //set xcodeprj = strreplace xcodeprj "@IOS_ORIENTATION@" getProjectSettingDef "appOrientation" "landscape";
      
      _storepack xcodeprj strcatn dir::"/"::shortname::".xcodeproj/project.pbxproj"::nil;
    );
    
    let _getpack _checkpack "scol.xcodeproj/project.xcworkspace/contents.xcworkspacedata.in" -> xcodeprj in
    (
      set xcodeprj = strreplace xcodeprj "@IOS_PRJ_NAME@" strtoutf8 shortname;      
      _storepack xcodeprj strcatn dir::"/"::shortname::".xcodeproj/project.xcworkspace/contents.xcworkspacedata"::nil;
    );
    
    let _getpack _checkpack "scol/Info.plist.in" -> xcodeprj in
    (
      set xcodeprj = strreplace xcodeprj "@IOS_PRODUCT_NAME@" strtoutf8 fname;
      set xcodeprj = strreplace xcodeprj "@IOS_VERSION@" itoa (time + 100000000000);
      set xcodeprj = strreplace xcodeprj "@IOS_VERSION_NAME@" getProjectVersion;
      
      _storepack2 xcodeprj strcatn dir::"/scol/Info.plist"::nil;
    );
    
    //make master.pkg
    let ("typeof"::"env_ref=Env;;"::nil)::
        ("defcom"::"Smain=main"::"S"::"S"::"S"::"S"::"I;;"::nil)::
        ("fun"::"multiress(res)="::nil)::
        ("if"::"res==nil"::"then"::nil)::
        ("0"::nil)::
        ("else"::nil)::
        ("let"::"res"::"->"::"[l"::"nxt]"::"in"::nil)::
        ("("::nil)::
        ("_setress"::"hd"::"l"::"hd"::"tl"::"l;"::nil)::
        ("multiress"::"nxt;"::nil)::
        (");;"::nil)::
        
        ("fun"::"main(p)="::nil)::
        ("set"::"env_ref=_envchannel"::"_channel;"::nil)::
        ("multiress"::"strextr"::"_loadressini;"::nil)::  
        ("srand"::"time;"::nil)::
        ("_load"::(strcatn "\""::APPBASEDIR::"os3dplayer/os3dload.pkg\";"::nil)::nil)::
        ("_script"::"mkscript"::"Smain"::(strcatn "[\""::xmlpath::"\""::nil)::(strcatn "\""::fname::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultWidth" "1280")::"\""::nil)::(strcatn "\""::(getProjectSettingDef "defaultHeight" "720")::"\""::nil)::"0];"::nil)::
        ("0;;"::nil)::nil
    -> pmaster in
    _storepack (strbuild pmaster) strcatn dir::"/scol/resources/partition/locked/master.pkg"::nil;
    0;
  );;


fun cbMkIosDoneBtn(ctrlbtn, p)=
  let p -> [winstr pwinstr exportdir xmlpath projname] in
  (
    dsEdWindow winstr;
    dsEdWindow pwinstr;
    set winMkApplet = nil;
    let strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\IOS"::"\\"::projname::nil -> fullpath in
    (
      _startExe "launch" "openExplorer" strcatn "\""::fullpath::"\""::nil;
    );
  );
  0;;


fun cbMkIosCancelBtn(ctrlbtn, winstr)=
  dsEdWindow winstr;
  0;;


fun cbDestroyIosExportWin(winstr, pwinstr)=
  dsEdWindow2 pwinstr;
  0;;


fun cbMkIosOk(ctrlbtn, p)=
  let p -> [pwinstr fatherstr projname xmlpath script ctrlorient ctrlpkgname] in
  let _GETscreenSize -> [sw sh] in
  let [430 120] -> [iw ih] in
  let getDirectoryWithoutLastSlash (getFileDirectory xmlpath) -> projdir in
  let getSelectedEdCtrlSelectPos ctrlorient -> orientation in
  let getEdCtrlTextLineValue ctrlpkgname -> pkgname in
  let if (projdir == nil) || (!strcmp projdir "") then (strcatn sExportDirectory::"/IOS"::"/"::projname::nil) else (strcatn projdir::"/"::sExportDirectory::"/IOS"::"/"::projname::nil) -> exportdir in
  (
    //set conf
    let if (orientation == 0) then
          "landscape"
        else if (orientation == 1) then
          "portrait"
        else if (orientation == 2) then
          "reverseLandscape"
        else
          "reversePortrait"
    -> orientmode in
      setProjectSetting "appOrientation" orientmode;
    
    if (!checkAndroidPkgName(pkgname)) then
    (
      _DLGMessageBox _channel pwinstr.EDW_win (loc "OS3D_0155") strcatn (loc "OS3D_0586")::nil 0;
      0;
    )
    else
    (
      setProjectSetting "appPkgName" strlowercase pkgname;
      
      let crEdModalDialogWindow _channel pwinstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
      let crEdCtrlLabelEx winstr 10 12 iw-20 50 (loc "OS3D_0524") ET_ALIGN_CENTER nil -> labelport in
      let crEdCtrlButton winstr ((iw /2) - 45) (ih - 30) 90 20 (loc "OS3D_0518") EDWIN_RESIZE_MW -> ctrldone in
      (
        set winMkApplet = winstr;
        
        setEdCtrlButtonEnable ctrldone 0;
        _addPartition "./Ios" 2;
        let mkStandAloneListFiles xmlpath -> [lfiles ldeps] in
        (
          cleanDirectory exportdir;
          copyIosFilesToExportDirectory exportdir lfiles ldeps xmlpath projname;
       
          setEdCtrlButtonCb ctrldone mkfun2 @cbMkIosDoneBtn [winstr pwinstr exportdir xmlpath projname];
          setEdwindowCbDestroy winstr mkfun2 @cbDestroyIosExportWin pwinstr;
          
          setEdWindowFocus winstr;
        );
        
        _removeLastPartition;
        setEdCtrlLabelValue labelport strcatn (loc "OS3D_0520")::exportdir::(loc "OS3D_0548")::nil;
        setEdCtrlButtonEnable ctrldone 1;
      );      
      0;
    );
  );
  0;;


fun cbMkIosValidate(ctrl, val, p)=
  cbMkIosOk nil p;
  0;;

  
fun mkIosApp(fatherstr, projname, xmlpath, script)=
  _refreshExe;
  let _GETscreenSize -> [sw sh] in
  let [430 90] -> [iw ih] in
  let 10 -> ipos in
  let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
  
  let getAndroidShortName projname -> shortname in
  let getProjectSettingDef "appPkgName" if ((getProjectSetting "authorCompany") != nil) then strcatn "com."::(getAndroidShortName (getProjectSetting "authorCompany"))::"."::shortname::nil else strcat "os3d.app." shortname -> pkgname in
  let crEdCtrlLabel winstr 10 (ipos + 2) 160 20 (loc "OS3D_0585") nil -> labelpkg in
  let crEdCtrlTextLine winstr 180 ipos (iw - 190) 20 pkgname nil EDWIN_RESIZE_MW -> ctrlpkgname in
  //let crEdCtrlLabel winstr 10 ((set ipos = ipos + 25) + 2) 160 20 (loc "OS3D_0582") nil -> labelorient in
  //let crEdCtrlSelect winstr 180 ipos (iw - 190) 120 EDWIN_RESIZE_MW -> ctrlorient in
  let crEdCtrlButton winstr 10 (ih - 30) 90 20 (loc "OS3D_0536") EDWIN_RESIZE_MW -> ctrlok in
  let crEdCtrlButton winstr (iw - 100) (ih - 30) 90 20 (loc "OS3D_0513") EDWIN_RESIZE_MW -> ctrlcancel in
  let [winstr fatherstr projname xmlpath script /*ctrlorient*/ nil ctrlpkgname] -> p in
  (
    set winMkApplet = winstr;
    
    /*
    fillEdCtrlSelect ctrlorient (loc "OS3D_0583")::(loc "OS3D_0584")::nil;
    let if !strcmpi (getProjectSettingDef "appOrientation" "landscape") "landscape" then 0 else 1 -> opos in
      selectEdCtrlSelectByPos ctrlorient opos;
    */
    
    setEdCtrlButtonCb ctrlok mkfun2 @cbMkIosOk p;
    setEdCtrlButtonCb ctrlcancel mkfun2 @cbMkIosCancelBtn winstr;
  );
  0;;
  

//// OS3D PACK
fun cbDestroyOS3DPakExportWin(winstr)=
  0;;


fun cbOS3DPakProjectPacked(p)=
  let p -> [labelport ctrldone exportdir] in
  (
    setEdCtrlLabelValue labelport strcatn (loc "OS3D_0520")::exportdir::(loc "OS3D_0548")::nil;
    setEdCtrlButtonEnable ctrldone 1;
  );
  0;;


fun cbMkOS3DPakDoneBtn(ctrlstr, p)=
  let p -> [winstr exportdir xmlpath projname] in
  (
    dsEdWindow winstr;
    set winMkApplet = nil;
    let strcatn (getFileDirectory (_PtoS _checkpack xmlpath))::sExportDirectory::"\\OS3DPACK"::"\\"::projname::nil -> fullpath in
    (
      _startExe "launch" "openExplorer" strcatn "\""::fullpath::"\""::nil;
    );
  );
  0;;


fun cbOS3DPakTrm(trm, wp)=
  let wp -> [l wfile logp cbComplete] in
  (
    _deltimer trm;
    _freememory;
    
    //manage cancel
    if (winMkApplet == nil) then nil else
      mkOS3DPakAll l wfile logp cbComplete;
  );
  0;;


fun mkOS3DPakAll(l, wfile, logp, cbComplete)=
  if (l == nil) then
  (
    _appendpack "\nDone!" logp;
    exec cbComplete with [];
    0;
  )
  else
  (
    let l->[name nxt] in
    let
      let _FILEOpen _channel _checkpack name -> from in
      if (from == nil) then 0 else
      let _FILESize from -> size in
        (_FILEClose from; size;)
    -> filesize in
    if (filesize > iOS3DPackMaxZipBuffer) then
    (
      if ((_checkpack name) == nil) then nil else
      (
    	  let _fileSign _checkpack name -> signstr in
    	  let if (!strcmpi (substr name 0 (strlen APPBASEDIR)) APPBASEDIR) then strcat "APPBASEDIR" (substr name ((strlen APPBASEDIR) - 1) (strlen name)) else strcat "APPROOTDIR/" name -> mname in
    	    _appendpack strcatn "#******#"::mname::"|"::"!Z"::"|"::signstr::"|"::(itoa filesize)::"|"::nil wfile;
    	  
    	  let _FILEOpen _channel _checkpack name -> file in
    	  if (file == nil) then nil else
        (
          while ((_FILETell file) < filesize) do
            _appendpack (_FILERead file 65534) wfile;
          
          _FILEClose file;
        );
    	  
    	  _freememory;
    	  _appendpack strcatn "\n> Packed "::name::nil logp;
      );
        
  	  // use a timer to allow the garbage collector to free some memory in the loop
  	  _rfltimer _starttimer _channel 5 @cbOS3DPakTrm [nxt wfile logp cbComplete];
  	  0;
    )
    else
    (
      if ((_checkpack name) == nil) then nil else
      let getFileContent name -> content in
      let 1 -> packed in
      (
        if (content != nil) then nil else
        let getPathFile _PtoScol (_WtoP wfile) "" -> [path _] in
        let getPathFile name "" -> [_ fname] in
        (
          _CopyFile (_checkpack name) (_getmodifypack strcatn path::"/"::fname::nil);
    	    _appendpack strcatn "\n> Copy "::name::" because the file is too big to be packed"::nil logp;
    	    set packed = 0;
        );
        
    	  let if (content == nil) then "" else zip content -> ziped in
    	  let if (content == nil) then _fileSign _checkpack name else (_getlongname content "" "#") -> signstr in
    	  let if (!strcmpi (substr name 0 (strlen APPBASEDIR)) APPBASEDIR) then strcat "APPBASEDIR" (substr name ((strlen APPBASEDIR) - 1) (strlen name)) else strcat "APPROOTDIR/" name -> mname in
    	    _appendpack strcatn "#******#"::mname::"|"::"Z"::"|"::signstr::"|"::(itoa (strlen ziped))::"|"::ziped::nil wfile;
    	  
    	  _freememory;
    	  if (!packed) then nil else
    	    _appendpack strcatn "\n> Packed "::name::nil logp;
      );
      
  	  // use a timer to allow the garbage collector to free some memory in the loop
  	  _rfltimer _starttimer _channel 5 @cbOS3DPakTrm [nxt wfile logp cbComplete];
  	  0;
    );
  );
  0;;
  

fun mkOS3DPakProject(lfiles, outpath, xmlpath, logpath, cbComplete)=
  let strcatn (mkDTime time)::"\n"::xmlpath::"\n"::nil -> ncontent in
  let _getmodifypack logpath -> logp in
  (
    _appendpack "// Export OpenSpace3D project package //\n" logp;
    _appendpack ncontent logp;
    _storepack ncontent outpath;
    
    mkOS3DPakAll lfiles (_getmodifypack outpath) logp cbComplete;
  );
  0;;


fun mkOS3DPack(fatherstr, projname, xmlpath, script)=
  let getAndroidShortName projname -> shortname in
  let getProjectSettingDef "appPkgName" if ((getProjectSetting "authorCompany") != nil) then strcatn "com."::(getAndroidShortName (getProjectSetting "authorCompany"))::"."::shortname::nil else strcat "os3d.app." shortname -> pkgname in
  let getDirectoryWithoutLastSlash (getFileDirectory xmlpath) -> projdir in
  let if (projdir == nil) || (!strcmp projdir "") then (strcatn sExportDirectory::"/OS3DPACK"::"/"::projname::nil) else (strcatn projdir::"/"::sExportDirectory::"/OS3DPACK"::"/"::projname::nil) -> exportdir in
  
  let strlowercase strcatn exportdir::"/"::pkgname::".pkos"::nil -> pakpath in
  let strlowercase strcatn exportdir::"/"::pkgname::".log"::nil -> logpath in
  (
    let _GETscreenSize -> [sw sh] in
    let [430 120] -> [iw ih] in
    let crEdModalDialogWindow _channel fatherstr ((sw / 2) - (iw / 2)) ((sh / 2) - (ih / 2)) iw ih WN_NOSCOL|WN_MENU nil (loc "OS3D_0556") -> winstr in
    let crEdCtrlLabelEx winstr 10 12 iw-20 50 (loc "OS3D_0524") ET_ALIGN_CENTER nil -> labelport in
    let crEdCtrlButton winstr ((iw /2) - 45) (ih - 30) 90 20 (loc "OS3D_0518") EDWIN_RESIZE_MW -> ctrldone in
    (
      set winMkApplet = winstr;
      
      setEdCtrlButtonEnable ctrldone 0;
      let mkStandAloneProjectListFiles xmlpath -> [lfiles ldeps] in
      (
        cleanDirectory exportdir;
        mkOS3DPakProject lfiles pakpath xmlpath logpath mkfun1 @cbOS3DPakProjectPacked [labelport ctrldone exportdir];
        
        setEdCtrlButtonCb ctrldone mkfun2 @cbMkOS3DPakDoneBtn [winstr exportdir xmlpath projname];
        setEdwindowCbDestroy winstr @cbDestroyOS3DPakExportWin;
        
        setEdWindowFocus winstr;
      );
    );
  );
  0;;