diff --git a/src/polmon.cc b/src/polmon.cc index c23642c..4dcaff3 100644 --- a/src/polmon.cc +++ b/src/polmon.cc @@ -164,34 +164,41 @@ uint16_t __readfile__(const char* name, uint16_t addr) { return ret; } -uint16_t LaunchFile(const char* name, uint8_t len, uint8_t argc, - uint16_t* argv) { - constexpr uint16_t kSegment = 0x200; +uint16_t LoadFile(const char* name, uint8_t len, uint16_t seg) { constexpr uint16_t kAddress = 0x100; - constexpr uint16_t kHeaderAddress = (kSegment << 4); - constexpr uint16_t kFlatAddress = (kSegment << 4) + kAddress; - constexpr uint16_t kArgvAddress = 0x0004; // trampoline: // call 0x100 // retf // XXX: if you change kAddress, the trampoline needs to be updated constexpr uint8_t kTrampoline[] = {0xe8, 0xfd, 0x00, 0xcb}; + uint16_t headeraddr = (seg << 4); + uint16_t flataddr = headeraddr + kAddress; + char fatname[11]; tofatname(name, len, fatname); - uint16_t r = __readfile__(fatname, kFlatAddress); + uint16_t r = __readfile__(fatname, flataddr); if (r) { memcpy(fatname + 8, "COM", 3); - r = __readfile__(fatname, kFlatAddress); + r = __readfile__(fatname, flataddr); } if (r) { return r; } - auto* ptr = reinterpret_cast(kHeaderAddress); + auto* ptr = reinterpret_cast(headeraddr); memcpy(ptr, kTrampoline, sizeof(kTrampoline)); - auto* argp = reinterpret_cast(kHeaderAddress + kArgvAddress); + + return 0; +} + +uint16_t Exec(uint16_t seg, uint8_t argc, uint16_t* argv) { + constexpr uint16_t kAddress = 0x100; + constexpr uint16_t kArgvAddress = 0x0004; + + uint16_t headeraddr = (seg << 4); + auto* argp = reinterpret_cast(headeraddr + kArgvAddress); memcpy(argp, argv, argc * 2); register uint16_t ac asm("ax") = argc; @@ -205,8 +212,13 @@ uint16_t LaunchFile(const char* name, uint8_t len, uint8_t argc, "xchg %%cx, %%sp \n\t" "sti \n\t" "push %%cx \n\t" - "lcall %2,$0 \n\t" + "push %2 \n\t" "xor %%cx, %%cx \n\t" + "push %%cx \n\t" + "mov %%sp, %%bx \n\t" + "lcall *(%%bx) \n\t" + "pop %%cx \n\t" + "pop %%dx \n\t" "mov %%cx, %%ds \n\t" "mov %%cx, %%es \n\t" "cli \n\t" @@ -214,7 +226,7 @@ uint16_t LaunchFile(const char* name, uint8_t len, uint8_t argc, "mov %%cx, %%ss \n\t" "sti" : "+r"(ac), "+r"(av) - : "i"(kSegment), "i"(kAddress) + : "r"(seg), "i"(kAddress) : "bx", "cx", "memory", "cc"); return ac; @@ -245,13 +257,43 @@ void InstallCtrlBreak() { vec[1] = 0; } +// j +// w [u8]* +// i [u16] [u16]* +// r str [u16]* +// k u16 u16 u16 + +int ReadArgs(const char*& ptr, uint16_t* args, int size) { + int nargs = 0; + while (*ptr && nargs < size) { + if (*ptr == ' ') { + ptr += 1; + continue; + } + args[nargs] = ReadUint16(ptr); + nargs += 1; + } + return nargs; +} + +int ReadString(const char*& ptr, const char*& str) { + while (*ptr == ' ') { + ptr++; + } + str = ptr; + int l; + for (l = 0; *ptr && *ptr != ' '; l++, ptr++) { + } + return l; +} + bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { bool dump = true; for (const char* ptr = buf; *ptr;) { if (*ptr == 's') { - cur_addr = 0; ptr += 1; - cur_seg = ReadUint16(ptr); + cur_addr = 0; + ReadArgs(ptr, &cur_seg, 1); } else if (*ptr == '$') { __basic__(); } else if (*ptr == 'j') { @@ -262,44 +304,27 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { WriteUint16ln(ret); } else if (*ptr == 'i') { dump = false; - uint16_t args[8]; // ought to be enough for everybody - uint8_t nargs = 0; ptr++; - int fun = ReadUint8(ptr) << 8; - fun += ReadUint8(ptr); - for (; *ptr && nargs < 8;) { - if (*ptr == ' ') { - ptr++; - continue; - } - args[nargs++] = ReadUint16(ptr); - } - uint16_t ret = Int80h(fun, nargs, args); + uint16_t args[8]; // ought to be enough for everybody + int nargs = ReadArgs(ptr, args, 8); + uint16_t fun = args[0]; + uint16_t ret = Int80h(fun, nargs - 1, args + 1); WriteUint16ln(ret); } else if (*ptr == 'l') { dump = false; - ClearScreen(); ptr++; + const char* fname; + int l = ReadString(ptr, fname); + uint16_t ret = LoadFile(fname, l, cur_seg); + if (ret) { + WriteUint16ln(ret); + } } else if (*ptr == 'r') { dump = false; - uint16_t args[8]; // ought to be enough for everybody - uint8_t nargs = 0; ptr++; - while (*ptr == ' ') { - ptr++; - } - const char* fname = ptr; - int l; - for (l = 0; *ptr && *ptr != ' '; l++, ptr++) { - } - for (; *ptr && nargs < 8;) { - if (*ptr == ' ') { - ptr++; - continue; - } - args[nargs++] = ReadUint16(ptr); - } - uint16_t ret = LaunchFile(fname, l, nargs, args); + uint16_t args[8]; // ought to be enough for everybody + int nargs = ReadArgs(ptr, args, 8); + uint16_t ret = Exec(cur_seg, nargs, args); WriteUint16ln(ret); } else if (*ptr == 'w') { dump = false; @@ -314,6 +339,17 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { __set_far_u8__(addr, cur_seg, d); addr++; } + } else if (*ptr == 'k') { + dump = false; + ptr++; + uint16_t args[2]; + // TODO: implement copy on non-zero segments + if (cur_seg == 0 && ReadArgs(ptr, args, 2) == 2) { + auto* src = reinterpret_cast(args[0]); + uint16_t size = args[1]; + auto* dest = reinterpret_cast(cur_addr); + memcpy(dest, src, size); + } } else { cur_addr = ReadUint16(ptr); }