1;
2; The code in this file complete the spint calls
3;
4
5spint	struc
6; union REGS
7spint_ax	dw	1
8spint_bx	dw	1
9spint_cx	dw	1
10spint_dx	dw	1
11spint_si	dw	1
12spint_di	dw	1
13spint_cflag	dw	1
14; struct SREGS
15spint_es	dw	1
16spint_cs	dw	1
17spint_ss	dw	1
18spint_ds	dw	1
19; int intno
20spint_intno	dw	1
21; int done
22spint_done	dw	1
23; int rc
24spint_rc	dw	1
25;
26spint	ends
27
28
29ENTER	MACRO
30	; Begin enter
31	push	bp
32	mov	bp,sp
33
34	push	ax
35	push	bx
36	push	cx
37	push	dx
38	push	bp
39	push	di
40	push	si
41	push	ds
42	push	es
43	pushf
44
45	mov	cs:start_sp, sp
46	mov	cs:start_ss, ss
47	; End enter
48	ENDM
49
50LEAVE	MACRO
51	; Begin leave
52	cli
53	mov	sp, cs:start_sp
54	mov	ss, cs:start_ss
55	sti
56
57	popf
58	pop	es
59	pop	ds
60	pop	si
61	pop	di
62	pop	bp
63	pop	dx
64	pop	cx
65	pop	bx
66	pop	ax
67
68	mov	sp,bp
69	pop	bp
70	ret
71	; End leave
72	ENDM
73
74GETREGS	MACRO	wherefrom
75	mov	si, wherefrom
76	mov	spint_segment, ds
77	mov	spint_offset, si
78
79	mov	ax, spint_ax[si]
80	mov	bx, spint_bx[si]
81	mov	cx, spint_cx[si]
82	mov	dx, spint_dx[si]
83	; XXX mov	si, spint_si[si]
84	mov	di, spint_di[si]
85	mov	es, spint_es[si]
86	; Now, need to do DS, SI
87	push	spint_ds[si]
88	mov	si, spint_si[si]
89	pop	ds
90	ENDM
91
92
93SETREGS	MACRO
94	mov	cs:old_si, si
95	mov	cs:old_ds, ds
96
97	mov	ds, cs:spint_segment
98	mov	si, cs:spint_offset
99
100	mov	spint_ax[si], ax
101	mov	spint_bx[si], bx
102	mov	spint_cx[si], cx
103	mov	spint_dx[si], dx
104
105	mov	spint_si[si], si
106	mov	spint_di[si], di
107
108	mov	spint_cs[si], cs
109	mov	spint_ds[si], ds
110	mov	spint_es[si], es
111	mov	spint_ss[si], ss
112	; now, need to do SI, DS
113	mov	ax, old_si
114	mov	spint_si[si], ax
115	mov	ax, old_ds
116	mov	spint_ds[si], ax
117	ENDM
118
119
120_TEXT	segment	byte public 'CODE'
121_TEXT	ends
122
123_DATA	segment	word public 'DATA'
124_DATA	ends
125
126CONST	segment	word public 'CONST'
127CONST	ends
128
129_BSS	segment word public 'BSS'
130_BSS	ends
131
132DGROUP	group	CONST, _BSS, _DATA
133
134	assume	cs:_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP
135
136_TEXT	segment
137
138start_sp	dw	1 dup (?)	; For use in our 'longjmp'
139start_ss	dw	1 dup (?)	; For use in our 'longjmp'
140
141spint_segment	dw	1 dup (?)	; Segment of spawn control block
142spint_offset	dw	1 dup (?)	; Offset of spawn control block
143
144old_si		dw	1 dup (?)	; SI of interrupt issuer (temporary)
145old_ds		dw	1 dup (?)	; DS of interrupt issuer (temporary)
146
147issuer_ss	dw	1 dup (?)	; ss of person who called us (permanent)
148issuer_sp	dw	1 dup (?)	; sp of person who called us (permanent)
149
150int21_stack	db	100 dup (?)	; Stack for int21.
151
152;
153; _spint_int gets control on an interrupt.  It switches the stack
154; and does a 'return' from _spint_start.
155;
156	public	__spint_int
157
158__spint_int	proc	near
159	mov	cs:issuer_sp, sp
160	mov	cs:issuer_ss, ss
161	sti
162
163	SETREGS
164
165	LEAVE
166__spint_int	endp
167
168;
169; _spint_start issues the dos interrupt after setting up the passed
170; registers.  When control returns to it, it sets spint->done to non-zero.
171;
172	public	__spint_start
173
174__spint_start	proc	near
175	ENTER
176
177	GETREGS	4[bp]
178
179	; Now, switch to a different (short) stack.  This is so
180	; that our games won't mess up the stack int 21 (hardware and,
181	; possibly, software) stores things on.
182
183	cli
184	mov	cs:int21_stack, cs
185	mov	ss, cs:int21_stack
186	mov	sp, offset int21_stack
187	add	sp, (length int21_stack) - 4
188	sti
189
190	int	21H		; Issue DOS interrupt
191
192	SETREGS
193
194	mov	ds, cs:spint_segment
195	mov	si, cs:spint_offset
196	mov	spint_done[si], 1	; We are done
197
198	LEAVE
199__spint_start	endp
200
201;
202; After _spint_int has faked a return from start_spawn, we come here to
203; return to the interrupt issuer.
204;
205	public	__spint_continue
206
207__spint_continue	proc	near
208	ENTER
209
210	GETREGS	4[bp]
211
212	mov	sp, cs:issuer_sp		; Restore SP
213	mov	ss, cs:issuer_ss		; Restore SS
214
215	iret
216__spint_continue	endp
217
218_TEXT	ends
219
220	end
221