-
Notifications
You must be signed in to change notification settings - Fork 2
/
AMIPOPUP.ASM
263 lines (234 loc) · 6.29 KB
/
AMIPOPUP.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
;-----------------------------------------------------------------------
; AMIPOPUP.ASM Public Domain 1993 Ralf Brown
; You may do with this software whatever you want, but
; common courtesy dictates that you not remove my name
; from it.
;
; code to handle a TSRs popup hotkey
;
; Version 0.92
; LastEdit: 2/21/93
;-----------------------------------------------------------------------
__DEFAULT_MODEL__ equ __TINY__
INCLUDE AMIS.MAC
;-----------------------------------------------------------------------
LOCAL_STACK_SIZE equ 128 ; size of local stack in bytes
;-----------------------------------------------------------------------
TSRgroup@ byte
;-----------------------------------------------------------------------
; Put the resident code into its own segment so that all the offsets are
; proper for the new location after copying it into a UMB or down into
; the PSP.
;
TSRcode@ byte
extrn TSR_MAIN:near,TSR_SHUTDOWN:near
extrn TSR_SAVE_SCREEN:near,TSR_FRAMED_WINDOW:near,TSR_RESTORE_SCREEN:near
extrn TSR_INT1B_HANDLER:far,TSR_INT23_HANDLER:far,TSR_INT24_HANDLER:far
;-----------------------------------------------------------------------
; TSR's initialized data storage
;
TSRdata@
disk_TSR_busy label word ; allow both to be tested in one operation
public $AMIS$DISK_BUSY
$AMIS$DISK_BUSY db 0
TSR_activated db 0
public $AMIS$WANT_POPUP
$AMIS$WANT_POPUP db 0
public $AMIS$WANT_SHUTDOWN
$AMIS$WANT_SHUTDOWN db 0
public $AMIS$POPUP_INT28
$AMIS$POPUP_INT28 db 0
errorinfo DPL <>
TSRdataEnd@
;-----------------------------------------------------------------------
; TSR's uninitialized data storage
;
TSRbss@
INDOS_PTR dd ?
CRITERR_PTR dd ?
interrupted_DTA dd ?
interrupted_PSP dw ?
interrupted_SP dw ?
interrupted_SS dw ?
local_stack db LOCAL_STACK_SIZE dup (?)
local_stack_bottom label byte
TSRbssEnd@
;-----------------------------------------------------------------------
; requires DS = TGROUP and interrupts enabled on entry; may destroy BX
;
public $AMIS$POPUP
$AMIS$POPUP proc near
mov TSR_activated,1 ; yes, we are now active
mov $AMIS$WANT_POPUP,0 ; and we are finally popping up
;
; switch to a local stack so that we are assured of enough stack space
;
push ax
mov interrupted_SS,ss
mov interrupted_SP,sp
mov ax,cs
cli
mov ss,ax ; switch stack
ASSUME SS:TGROUP
mov sp,offset RESIDENT_CODE:local_stack_bottom
sti
push es
push di
push si
push bp
push dx
push cx
push bx
;
; switch to our own PSP and store current DTA and extended error info
;
mov ah,51h
int 21h ; get PSP of interrupted program
mov interrupted_PSP,bx
mov errorinfo.dpl_pid,bx
mov bx,cs
mov ah,50h ; set PSP to our own
int 21h
mov ah,2Fh ; get DTA
int 21h
ASSUME ES:NOTHING
mov word ptr interrupted_DTA,bx
mov word ptr interrupted_DTA+2,es
mov ah,59h
xor bx,bx
int 21h
ASSUME ES:NOTHING
mov errorinfo.dpl_ax,ax
mov errorinfo.dpl_bx,bx
mov errorinfo.dpl_cx,cx
mov errorinfo.dpl_di,di
mov errorinfo.dpl_es,es
GRAB_INTERRUPT 1Bh,TSR_INT1B_HANDLER
GRAB_INTERRUPT 23h,TSR_INT23_HANDLER
GRAB_INTERRUPT 24h,TSR_INT24_HANDLER
mov al,0
xchg al,$AMIS$WANT_SHUTDOWN ; get and clear shutdown flag
or al,al ; was it set?
jz do_popup ; if not, regular popup
call TSR_SHUTDOWN
jmp short popup_done
do_popup:
call TSR_SAVE_SCREEN
call TSR_FRAMED_WINDOW
call TSR_MAIN ; the actual guts of the TSR
call TSR_RESTORE_SCREEN
popup_done:
RESTORE_INTERRUPT 1Bh
RESTORE_INTERRUPT 23h
RESTORE_INTERRUPT 24h
;
; restore the original PSP, DTA, and extended error info
;
mov bx,interrupted_PSP
mov ah,50h ; set PSP back to stored value
int 21h
push ds
lds dx,interrupted_DTA
ASSUME DS:NOTHING
mov ah,1Ah ; set DTA back to stored value
int 21h
pop ds ; restore DS
ASSUME DS:TGROUP
mov dx,offset TGROUP:errorinfo
mov ax,5D0Ah ; set extended error information
int 21h
pop bx
pop cx
pop dx
pop bp
pop si
pop di
pop es
;
; finally, switch back to original stack
;
cli
mov ss,interrupted_SS
ASSUME SS:NOTHING
mov sp,interrupted_SP
sti
pop ax
mov TSR_activated,0 ; no longer popped up, so OK to pop again
ret
$AMIS$POPUP endp
;-----------------------------------------------------------------------
public $AMIS$ATTEMPT_POPUP
$AMIS$ATTEMPT_POPUP proc near
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
mov $AMIS$WANT_POPUP,1 ; remember that a popup was requested
;; fall through to $AMIS$TRY_POPUP ;;
$AMIS$ATTEMPT_POPUP endp
public $AMIS$TRY_POPUP
$AMIS$TRY_POPUP proc near
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
pushf ; remember current flags
sti ; OK to interrupt
cmp $AMIS$WANT_POPUP,0
je try_popup_done
cmp disk_TSR_busy,0 ; check whether disk busy or popped up
jnz try_popup_done ; can't popup if either flag set
push ds
push bx
lds bx,INDOS_ptr ; check InDOS flag
ASSUME DS:NOTHING
cmp byte ptr [bx],1
jb try_popup_1 ; if zero, DOS is probably idle
ja try_popup_2 ; if not 0 or 1, DOS is definitely busy
cmp $AMIS$POPUP_INT28,0 ; if activated via INT 28, INDOS flag is
jz try_popup_2 ; allowed to be 1 rather than 0
try_popup_1:
lds bx,CRITERR_ptr ; InDOS says DOS is idle, but it might
ASSUME DS:NOTHING ; be in the critical error handler
cmp byte ptr [bx],0 ; so check the CritErr flag
jne try_popup_2 ; can't popup if in critical error
push cs
pop ds ; restore DS
ASSUME DS:TGROUP
call $AMIS$POPUP ; whew, we made it... we can pop up now
try_popup_2:
ASSUME DS:NOTHING
pop bx ; restore registers
pop ds
ASSUME DS:NOTHING
try_popup_done:
popf ; restore flags
ret
$AMIS$TRY_POPUP endp
;-----------------------------------------------------------------------
TSRcodeEnd@
_TEXT SEGMENT PUBLIC 'CODE'
ASSUME cs:_TEXT,ds:NOTHING,es:NOTHING,ss:NOTHING
IFDEF __TINY__
extrn TGROUP@:word
ENDIF
;-----------------------------------------------------------------------
; get and store pointers to DOS busy flags
;
public $AMIS$GET_DOS_PTRS
$AMIS$GET_DOS_PTRS proc DIST
mov ah,34h ; get address of InDOS flag
int 21h
ASSUME ES:NOTHING
mov ds,TGROUP@
ASSUME DS:TGROUP
mov word ptr TGROUP:INDOS_ptr,bx
mov word ptr TGROUP:INDOS_ptr+2,es
push ds
mov ax,5D06h ; get address of CriticalError flag
int 21h
ASSUME DS:NOTHING
mov dx,ds
pop ds
ASSUME DS:TGROUP
mov word ptr TGROUP:CRITERR_ptr+2,dx
mov word ptr TGROUP:CRITERR_ptr,si
ret
$AMIS$GET_DOS_PTRS endp
;-----------------------------------------------------------------------
_TEXT ENDS
END