polmon: add kopy and split launch into load+run

This commit is contained in:
2025-10-06 22:51:32 +02:00
parent 8818606867
commit 84ea4d5cae

View File

@@ -164,34 +164,41 @@ uint16_t __readfile__(const char* name, uint16_t addr) {
return ret; return ret;
} }
uint16_t LaunchFile(const char* name, uint8_t len, uint8_t argc, uint16_t LoadFile(const char* name, uint8_t len, uint16_t seg) {
uint16_t* argv) {
constexpr uint16_t kSegment = 0x200;
constexpr uint16_t kAddress = 0x100; constexpr uint16_t kAddress = 0x100;
constexpr uint16_t kHeaderAddress = (kSegment << 4);
constexpr uint16_t kFlatAddress = (kSegment << 4) + kAddress;
constexpr uint16_t kArgvAddress = 0x0004;
// trampoline: // trampoline:
// call 0x100 // call 0x100
// retf // retf
// XXX: if you change kAddress, the trampoline needs to be updated // XXX: if you change kAddress, the trampoline needs to be updated
constexpr uint8_t kTrampoline[] = {0xe8, 0xfd, 0x00, 0xcb}; constexpr uint8_t kTrampoline[] = {0xe8, 0xfd, 0x00, 0xcb};
uint16_t headeraddr = (seg << 4);
uint16_t flataddr = headeraddr + kAddress;
char fatname[11]; char fatname[11];
tofatname(name, len, fatname); tofatname(name, len, fatname);
uint16_t r = __readfile__(fatname, kFlatAddress); uint16_t r = __readfile__(fatname, flataddr);
if (r) { if (r) {
memcpy(fatname + 8, "COM", 3); memcpy(fatname + 8, "COM", 3);
r = __readfile__(fatname, kFlatAddress); r = __readfile__(fatname, flataddr);
} }
if (r) { if (r) {
return r; return r;
} }
auto* ptr = reinterpret_cast<uint8_t*>(kHeaderAddress); auto* ptr = reinterpret_cast<uint8_t*>(headeraddr);
memcpy(ptr, kTrampoline, sizeof(kTrampoline)); memcpy(ptr, kTrampoline, sizeof(kTrampoline));
auto* argp = reinterpret_cast<uint16_t*>(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<uint16_t*>(headeraddr + kArgvAddress);
memcpy(argp, argv, argc * 2); memcpy(argp, argv, argc * 2);
register uint16_t ac asm("ax") = argc; 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" "xchg %%cx, %%sp \n\t"
"sti \n\t" "sti \n\t"
"push %%cx \n\t" "push %%cx \n\t"
"lcall %2,$0 \n\t" "push %2 \n\t"
"xor %%cx, %%cx \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, %%ds \n\t"
"mov %%cx, %%es \n\t" "mov %%cx, %%es \n\t"
"cli \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" "mov %%cx, %%ss \n\t"
"sti" "sti"
: "+r"(ac), "+r"(av) : "+r"(ac), "+r"(av)
: "i"(kSegment), "i"(kAddress) : "r"(seg), "i"(kAddress)
: "bx", "cx", "memory", "cc"); : "bx", "cx", "memory", "cc");
return ac; return ac;
@@ -245,13 +257,43 @@ void InstallCtrlBreak() {
vec[1] = 0; 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 ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) {
bool dump = true; bool dump = true;
for (const char* ptr = buf; *ptr;) { for (const char* ptr = buf; *ptr;) {
if (*ptr == 's') { if (*ptr == 's') {
cur_addr = 0;
ptr += 1; ptr += 1;
cur_seg = ReadUint16(ptr); cur_addr = 0;
ReadArgs(ptr, &cur_seg, 1);
} else if (*ptr == '$') { } else if (*ptr == '$') {
__basic__(); __basic__();
} else if (*ptr == 'j') { } else if (*ptr == 'j') {
@@ -262,44 +304,27 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) {
WriteUint16ln(ret); WriteUint16ln(ret);
} else if (*ptr == 'i') { } else if (*ptr == 'i') {
dump = false; dump = false;
ptr++;
uint16_t args[8]; // ought to be enough for everybody uint16_t args[8]; // ought to be enough for everybody
uint8_t nargs = 0; int nargs = ReadArgs(ptr, args, 8);
ptr++; uint16_t fun = args[0];
int fun = ReadUint8(ptr) << 8; uint16_t ret = Int80h(fun, nargs - 1, args + 1);
fun += ReadUint8(ptr);
for (; *ptr && nargs < 8;) {
if (*ptr == ' ') {
ptr++;
continue;
}
args[nargs++] = ReadUint16(ptr);
}
uint16_t ret = Int80h(fun, nargs, args);
WriteUint16ln(ret); WriteUint16ln(ret);
} else if (*ptr == 'l') { } else if (*ptr == 'l') {
dump = false; dump = false;
ClearScreen();
ptr++; 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') { } else if (*ptr == 'r') {
dump = false; dump = false;
ptr++;
uint16_t args[8]; // ought to be enough for everybody uint16_t args[8]; // ought to be enough for everybody
uint8_t nargs = 0; int nargs = ReadArgs(ptr, args, 8);
ptr++; uint16_t ret = Exec(cur_seg, nargs, args);
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);
WriteUint16ln(ret); WriteUint16ln(ret);
} else if (*ptr == 'w') { } else if (*ptr == 'w') {
dump = false; 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); __set_far_u8__(addr, cur_seg, d);
addr++; 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<uint8_t*>(args[0]);
uint16_t size = args[1];
auto* dest = reinterpret_cast<uint8_t*>(cur_addr);
memcpy(dest, src, size);
}
} else { } else {
cur_addr = ReadUint16(ptr); cur_addr = ReadUint16(ptr);
} }