package org.freertr.user; import java.io.File; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.List; import org.freertr.cfg.cfgAll; import org.freertr.cry.cryHashCrc32; import org.freertr.pipe.pipeSide; import org.freertr.enc.encUrl; import org.freertr.tab.tabGen; import org.freertr.util.bits; import org.freertr.util.logger; import org.freertr.util.version; /** * virtual machine v2 * * @author matecsaba */ public class userVM { private final static String rootDir = "../vm/"; private final static int reg_a = 1; private final static int reg_b = 2; private final static int reg_c = 3; private final static int reg_d = 4; private final static int reg_src = 5; private final static int reg_trg = 6; private final static int reg_cip = 7; /** * termination flag */ public final static int res_term = 0x40000000; private final static int memBound = 65536; private boolean allowFileIO; private int[] regs; private int flags; // 1=above, 2=below, 4=equal private String nam; private String par; private byte[] stackD; private int stackP; private byte[] codeD; private byte[] dataD; private int dataP; private int dataS; private int[] procD; private tabGen files; private tabGen dirs; private pipeSide console; private String currDir; /** * do vm work * * @param cons pipe to use * @param fio set true to allow file io * @param dir working directory * @param name file to load * @param param parameters to give * @return result code */ public int doWork(pipeSide cons, boolean fio, String dir, String name, String param) { userVM vm = new userVM(cons, fio, dir); int res; try { vm.doLoad(name, param); res = vm.doProcess(); } catch (Exception e) { cons.linePut("vm error: " + logger.dumpException(e, "fio=" + fio + " fn=" + dir + " " + name + " pars" + param)); List txt = vm.dump(); for (int i = 0; i < txt.size(); i++) { cons.linePut(txt.get(i)); } res = 1; } try { vm.doFinish(); } catch (Exception e) { } return res; } /** * construct a vm2 * * @param cons pipe to use * @param fio set true to allow file io * @param dir working directory */ public userVM(pipeSide cons, boolean fio, String dir) { console = cons; allowFileIO = fio; currDir = "/" + encUrl.normalizePath(dir + "/"); regs = new int[8]; } public String toString() { return "emulating " + nam; } /** * dump this virtual machine * * @return dump of virtual machine */ public List dump() { List l = new ArrayList(); l.add("nam='" + nam + "' par='" + par + "' dir='" + currDir + "'"); l.add("a=" + regs[reg_a] + " b=" + regs[reg_b] + " c=" + regs[reg_c] + " d=" + regs[reg_d]); l.add("src=" + regs[reg_src] + " trg=" + regs[reg_trg] + " cip=" + regs[reg_cip]); return l; } /** * convert result to error * * @param i result * @return error */ public static int result2error(int i) { if ((i & res_term) == 0) { return i; } else { return 0; } } /** * convert result to exit code * * @param i result * @return exit code */ public static int result2extcod(int i) { i &= ~res_term; return i; } /** * convert result to string * * @param i result * @return string */ public static String result2string(int i) { if (result2error(i) != 0) { return "error code=" + result2error(i); } return "exit code=" + result2extcod(i); } private static int getSize(int siz) { siz &= 15; switch (siz) { case 1: return 1; case 2: return 2; case 3: return 4; } return 0; } private static int convType(int d, int sig, int siz, int after) { sig &= 1; siz &= 15; switch (siz) { case 1: d &= 0xff; break; case 2: d &= 0xffff; break; case 3: d &= 0xffffffff; break; } if (sig != 0) { switch (siz) { case 1: d = (byte) d; break; case 2: d = (short) d; break; case 3: // d = d; break; } } if (after != 0) { switch (siz) { case 1: d &= 0xff; break; case 2: d &= 0xffff; break; case 3: d &= 0xffffffff; break; } } return d; } private static String replacePathSep(String s) { byte[] buf = s.getBytes(); for (int i = 0; i < buf.length; i++) { switch (buf[i]) { case 47: buf[i] = 92; break; case 92: buf[i] = 47; break; } } return new String(buf); } private static String fromUnix(String s) { return "c:" + replacePathSep(s); } private String fromDos(String s) { s = replacePathSep(s); if (s.length() > 2) { if (s.substring(1, 3).equals(":/")) { s = s.substring(2, s.length()); } } if (!s.startsWith("/")) { s = currDir + s; } return s; } private String getPascii(int ofs) { int i = dataD[ofs]; byte[] buf = new byte[i]; bits.byteCopy(dataD, ofs + 1, buf, 0, buf.length); return new String(buf); } private void putPascii(int ofs, String str) { final int max = 255; if (str.length() > max) { str = str.substring(0, max); } byte[] res = str.getBytes(); dataD[ofs] = (byte) res.length; bits.byteCopy(res, 0, dataD, ofs + 1, res.length); } private void putAsciiz(int ofs, String str) { byte[] res = str.getBytes(); bits.byteCopy(res, 0, dataD, ofs, res.length); bits.msbPutD(dataD, ofs + res.length, 0); } private int readOne(byte[] data, int ofs, int siz, int msb) throws Exception { siz &= 15; switch (siz) { case 1: return data[ofs] & 0xff; case 2: switch (msb) { case 1: // default case 3: // lsb return bits.lsbGetW(data, ofs); case 2: // msb return bits.msbGetW(data, ofs); default: throw new Exception("invalid type"); } case 3: switch (msb) { case 1: // default case 3: // lsb return bits.lsbGetD(data, ofs); case 2: return bits.msbGetD(data, ofs); default: throw new Exception("invalid type"); } default: throw new Exception("invalid type"); } } private void writeOne(byte[] data, int ofs, int siz, int msb, int val) throws Exception { siz &= 15; switch (siz) { case 1: data[ofs] = (byte) (val & 0xff); return; case 2: switch (msb) { case 1: // default case 3: // lsb bits.lsbPutW(data, ofs, val); return; case 2: // msb bits.msbPutW(data, ofs, val); return; default: throw new Exception("invalid type"); } case 3: switch (msb) { case 1: // default case 3: // lsb bits.lsbPutD(data, ofs, val); return; case 2: // msb bits.msbPutD(data, ofs, val); return; default: throw new Exception("invalid type"); } default: throw new Exception("invalid type"); } } private int getConst(int siz) throws Exception { int i = readOne(codeD, regs[reg_cip], siz, 1); regs[reg_cip] += getSize(siz); return i; } private void pushOne(int val, int siz) throws Exception { writeOne(stackD, stackP, siz, 1, val); stackP += getSize(siz); } private int popOne(int siz) throws Exception { stackP -= getSize(siz); return readOne(stackD, stackP, siz, 1); } private int getMemory() throws Exception { int i, o, p; i = getConst(1); p = i & 0x80; i = i & 15; o = getConst(3); i = regs[i]; if (p == 0) { o += i; } else { o -= i; } return o; } private static int convCol(int i) { final int[] tab = {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; int fg = i & 0xf; int bg = (i >>> 4) & 0xf; return tab[fg] | (tab[bg] << 16); } private int getKey() { return userScreen.getKey(console); } /** * load one file * * @param name file to load * @param param parameters to give * @throws Exception on error */ public void doLoad(String name, String param) throws Exception { name = "/" + encUrl.normalizePath(name); nam = name; par = param; RandomAccessFile f = new RandomAccessFile(rootDir + name, "r"); int codeS = (int) f.length(); codeD = new byte[codeS]; f.read(codeD, 0, codeS); f.close(); if (getConst(3) != 0x30314d56) { throw new Exception("invalid magic number"); } int i = getConst(3); if (i != codeS) { throw new Exception("invalid size field"); } int stackS = getConst(3); dataS = getConst(3) + memBound; int procS = getConst(3); int procB = getConst(3); cryHashCrc32 h = new cryHashCrc32(cryHashCrc32.polyCrc32i); h.init(); h.update(codeD, 0, codeD.length - 4); byte[] buf = h.finish(); regs[reg_cip] = codeD.length - 4; if (getConst(3) != bits.msbGetD(buf, 0)) { throw new Exception("invalid checksum"); } regs[reg_cip] = procB; stackD = new byte[stackS + memBound]; dataD = new byte[dataS]; procD = new int[procS]; files = new tabGen(); dirs = new tabGen(); } /** * run until end * * @return result code * @throws Exception on error */ public int doProcess() throws Exception { int i; for (;;) { i = doOpcode(); if ((i & res_term) != 0) { break; } } return i; } /** * finish the process */ public void doFinish() { for (int i = 0; i < files.size(); i++) { try { files.get(i).fil.close(); } catch (Exception e) { } } } /** * run one opcode * * @return result code * @throws Exception on error */ public int doOpcode() throws Exception { int form; int siz1, siz2; int reg1, reg2; int val1, val2; int opc = getConst(1); switch (opc) { case 1: // add siz1 = getConst(1); reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } regs[reg1] += val1; return 0; case 2: // sub siz1 = getConst(1); reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } regs[reg1] -= val1; return 0; case 3: // mul siz1 = getConst(1); siz2 = siz1 >>> 6; reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } val1 = convType(val1, siz2, siz1, 0); val2 = convType(regs[reg1], siz2, siz1, 0); regs[reg1] = val2 * val1; return 0; case 4: // div siz1 = getConst(1); siz2 = siz1 >>> 6; reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } val1 = convType(val1, siz2, siz1, 0); val2 = convType(regs[reg1], siz2, siz1, 0); if (val1 == 0) { throw new Exception("division by zero"); } regs[reg1] = val2 / val1; return 0; case 5: // mod siz1 = getConst(1); siz2 = siz1 >>> 6; reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } val1 = convType(val1, siz2, siz1, 0); val2 = convType(regs[reg1], siz2, siz1, 0); if (val1 == 0) { throw new Exception("division by zero"); } regs[reg1] = val2 % val1; return 0; case 6: // or siz1 = getConst(1); reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } regs[reg1] |= val1; return 0; case 7: // xor siz1 = getConst(1); reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } regs[reg1] ^= val1; return 0; case 8: // and siz1 = getConst(1); reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } regs[reg1] &= val1; return 0; case 9: // not siz1 = getConst(1); reg1 = getConst(1); regs[reg1] = -1 - regs[reg1]; return 0; case 10: // neg siz1 = getConst(1); reg1 = getConst(1); regs[reg1] = -regs[reg1]; return 0; case 11: // shl siz1 = getConst(1); reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } regs[reg1] <<= val1; return 0; case 12: // shr siz1 = getConst(1); reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } regs[reg1] >>>= val1; return 0; case 13: // push siz1 = getConst(1); reg1 = getConst(1); val1 = regs[reg1]; pushOne(val1, siz1); return 0; case 14: // pop siz1 = getConst(1); reg1 = getConst(1); regs[reg1] = popOne(siz1); return 0; case 15: // comp siz1 = getConst(1); siz2 = siz1 >>> 6; reg1 = getConst(1); if ((siz1 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } val1 = convType(val1, siz2, siz1, 0); val2 = convType(regs[reg1], siz2, siz1, 0); reg1 = 0; if (val1 < val2) { reg1 |= 1; } if (val1 > val2) { reg1 |= 2; } if (val1 == val2) { reg1 |= 4; } flags &= 0xffffff8; flags |= reg1; return 0; case 16: // move siz1 = getConst(1); siz2 = getConst(1); reg1 = getConst(1); if ((siz2 & 0x80) != 0) { val1 = getConst(3); } else { val1 = regs[getConst(1)]; } val1 = convType(val1, siz2 >>> 6, siz2, 0); val1 = convType(val1, siz1 >>> 6, siz1, 1); regs[reg1] = val1; return 0; case 17: // movr form = getConst(1); siz1 = getConst(1); siz2 = getConst(1); val2 = getMemory(); reg1 = getConst(1); val1 = readOne(dataD, val2, siz2, form); val1 = convType(val1, siz2 >>> 6, siz2, 0); val1 = convType(val1, siz1 >>> 6, siz1, 1); regs[reg1] = val1; return 0; case 18: // movw form = getConst(1); siz1 = getConst(1); siz2 = getConst(1); val2 = getMemory(); reg1 = getConst(1); val1 = regs[reg1]; val1 = convType(val1, siz2 >>> 6, siz2, 0); val1 = convType(val1, siz1 >>> 6, siz1, 1); writeOne(dataD, val2, siz1, form, val1); return 0; case 19: // call val1 = getConst(3); pushOne(regs[reg_cip], 3); regs[reg_cip] = val1; return 0; case 20: // ret regs[reg_cip] = popOne(3); return 0; case 21: // jump regs[reg_cip] = getConst(3); return 0; case 22: // jmpc reg1 = getConst(1); val1 = getConst(3); if ((flags & reg1) != 0) { regs[reg_cip] = val1; } return 0; case 23: // addrLod val2 = getMemory(); reg1 = getConst(1); regs[reg1] = readOne(dataD, val2, 3, 1); return 0; case 24: // addrSav val2 = getMemory(); reg1 = getConst(1); writeOne(dataD, val2, 3, 1, regs[reg1]); return 0; case 25: // procAddr reg1 = getConst(1); val1 = getConst(3); if (val1 == -1) { val2 = popOne(3); pushOne(val2, 3); } else { val2 = procD[val1]; } regs[reg1] = val2; return 0; case 26: // procAllocBeg val1 = getConst(3); val2 = procD[val1]; pushOne(val2, 3); val2 = dataP; val1 = getConst(3); dataP += val1; pushOne(val2, 3); return 0; case 27: // procFree val1 = getConst(3); val2 = popOne(3); procD[val1] = val2; val2 = getConst(3); dataP -= val2; return 0; case 28: // codeOfs reg1 = getConst(1); regs[reg1] = getConst(3); return 0; case 29: // xchg siz1 = getConst(1); val2 = getMemory(); reg1 = getConst(1); val1 = regs[reg1]; regs[reg1] = readOne(dataD, val2, siz1, 1); writeOne(dataD, val2, siz1, 1, val1); return 0; case 30: // setc reg2 = getConst(1); siz1 = getConst(1); reg1 = getConst(1); if ((flags & reg2) != 0) { val1 = 1; } else { val1 = 0; } regs[reg1] = val1; return 0; case 31: // procAllocEnd val2 = popOne(3); val1 = getConst(3); procD[val1] = val2; getConst(3); return 0; case 32: // syscall return doSyscall(); case 33: // cllr reg1 = getConst(1); pushOne(regs[reg_cip], 3); regs[reg_cip] = regs[reg1]; return 0; case 34: // jmpr reg1 = getConst(1); regs[reg_cip] = regs[reg1]; return 0; } regs[reg_cip] -= 1; throw new Exception("unknown (" + opc + ") opcode"); } /** * do a system call * * @return return code * @throws Exception may throw an exception */ public int doSyscall() throws Exception { int opc = getConst(1); int val1; switch (opc) { case 1: // sleep bits.sleep(10); return 0; case 2: // memCopy bits.byteCopy(dataD, regs[reg_src], dataD, regs[reg_trg], regs[reg_c]); return 0; case 3: // codeCopy bits.byteCopy(codeD, regs[reg_src], dataD, regs[reg_trg], regs[reg_c]); return 0; case 4: // terminate return (regs[reg_a] & 0xffff) | res_term; case 5: // console.write console.strPut(new String(dataD, regs[reg_src], regs[reg_c])); return 0; case 6: // console.read if (console.ready2rx() < 1) { if (console.isClosed() != 0) { throw new Exception("console closed"); } regs[reg_c] = 0; return 0; } bits.lsbPutW(dataD, regs[reg_trg], getKey()); regs[reg_c] = 2; return 0; case 7: // file.maxName regs[reg_a] = 128; return 0; case 8: // file.myName String a = fromUnix(nam); regs[reg_c] = a.length(); putAsciiz(regs[reg_trg], a); return 0; case 9: // file.myParam regs[reg_c] = par.length(); putAsciiz(regs[reg_trg], par); return 0; case 10: // file.open regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (!new File(a).exists()) { return 0; } userVMfile fil = new userVMfile(0); try { fil.fil = new RandomAccessFile(a, "rw"); } catch (Exception e) { return 0; } for (;;) { fil.num = bits.randomD(); if (files.add(fil) == null) { break; } } regs[reg_a] = fil.num; regs[reg_b] = 0; return 0; case 11: // file.read regs[reg_b] = 1; fil = files.find(new userVMfile(regs[reg_a])); if (fil == null) { return 0; } try { fil.fil.read(dataD, regs[reg_trg], regs[reg_c]); } catch (Exception e) { return 0; } regs[reg_b] = 0; return 0; case 12: // file.write regs[reg_b] = 1; fil = files.find(new userVMfile(regs[reg_a])); if (fil == null) { return 0; } try { fil.fil.write(dataD, regs[reg_src], regs[reg_c]); } catch (Exception e) { return 0; } regs[reg_b] = 0; return 0; case 13: // file.seek regs[reg_b] = 1; fil = files.find(new userVMfile(regs[reg_a])); if (fil == null) { return 0; } try { fil.fil.seek(regs[reg_c]); } catch (Exception e) { return 0; } regs[reg_b] = 0; return 0; case 14: // file.getSize regs[reg_b] = 1; fil = files.find(new userVMfile(regs[reg_a])); if (fil == null) { return 0; } try { regs[reg_c] = (int) fil.fil.length(); } catch (Exception e) { return 0; } regs[reg_b] = 0; return 0; case 15: // file.getPos regs[reg_b] = 1; fil = files.find(new userVMfile(regs[reg_a])); if (fil == null) { return 0; } try { regs[reg_c] = (int) fil.fil.getFilePointer(); } catch (Exception e) { return 0; } regs[reg_b] = 0; return 0; case 16: // file.truncate regs[reg_b] = 1; fil = files.find(new userVMfile(regs[reg_a])); if (fil == null) { return 0; } try { fil.fil.setLength(fil.fil.getFilePointer()); } catch (Exception e) { return 0; } regs[reg_b] = 0; return 0; case 17: // file.close regs[reg_b] = 1; fil = files.del(new userVMfile(regs[reg_a])); if (fil == null) { return 0; } try { fil.fil.close(); } catch (Exception e) { return 0; } regs[reg_b] = 0; return 0; case 18: // file.create regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (userFlash.mkfile(a)) { return 0; } regs[reg_b] = 0; return 0; case 19: // file.erase regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (userFlash.delete(a)) { return 0; } regs[reg_b] = 0; return 0; case 20: // dir.current putPascii(regs[reg_trg], fromUnix(currDir)); regs[reg_b] = 0; return 0; case 21: // dir.change regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = fromDos(getPascii(regs[reg_src])); a = "/" + encUrl.normalizePath(a + "/"); if (!new File(rootDir + a).isDirectory()) { return 0; } currDir = a; regs[reg_b] = 0; return 0; case 22: // dir.setRights regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (!new File(a).exists()) { return 0; } regs[reg_b] = 0; return 0; case 23: // dir.rename regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (userFlash.rename(a, rootDir + fromDos(getPascii(regs[reg_trg])), false, false)) { return 0; } regs[reg_b] = 0; return 0; case 24: // dir.makeLink regs[reg_b] = 1; return 0; case 25: // dir.open regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (!new File(a).exists()) { return 0; } userVMdir dir = new userVMdir(0); dir.lst = userFlash.dirList(a); if (dir.lst == null) { return 0; } for (;;) { dir.num = bits.randomD(); if (dirs.add(dir) == null) { break; } } regs[reg_a] = dir.num; regs[reg_b] = 0; return 0; case 26: // dir.read regs[reg_b] = 1; dir = dirs.find(new userVMdir(regs[reg_a])); if (dir == null) { return 0; } bits.byteFill(dataD, regs[reg_trg], 64, 0); if (dir.pos < dir.lst.length) { File ntry = dir.lst[dir.pos]; dir.pos++; int ofs = regs[reg_trg]; int rgt = 0; long tim = ntry.lastModified(); if (ntry.isDirectory()) { rgt |= 0x83; } if (ntry.canRead()) { rgt |= 0x01; } if (ntry.canWrite()) { rgt |= 0x02; } if (ntry.canExecute()) { rgt |= 0x04; } bits.lsbPutD(dataD, ofs + 0, (int) ntry.length()); bits.lsbPutD(dataD, ofs + 4, rgt); bits.lsbPutD(dataD, ofs + 8, 0); bits.lsbPutW(dataD, ofs + 12, bits.time2num(cfgAll.timeZoneName, tim, 1)); dataD[ofs + 14] = (byte) bits.time2num(cfgAll.timeZoneName, tim, 2); dataD[ofs + 15] = (byte) bits.time2num(cfgAll.timeZoneName, tim, 3); dataD[ofs + 16] = (byte) bits.time2num(cfgAll.timeZoneName, tim, 4); dataD[ofs + 17] = (byte) bits.time2num(cfgAll.timeZoneName, tim, 5); dataD[ofs + 18] = (byte) bits.time2num(cfgAll.timeZoneName, tim, 6); bits.byteCopy(dataD, ofs + 12, dataD, ofs + 19, 7); putPascii(ofs + 26, ntry.getName()); } regs[reg_b] = 0; return 0; case 27: // dir.close regs[reg_b] = 1; dir = dirs.del(new userVMdir(regs[reg_a])); if (dir == null) { return 0; } regs[reg_b] = 0; return 0; case 28: // dir.create regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (userFlash.mkdir(a)) { return 0; } regs[reg_b] = 0; return 0; case 29: // dir.erase regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (userFlash.delete(a)) { return 0; } regs[reg_b] = 0; return 0; case 30: // dir.stats regs[reg_a] = 0x20000000; regs[reg_b] = 0x10000000; regs[reg_c] = 0; regs[reg_d] = 512; return 0; case 31: // dir.setDate regs[reg_b] = 1; if (!allowFileIO) { return 0; } a = rootDir + fromDos(getPascii(regs[reg_src])); if (!new File(a).exists()) { return 0; } regs[reg_b] = 0; return 0; case 32: // memReSize byte[] buf = dataD; dataD = new byte[dataS + regs[reg_c] + memBound]; if (buf.length < dataD.length) { val1 = buf.length; } else { val1 = dataD.length; } bits.byteCopy(buf, 0, dataD, 0, val1); regs[reg_c] = dataD.length - dataS - memBound; regs[reg_trg] = dataS; return 0; case 33: // memInfo regs[reg_c] = dataD.length - dataS - memBound; regs[reg_trg] = dataS; return 0; case 34: // console.isKey regs[reg_a] = 0; if (console.ready2rx() > 0) { regs[reg_a] = 1; } return 0; case 35: // console.size regs[reg_a] = 78; regs[reg_b] = 24; return 0; case 36: // console.gotoXY userScreen.sendCur(console, regs[reg_a] - 1, regs[reg_b] - 1); return 0; case 37: // console.setColor userScreen.sendAnsCol(console, convCol(regs[reg_a])); return 0; case 38: // console.clear userScreen.sendCls(console); return 0; case 39: // console.execWait a = fromDos(getPascii(regs[reg_src])); userVM v = new userVM(console, true, currDir); v.doLoad(a, currDir); val1 = v.doWork(console, true, "", a, currDir); regs[reg_b] = result2error(val1); regs[reg_a] = result2extcod(val1); return 0; case 40: // console.execBckgnd regs[reg_b] = 1; return 0; case 41: // console.execInMe regs[reg_b] = 1; return 0; case 42: // console.getDate regs[reg_a] = bits.time2num(cfgAll.timeZoneName, bits.getTime(), 1); regs[reg_b] = bits.time2num(cfgAll.timeZoneName, bits.getTime(), 2); regs[reg_c] = bits.time2num(cfgAll.timeZoneName, bits.getTime(), 3); return 0; case 43: // console.getTime regs[reg_a] = bits.time2num(cfgAll.timeZoneName, bits.getTime(), 4); regs[reg_b] = bits.time2num(cfgAll.timeZoneName, bits.getTime(), 5); regs[reg_c] = bits.time2num(cfgAll.timeZoneName, bits.getTime(), 6); return 0; case 44: // memFillByte bits.byteFill(dataD, regs[reg_trg], regs[reg_c], regs[reg_a]); return 0; case 100: // pipeline.startListen case 101: // pipeline.stopListen case 102: // pipeline.getIncoming case 103: // pipeline.create case 104: // pipeline.close case 105: // pipeline.info case 106: // pipeline.receive case 107: // pipeline.send regs[reg_b] = 1; return 0; case 108: // system.getPID regs[reg_a] = 1234; regs[reg_b] = 4321; regs[reg_c] = 3; return 0; case 109: // system.getUID regs[reg_a] = 0; regs[reg_b] = 0; return 0; case 110: // system.sysInfoNum regs[reg_a] = 1; regs[reg_c] = 0; regs[reg_d] = dirs.size() + files.size(); return 0; case 111: // system.sysInfoMem regs[reg_a] = 0x20000000; regs[reg_c] = 0x10000; regs[reg_d] = 0x10000000; return 0; case 112: // system.sysInfoProc regs[reg_a] = 64; regs[reg_b] = 1; regs[reg_c] = 1; regs[reg_d] = 1; return 0; case 113: // system.procInfoNam putPascii(regs[reg_trg] + 0, ""); putPascii(regs[reg_trg] + 256, ""); regs[reg_a] = 0; regs[reg_c] = 0; regs[reg_d] = 0; return 0; case 114: // system.procInfoNum regs[reg_a] = 0; regs[reg_c] = 0; regs[reg_d] = 0; return 0; case 115: // system.procInfoRun regs[reg_a] = 0; regs[reg_b] = 0; regs[reg_c] = 0; return 0; case 116: // system.findProcNum regs[reg_a] = 0; return 0; case 117: // system.findProcNam regs[reg_a] = 0; return 0; case 118: // system.cpuInfo regs[reg_a] = 1; regs[reg_c] = 8086; putAsciiz(regs[reg_trg], "emulator"); return 0; case 119: // system.kernelInfo putAsciiz(regs[reg_trg], bits.lst2str(version.shPlat(), "\r\n")); return 0; case 120: // system.kernelLogo putAsciiz(regs[reg_trg], bits.lst2str(version.shLogo(0x08), "\r\n")); return 0; case 121: // system.procLive regs[reg_b] = 0; return 0; case 122: // system.uptimeInfo regs[reg_a] = 0; regs[reg_c] = (int) ((bits.getTime() / 10) % 1000000); regs[reg_d] = 100; return 0; case 123: // system.killProc regs[reg_b] = 1; return 0; } regs[reg_cip] -= 2; throw new Exception("unknown (" + opc + ") syscall"); } } class userVMfile implements Comparable { public int num; public RandomAccessFile fil; public userVMfile(int i) { num = i; } public int compareTo(userVMfile o) { if (num < o.num) { return -1; } if (num > o.num) { return +1; } return 0; } } class userVMdir implements Comparable { public int num; public File[] lst; public int pos; public userVMdir(int i) { num = i; } public int compareTo(userVMdir o) { if (num < o.num) { return -1; } if (num > o.num) { return +1; } return 0; } }