diff options
author | Daniel Serpell <daniel.serpell@gmail.com> | 2020-04-28 19:14:37 -0400 |
---|---|---|
committer | Daniel Serpell <daniel.serpell@gmail.com> | 2020-04-28 19:14:37 -0400 |
commit | e3541120b2978abe01edf8780b1b1c57f5900c88 (patch) | |
tree | fe1697f047a27158c39c3871029fa02eb6f53d14 | |
parent | 5e80f6566319161a3bf9e13b8dd7ef76876fe48c (diff) | |
download | emu2-e3541120b2978abe01edf8780b1b1c57f5900c88.tar.gz |
Adds support for CP/M emulated calls.
Very old programs call CP/M compatible functions via "CALL 5".
-rw-r--r-- | src/dos.c | 24 | ||||
-rw-r--r-- | src/loader.c | 5 |
2 files changed, 29 insertions, 0 deletions
@@ -883,6 +883,26 @@ static void int21_debug(void) // DOS int void int21() { + // Check CP/M call, INT 21h from address 0x000C0 + if(cpuGetAddress(cpuGetStack(2), cpuGetStack(0)) == 0xC2) + { + debug(debug_dos, "CP/M CALL: "); + int old_ax = cpuGetAX(); + int ip = cpuGetStack(10), cs = cpuGetStack(8), flags = cpuGetStack(4); + // Fix-up registers + cpuSetAX((cpuGetCX() << 8) | (old_ax & 0xFF)); + cpuSetSP(cpuGetSP() + 6); + // Fix-up return address, interchanges segment/ip: + int stack = cpuGetAddress(cpuGetSS(), cpuGetSP()); + put16(stack, ip); + put16(stack+2, cs); + put16(stack+4, flags); + // Call ourselves + int21(); + // Restore AH + cpuSetAX( (old_ax & 0xFF00) | (cpuGetAX() & 0xFF) ); + return; + } debug(debug_int, "D-21%04X: BX=%04X\n", cpuGetAX(), cpuGetBX()); if(debug_active(debug_dos)) int21_debug(); @@ -1874,6 +1894,10 @@ void init_dos(int argc, char **argv) memory[i * 4 + 3] = 0; } + // Patch an INT 21 at address 0x000C0, this is for the CP/M emulation code + memory[0x000C0] = 0xCD; + memory[0x000C1] = 0x21; + // Init memory handling - available start address at 0x800, // ending address at 0xA0000. mcb_init(0x80,0xA000); diff --git a/src/loader.c b/src/loader.c index 172cb7d..aebbb50 100644 --- a/src/loader.c +++ b/src/loader.c @@ -279,6 +279,11 @@ uint16_t create_PSP(const char *cmdline, const char *environment, dosPSP[1] = 0x20; dosPSP[2] = 0x00; // 02: memory end segment dosPSP[3] = 0x00; // + dosPSP[5] = 0x9A; // 05: FAR call to CP/M entry point: + dosPSP[6] = 0xF0; // CALL FAR F01D:FEF0 + dosPSP[7] = 0xFE; // this jumps to 0xC0, where an + dosPSP[8] = 0x1D; // INT 21h is patched. + dosPSP[9] = 0xF0; dosPSP[44] = 0xFF & env_seg; // 2C: environment segment dosPSP[45] = 0xFF & (env_seg >> 8); // dosPSP[80] = 0xCD; // 50: INT 21h / RETF |