aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Serpell <daniel.serpell@gmail.com>2020-04-28 19:14:37 -0400
committerDaniel Serpell <daniel.serpell@gmail.com>2020-04-28 19:14:37 -0400
commite3541120b2978abe01edf8780b1b1c57f5900c88 (patch)
treefe1697f047a27158c39c3871029fa02eb6f53d14
parent5e80f6566319161a3bf9e13b8dd7ef76876fe48c (diff)
downloademu2-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.c24
-rw-r--r--src/loader.c5
2 files changed, 29 insertions, 0 deletions
diff --git a/src/dos.c b/src/dos.c
index 74c580a..c5c9830 100644
--- a/src/dos.c
+++ b/src/dos.c
@@ -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
Un proyecto texto-plano.xyz