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;
}
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<uint8_t*>(kHeaderAddress);
auto* ptr = reinterpret_cast<uint8_t*>(headeraddr);
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);
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<uint8_t*>(args[0]);
uint16_t size = args[1];
auto* dest = reinterpret_cast<uint8_t*>(cur_addr);
memcpy(dest, src, size);
}
} else {
cur_addr = ReadUint16(ptr);
}