int int_no; /* Which interrupt to wait on */
int done; /* Are we done, or just took an interrupt? */
int rc; /* return code */
-} Spawn;
+} Spint;
;
-; The code in this file complete the spawn_int calls
+; The code in this file complete the spint calls
;
-spawn struc
+spint struc
; union REGS
-spawn_ax dw 1
-spawn_bx dw 1
-spawn_cx dw 1
-spawn_dx dw 1
-spawn_si dw 1
-spawn_di dw 1
-spawn_cflag dw 1
+spint_ax dw 1
+spint_bx dw 1
+spint_cx dw 1
+spint_dx dw 1
+spint_si dw 1
+spint_di dw 1
+spint_cflag dw 1
; struct SREGS
-spawn_es dw 1
-spawn_cs dw 1
-spawn_ss dw 1
-spawn_ds dw 1
+spint_es dw 1
+spint_cs dw 1
+spint_ss dw 1
+spint_ds dw 1
; int intno
-spawn_intno dw 1
+spint_intno dw 1
; int done
-spawn_done dw 1
+spint_done dw 1
; int rc
-spawn_rc dw 1
+spint_rc dw 1
;
-spawn ends
+spint ends
ENTER MACRO
push es
pushf
- mov cs:save_sp, sp
- mov cs:save_ss, ss
+ mov cs:start_sp, sp
+ mov cs:start_ss, ss
; End enter
ENDM
LEAVE MACRO
; Begin leave
- mov sp, cs:save_sp
- mov ss, cs:save_ss
+ cli
+ mov sp, cs:start_sp
+ mov ss, cs:start_ss
+ sti
popf
pop es
GETREGS MACRO wherefrom
mov si, wherefrom
- mov spawn_segment, ds
- mov spawn_offset, si
-
- mov ax, spawn_ax[si]
- mov bx, spawn_bx[si]
- mov cx, spawn_cx[si]
- mov dx, spawn_dx[si]
- ; XXX mov si, spawn_si[si]
- mov di, spawn_di[si]
- mov es, spawn_es[si]
+ mov spint_segment, ds
+ mov spint_offset, si
+
+ mov ax, spint_ax[si]
+ mov bx, spint_bx[si]
+ mov cx, spint_cx[si]
+ mov dx, spint_dx[si]
+ ; XXX mov si, spint_si[si]
+ mov di, spint_di[si]
+ mov es, spint_es[si]
; Now, need to do DS, SI
- push spawn_ds[si]
- mov si, spawn_si[si]
+ push spint_ds[si]
+ mov si, spint_si[si]
pop ds
ENDM
mov cs:old_si, si
mov cs:old_ds, ds
- mov ds, cs:spawn_segment
- mov si, cs:spawn_offset
+ mov ds, cs:spint_segment
+ mov si, cs:spint_offset
- mov spawn_ax[si], ax
- mov spawn_bx[si], bx
- mov spawn_cx[si], cx
- mov spawn_dx[si], dx
+ mov spint_ax[si], ax
+ mov spint_bx[si], bx
+ mov spint_cx[si], cx
+ mov spint_dx[si], dx
- mov spawn_si[si], si
- mov spawn_di[si], di
+ mov spint_si[si], si
+ mov spint_di[si], di
- mov spawn_cs[si], cs
- mov spawn_ds[si], ds
- mov spawn_es[si], es
- mov spawn_ss[si], ss
+ mov spint_cs[si], cs
+ mov spint_ds[si], ds
+ mov spint_es[si], es
+ mov spint_ss[si], ss
; now, need to do SI, DS
mov ax, old_si
- mov spawn_si[si], ax
+ mov spint_si[si], ax
mov ax, old_ds
- mov spawn_ds[si], ax
+ mov spint_ds[si], ax
ENDM
_TEXT segment
-save_sp dw 1 ; For use in our 'longjmp'
-save_ss dw 1 ; For use in our 'longjmp'
+start_sp dw 1 dup (?) ; For use in our 'longjmp'
+start_ss dw 1 dup (?) ; For use in our 'longjmp'
-spawn_segment dw 1 ; Segment of spawn control block
-spawn_offset dw 1 ; Offset of spawn control block
+spint_segment dw 1 dup (?) ; Segment of spawn control block
+spint_offset dw 1 dup (?) ; Offset of spawn control block
-old_si dw 1 ; SI of interrupt issuer (temporary)
-old_ds dw 1 ; DS of interrupt issuer (temporary)
+old_si dw 1 dup (?) ; SI of interrupt issuer (temporary)
+old_ds dw 1 dup (?) ; DS of interrupt issuer (temporary)
-issuer_sp dw 1 ; sp of person who called us (permanent)
+issuer_ss dw 1 dup (?) ; ss of person who called us (permanent)
+issuer_sp dw 1 dup (?) ; sp of person who called us (permanent)
+
+int21_stack db 100 dup (?) ; Stack for int21.
;
-; int_spawn gets control on an interrupt. It switches the stack
-; and does a 'return' from start_spawn.
+; _spint_int gets control on an interrupt. It switches the stack
+; and does a 'return' from _spint_start.
;
- public _int_spawn
+ public __spint_int
-_int_spawn proc near
+__spint_int proc near
mov cs:issuer_sp, sp
+ mov cs:issuer_ss, ss
+ sti
SETREGS
LEAVE
-_int_spawn endp
+__spint_int endp
;
-; start_spawn issues the dos interrupt after setting up the passed
-; registers. When control returns to it, it sets spawn->done to non-zero.
+; _spint_start issues the dos interrupt after setting up the passed
+; registers. When control returns to it, it sets spint->done to non-zero.
;
- public _start_spawn
+ public __spint_start
-_start_spawn proc near
+__spint_start proc near
ENTER
GETREGS 4[bp]
+ ; Now, switch to a different (short) stack. This is so
+ ; that our games won't mess up the stack int 21 (hardware and,
+ ; possibly, software) stores things on.
+
+ cli
+ mov cs:int21_stack, cs
+ mov ss, cs:int21_stack
+ mov sp, offset int21_stack
+ add sp, (length int21_stack) - 4
+ sti
+
int 21H ; Issue DOS interrupt
SETREGS
- mov ds, cs:spawn_segment
- mov si, cs:spawn_offset
- mov spawn_done[si], 1 ; We are done
+ mov ds, cs:spint_segment
+ mov si, cs:spint_offset
+ mov spint_done[si], 1 ; We are done
LEAVE
-_start_spawn endp
+__spint_start endp
;
-; After int_spawn has faked a return from start_spawn, we come here to
+; After _spint_int has faked a return from start_spawn, we come here to
; return to the interrupt issuer.
;
- public _continue_spawn
+ public __spint_continue
-_continue_spawn proc near
+__spint_continue proc near
ENTER
GETREGS 4[bp]
mov sp, cs:issuer_sp ; Restore SP
+ mov ss, cs:issuer_ss ; Restore SS
iret
-_continue_spawn endp
+__spint_continue endp
_TEXT ends
fcb2_ptr_segment; /* Segment of FCB 2 */
} ExecList;
+
+static int int_offset, int_segment;
+
+
void
-do_spawn(command, spawn)
+spint_finish(spint)
+Spint *spint;
+{
+ union REGS regs;
+ struct SREGS sregs;
+
+ if (spint->done == 0) {
+ return; /* Not done yet */
+ }
+
+ /*
+ * Restore old interrupt handler.
+ */
+
+ regs.h.ah = 0x25;
+ regs.h.al = spint->int_no;
+ regs.x.dx = int_offset;
+ sregs.ds = int_segment;
+ intdosx(®s, ®s, &sregs);
+
+ if (spint->regs.x.cflag) {
+ fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax);
+ spint->done = 1;
+ spint->rc = 99;
+ return;
+ }
+
+ regs.h.ah = 0x4d; /* Get return code */
+
+ intdos(®s, ®s);
+
+ spint->rc = regs.x.ax;
+}
+
+void
+spint_continue(spint)
+Spint *spint;
+{
+ _spint_continue(spint); /* Return to caller */
+ spint_finish(spint);
+}
+
+
+void
+spint_start(command, spint)
char *command;
-Spawn *spawn;
+Spint *spint;
{
ExecList mylist;
char *comspec;
- void int_spawn();
- int int_offset, int_segment;
+ void _spint_int();
+ union REGS regs;
+ struct SREGS sregs;
/*
* Get comspec.
comspec = getenv("COMSPEC");
if (comspec == 0) { /* Can't find where command.com is */
fprintf(stderr, "Unable to find COMSPEC in the environment.");
- spawn->done = 1;
- spawn->rc = 99; /* XXX */
+ spint->done = 1;
+ spint->rc = 99; /* XXX */
return;
}
* Now, hook up our interrupt routine.
*/
- spawn->regs.h.ah = 0x35;
- spawn->regs.h.al = spawn->int_no;
- intdosx(&spawn->regs, &spawn->regs, &spawn->sregs);
+ regs.h.ah = 0x35;
+ regs.h.al = spint->int_no;
+ intdosx(®s, ®s, &sregs);
/* Save old routine */
- int_offset = spawn->regs.x.bx;
- int_segment = spawn->sregs.es;
+ int_offset = regs.x.bx;
+ int_segment = sregs.es;
- spawn->regs.h.ah = 0x25;
- spawn->regs.h.al = spawn->int_no;
- spawn->regs.x.dx = (int) int_spawn;
- segread(&spawn->sregs);
- spawn->sregs.ds = spawn->sregs.cs;
- intdosx(&spawn->regs, &spawn->regs, &spawn->sregs);
+ regs.h.ah = 0x25;
+ regs.h.al = spint->int_no;
+ regs.x.dx = (int) _spint_int;
+ segread(&sregs);
+ sregs.ds = sregs.cs;
+ intdosx(®s, ®s, &sregs);
/*
* Read in segment registers.
*/
- segread(&spawn->sregs);
+ segread(&spint->sregs);
/*
* Set up registers for the EXEC call.
*/
- spawn->regs.h.ah = 0x4b;
- spawn->regs.h.al = 0;
- spawn->regs.x.dx = (int) comspec;
- spawn->sregs.es = spawn->sregs.ds; /* Superfluous, probably */
- spawn->regs.x.bx = (int) &mylist;
+ spint->regs.h.ah = 0x4b;
+ spint->regs.h.al = 0;
+ spint->regs.x.dx = (int) comspec;
+ spint->sregs.es = spint->sregs.ds; /* Superfluous, probably */
+ spint->regs.x.bx = (int) &mylist;
/*
* Set up EXEC parameter list.
ClearElement(mylist);
mylist.cmd_ptr_offset = (int) command;
- mylist.cmd_ptr_segment = spawn->sregs.ds;
+ mylist.cmd_ptr_segment = spint->sregs.ds;
mylist.fcb1_ptr_offset = PSP_FCB1;
mylist.fcb1_ptr_segment = _psp;
mylist.fcb2_ptr_offset = PSP_FCB2;
/*
* Call to assembly language routine to actually set up for
- * the spawn.
- */
-
- start_spawn(spawn);
- spawn->done = 1; /* XXX */
-
- if (spawn->done == 0) {
- return; /* Not done yet */
- }
-
- if (spawn->regs.x.cflag) {
- fprintf(stderr, "0x%x return code from EXEC.\n", spawn->regs.x.ax);
- spawn->done = 1;
- spawn->rc = 99;
- return;
- }
-
- spawn->regs.h.ah = 0x4d; /* Get return code */
-
- intdos(&spawn->regs, &spawn->regs);
-
- spawn->rc = spawn->regs.x.ax;
-
- /*
- * Restore old interrupt handler.
+ * the spint.
*/
- spawn->regs.h.ah = 0x25;
- spawn->regs.h.al = spawn->int_no;
- spawn->regs.x.dx = int_offset;
- spawn->sregs.ds = int_segment;
- intdosx(&spawn->regs, &spawn->regs, &spawn->sregs);
-}
-\f
-/* XXX */
-
-#define INTERRUPT_NUMBER 73
-
-main(argc, argv, envp)
-int argc; /* Number of passed arguments */
-char *argv[]; /* Arguments passed */
-char *envp[]; /* Inherited environment */
-{
- Spawn spawned;
- static char command[256];
-
- ClearElement(spawned);
- spawned.int_no = INTERRUPT_NUMBER;
- if (argc == 1) {
- command[0] = 0;
- } else {
- char *cmdptr;
- int length;
-
- argc--;
- argv++;
- strcpy(command, " /c");
- cmdptr = command+strlen(command);
- while (argc) {
- if ((cmdptr+strlen(*argv)) >= (command+sizeof command)) {
- fprintf(stderr, "Argument list too long at argument *%s*.\n",
- *argv);
- return 0;
- }
- *cmdptr++ = ' '; /* Blank separators */
- strcpy(cmdptr, *argv);
- cmdptr += strlen(cmdptr);
- argc--;
- argv++;
- }
- length = strlen(command)-1;
- if (length < 0) {
- length = 0;
- }
- command[0] = length;
- }
+ _spint_start(spint);
- /*
- * do_spawn() returns when either the command has finished, or when
- * the required interrupt comes in. In the latter case, the appropriate
- * thing to do is to process the interrupt, and then return to
- * the interrupt issuer by calling continue_spawn().
- */
- do_spawn(command, &spawned);
- while (spawned.done == 0) {
- /* Process request */
- spawned.regs.h.al = 0;
- spawned.regs.x.cflag = 0; /* No errors (yet) */
- switch (spawned.regs.h.ah) {
- case 1: /* Add */
- spawned.regs.x.bx += spawned.regs.x.cx;
- break;
- case 2: /* Subtract */
- spawned.regs.x.bx -= spawned.regs.x.cx;
- break;
- case 3: /* Multiply */
- spawned.regs.x.bx *= spawned.regs.x.cx;
- break;
- case 4: /* Divide */
- spawned.regs.x.bx /= spawned.regs.x.cx;
- break;
- default:
- spawned.regs.h.al = -1; /* Error */
- spawned.regs.x.cflag = 1;
- break;
- }
- spawned.regs.h.ah = 0; /* We saw this */
- continue_spawn(&spawned);
- }
- if (spawned.rc != 0) {
- fprintf(stderr, "Process generated a return code of 0x%x.\n",
- spawned.rc);
- }
+ spint_finish(spint);
}
segread(&segregs); /* read the current segment register */
scrwait();
- movedata(segregs.ds, source, scrseg(), offset, length);
+ movedata(segregs.ds, source, scrseg(), sizeof *source*offset,
+ sizeof *source*length);
}
static void
segread(&segregs); /* read the current segment register */
scrwait();
- movedata(scrseg(), 0, segregs.ds, buffer, scrseg(), 0, crt_cols*crt_lins*2);
+ movedata(scrseg(), 0, segregs.ds, buffer, crt_cols*crt_lins*2);
}
static void
scrrest(buffer)
ScreenBuffer *buffer;
{
- scrwrite(buffer, 2*crt_cols*crt_lins, 0);
+ scrwrite(buffer, crt_cols*crt_lins, 0);
}
\f
static void
TryToSend()
{
-#define STANDOUT 0x0a
+#define STANDOUT 0x0a /* Highlighted mode */
#define NORMAL 0x02 /* Normal mode */
-
-#define DoAttribute(a) if (IsHighlightedAttr(a)) { \
- a = STANDOUT; \
- } else { \
- a = NORMAL; \
- } \
- if (IsNonDisplayAttr(a)) { \
- a = 0; /* zero == don't display */ \
- } \
- if (!FormattedScreen()) { \
- a = 1; /* one ==> do display on unformatted */\
+#define NONDISPLAY 0x00 /* Don't display */
+
+#define DoAttribute(a) \
+ if (screenIsFormatted) { \
+ if (IsNonDisplayAttr(a)) { \
+ a = NONDISPLAY; /* don't display */ \
+ } else if (IsHighlightedAttr(a)) { \
+ a = STANDOUT; \
+ } else { \
+ a = NORMAL; \
+ } \
+ } else { \
+ a = NORMAL; /* do display on unformatted */\
}
ScreenImage *p, *upper;
ScreenBuffer *sp;
int fieldattr; /* spends most of its time == 0 or 1 */
+ int screenIsFormatted = FormattedScreen();
/* OK. We want to do this a quickly as possible. So, we assume we
* only need to go from Lowest to Highest. However, if we find a
* In particular, we separate out the two cases from the beginning.
*/
if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) {
- register int columnsleft;
-
sp = &Screen[Lowest];
p = &Host[Lowest];
upper = &Host[Highest];
fieldattr = FieldAttributes(Lowest);
DoAttribute(fieldattr); /* Set standout, non-display status */
- columnsleft = NumberColumns-ScreenLineOffset(p-Host);
while (p <= upper) {
if (IsStartFieldPointer(p)) { /* New field? */
TryToSend(); /* Recurse */
return;
} else if (fieldattr) { /* Should we display? */
- sp->data = disp_asc[p->data]; /* Display translated data */
- sp->attr = fieldattr;
+ /* Display translated data */
+ sp->data = disp_asc[GetHostPointer(p)];
} else {
sp->data = ' ';
- sp->attr = NORMAL;
}
- /* If the physical screen is larger than what we
- * are using, we need to make sure that each line
- * starts at the beginning of the line. Otherwise,
- * we will just string all the lines together.
- */
+ sp->attr = fieldattr;
p++;
sp++;
}
if (IsStartFieldPointer(p)) { /* New field? */
fieldattr = FieldAttributesPointer(p); /* Get attributes */
DoAttribute(fieldattr); /* Set standout, non-display */
+ }
+ if (fieldattr) { /* Should we display? */
+ /* Display translated data */
+ sp->data = disp_asc[GetHostPointer(p)];
} else {
- if (fieldattr) { /* Should we display? */
- /* Display translated data */
- sp->data = disp_asc[p->data];
- sp->attr = fieldattr;
- } else {
- sp->data = ' ';
- sp->attr = NORMAL;
- }
+ sp->data = ' ';
}
- /* If the physical screen is larger than what we
- * are using, we need to make sure that each line
- * starts at the beginning of the line. Otherwise,
- * we will just string all the lines together.
- */
+ sp->attr = fieldattr;
p++;
sp++;
}
}
terminalCursorAddress = CorrectTerminalCursor();
- scrwrite(Screen+Lowest, sizeof Screen[0]*(Highest-Lowest), Lowest);
+ /*
+ * We might be here just to update the cursor address.
+ */
+ if (Highest >= Lowest) {
+ scrwrite(Screen+Lowest, (1+Highest-Lowest), Lowest);
+ }
setcursor(ScreenLine(terminalCursorAddress),
ScreenLineOffset(terminalCursorAddress), 0);
Lowest = HighestScreen()+1;