TSR.LST 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. Listing:
  2. 1 (*========================================================
  3. 2 == TopSpeed Modula-2 V3.10 ==
  4. 3 == demo program: ==
  5. 4 == ==
  6. 5 == TSR Shell ==
  7. 6 == ==
  8. 7 == Installs a "safe" Pop Up program ==
  9. 8 == ==
  10. 9 ========================================================*)
  11. 10 (*# check(stack=>off,index=>off,range=>off,overflow=>off,nil_ptr=>off) *)
  12. 11 (*# debug(vid=>off)*)
  13. 12
  14. 13 IMPLEMENTATION MODULE TSR ;
  15. 14 (* === *)
  16. 15
  17. 16
  18. 17 IMPORT IO,Window,Lib,Storage,Str,SYSTEM,TSRLow;
  19. 18
  20. 19 CONST
  21. 20 KBFuseful = KBFlagSet { RShift, LShift, Ctrl, Alt } ;
  22. ***** ^ undeclared identifier
  23. 21 TYPE
  24. 22 TSRmodeType = (Sleeping,Wake,Active,Kill,Dead ) ;
  25. 23 VAR
  26. 24 (*# save, data(volatile=>on) *)
  27. 25 ProgDTA : ADDRESS ;
  28. 26 ProgPSP : CARDINAL ;
  29. 27 ActivateScan : SHORTCARD ;
  30. 28 ActivateFlags : KBFlagSet ;
  31. 29 KBFlags[40H:17H] : KBFlagSet ;
  32. 30 TSRproc : PROC ;
  33. 31 DosNest : POINTER TO SHORTCARD ;
  34. 32 TSRmode : TSRmodeType ;
  35. 33 MainProcess : SYSTEM.PROCESS;
  36. 34
  37. 35 (*# restore *)
  38. 36
  39. 37
  40. 38 PROCEDURE SwapToTSR ;
  41. 39 VAR
  42. 40 op,np : SYSTEM.PROCESS ;
  43. 41 BEGIN
  44. 42 TSRmode := Active ;
  45. 43 np := MainProcess ;
  46. 44 SYSTEM.TRANSFER(op,np) ; (* can't use IOTRANSFER due to chaining problems
  47. 45 with other TSRs (SideKick 1, for example) *)
  48. 46 TSRmode := Sleeping ;
  49. 47 END SwapToTSR ;
  50. 48
  51. 49
  52. 50 (* Interrupt Handlers *)
  53. 51 (* ================== *)
  54. 52
  55. 53 (* pragmas for interrupt handler *)
  56. 54 (*# save,
  57. 55 call(interrupt => on,
  58. 56 reg_param => (),
  59. 57 same_ds => off
  60. 58 )
  61. 59 *)
  62. 60
  63. 61 TYPE
  64. 62 IPROC = PROCEDURE();
  65. 63 VAR
  66. 64 Irpt[0:0], (* Interrupt table *)
  67. 65 SaveIrpt : ARRAY [0..255] OF IPROC ;
  68. 66
  69. 67
  70. 68 PROCEDURE NullInt () ; (* Do nothing interrupt *)
  71. 69 BEGIN
  72. 70 END NullInt;
  73. 71
  74. 72 PROCEDURE Int9 () ; (* Keyboard H/W interrupt *)
  75. 73 VAR
  76. 74 sc : SHORTCARD ;
  77. 75 BEGIN
  78. 76 sc := SYSTEM.In(60H) ;
  79. 77 IF ((sc=ActivateScan)OR(ActivateScan=0))AND
  80. 78 ((KBFlags*KBFuseful)=ActivateFlags) THEN
  81. 79 sc := SYSTEM.In(61H) ;
  82. 80 SYSTEM.Out(61H,SHORTCARD(BITSET(sc)+{7}));
  83. 81 SYSTEM.Out(61H,sc);
  84. 82 SYSTEM.Out(20H,20H);
  85. 83 IF TSRmode=Sleeping THEN
  86. 84 TSRmode := Wake ;
  87. 85 END ;
  88. 86 ELSE
  89. 87 SaveIrpt[09H]() ; (* Chain Int 28 *)
  90. 88 END ;
  91. 89 END Int9 ;
  92. 90
  93. 91 VAR
  94. 92 Save28stack : ARRAY[0..3FFH] OF BYTE ;
  95. 93
  96. 94 PROCEDURE Int28 () ; (* DOS "I'm not doing much" interrupt *)
  97. 95 VAR
  98. 96 base : CARDINAL ;
  99. 97 BEGIN
  100. 98 Lib.Move(ADR(base),ADR(Save28stack),SIZE(Save28stack));
  101. 99 SaveIrpt[28H]() ; (* Chain Int 28 *)
  102. 100 IF (Ofs(base)>100H) AND (TSRmode=Wake) THEN
  103. 101 SwapToTSR ;
  104. 102 END ;
  105. 103 Lib.Move(ADR(Save28stack),ADR(base),SIZE(Save28stack));
  106. 104 END Int28 ;
  107. 105
  108. 106
  109. 107 PROCEDURE Int1C () ; (* Timer Interrupt *)
  110. 108 VAR
  111. 109 base : CARDINAL ;
  112. 110 BEGIN
  113. 111 SaveIrpt[1CH]() ; (* Chain Int 1C *)
  114. 112 IF (Ofs(base)>100H)AND(DosNest^ = 0)AND(TSRmode=Wake) THEN
  115. 113 SYSTEM.Out(20H,20H) ; (* Send EOI to timer *)
  116. 114 SwapToTSR ;
  117. 115 END ;
  118. 116 END Int1C ;
  119. 117
  120. 118 PROCEDURE Int24 () : CARDINAL ; (* Critical Error Interrupt *)
  121. 119 BEGIN
  122. 120 RETURN 0 ;
  123. 121 END Int24;
  124. 122
  125. 123 (*# restore *)
  126. 124
  127. 125 PROCEDURE SetIrpt ( N : CARDINAL ; P : IPROC ) ;
  128. 126 VAR
  129. 127 fl : CARDINAL ;
  130. 128 BEGIN
  131. 129 fl := SYSTEM.GetFlags() ; SYSTEM.DI ;
  132. 130 SaveIrpt[N] := Irpt[N] ;
  133. 131 Irpt[N] := P ;
  134. 132 SYSTEM.SetFlags(fl) ;
  135. 133 END SetIrpt ;
  136. 134
  137. 135 PROCEDURE ResetIrpt ( N : CARDINAL ) ;
  138. 136 VAR
  139. 137 fl : CARDINAL ;
  140. 138 BEGIN
  141. 139 fl := SYSTEM.GetFlags() ; SYSTEM.DI ;
  142. 140 Irpt[N] := SaveIrpt[N] ;
  143. 141 SYSTEM.SetFlags(fl) ;
  144. 142 END ResetIrpt ;
  145. 143
  146. 144
  147. 145
  148. 146 PROCEDURE Resident;
  149. 147 (* ======== *)
  150. 148
  151. 149 VAR I,F : CARDINAL;
  152. 150 R : SYSTEM.Registers;
  153. 151 SaveDTA : ADDRESS ;
  154. 152 SavePSP : CARDINAL ;
  155. 153 SaveBrk : SHORTCARD ;
  156. 154 BEGIN
  157. 155 (* Set Critical Error Handler and break handlers *)
  158. 156 SetIrpt(24H,IPROC(Int24)) ;
  159. 157 SetIrpt(1BH,NullInt);
  160. 158 SetIrpt(23H,NullInt);
  161. 159 (* Change DTA *)
  162. 160 R.AH := 2FH ;
  163. 161 Lib.Dos(R) ;
  164. 162 SaveDTA := [R.ES:R.BX] ;
  165. 163 R.AH := 1AH ;
  166. 164 R.DS := Seg(ProgDTA^) ;
  167. 165 R.DX := Ofs(ProgDTA^) ;
  168. 166 Lib.Dos(R) ;
  169. 167 (* Change PSP *)
  170. 168 R.AX := 5100H ;
  171. 169 Lib.Dos(R) ;
  172. 170 SavePSP := R.BX ;
  173. 171 R.BX := ProgPSP ;
  174. 172 R.AX := 5000H ;
  175. 173 Lib.Dos(R) ;
  176. 174 (* Turn off break flag *)
  177. 175 R.AX := 3300H ;
  178. 176 Lib.Dos(R) ;
  179. 177 SaveBrk := R.DL ;
  180. 178 R.DL := 0 ;
  181. 179 R.AX := 3301H ;
  182. 180 Lib.Dos(R) ;
  183. 181 R.AH := 3;
  184. 182 R.BH := 0;
  185. 183 Lib.Intr(R,010H);
  186. 184 Window.Use(Window.FullScreen);
  187. 185 Window.CursorOff;
  188. 186 Window.SnapShot;
  189. 187 TSRproc() ;
  190. 188 R.AH := 0DH ;
  191. 189 Lib.Dos(R) ;
  192. 190 Window.Use(Window.FullScreen);
  193. 191 Window.CursorOn;
  194. 192 R.AH := 2;
  195. 193 R.BH := 0;
  196. 194 Lib.Intr(R,010H);
  197. 195
  198. 196 (* Restore break flag *)
  199. 197 R.DL := SaveBrk ;
  200. 198 R.AX := 3301H ;
  201. 199 Lib.Dos(R) ;
  202. 200 (* Restore PSP *)
  203. 201 R.BX := SavePSP ;
  204. 202 R.AX := 5000H ;
  205. 203 Lib.Dos(R) ;
  206. 204 (* Restore DTA *)
  207. 205 R.AH := 1AH ;
  208. 206 R.DS := Seg(SaveDTA^) ;
  209. 207 R.DX := Ofs(SaveDTA^) ;
  210. 208 Lib.Dos(R) ;
  211. 209 (* Restore Critical irpt and break handlers *)
  212. 210 ResetIrpt(24H);
  213. 211 ResetIrpt(1BH);
  214. 212 ResetIrpt(23H);
  215. 213 END Resident;
  216. 214
  217. 215 VAR
  218. 216 HeapSize : CARDINAL ;
  219. 217 PROCEDURE TermProc ;
  220. 218 VAR
  221. 219 R : SYSTEM.Registers ;
  222. 220 psize : CARDINAL;
  223. 221 BEGIN
  224. 222 psize := TSRLow.ShrinkHeap(HeapSize);
  225. 223 R.AX := 03100H; (*Terminate and stay resident*)
  226. 224 R.DX := psize ;
  227. 225 Lib.Intr(R,21H); (* Use Intr, so as not to trigger the
  228. 226 Dos re-entry run-time check *)
  229. 227 (* No Return *)
  230. 228 END TermProc ;
  231. 229
  232. 230
  233. 231 PROCEDURE SKinstalled () : BOOLEAN ;
  234. 232 TYPE
  235. 233 AP = POINTER TO ADDRESS ;
  236. 234 VAR
  237. 235 id1 : POINTER TO LONGCARD ;
  238. 236 id2 : POINTER TO CARDINAL ;
  239. 237 BEGIN
  240. 238 id1 := Lib.SubAddr([0:8*4 AP]^,4) ;
  241. 239 id2 := Lib.SubAddr([0:25H*4 AP]^,2) ;
  242. 240 RETURN (id1^=049424B53H)OR(id2^=04B53H) ;
  243. 241 END SKinstalled ;
  244. 242
  245. 243 PROCEDURE InEnv() : BOOLEAN ;
  246. 244 TYPE Str5 = ARRAY[0..4] OF CHAR;
  247. 245 IDP = POINTER TO Str5;
  248. 246 AP = POINTER TO ADDRESS ;
  249. 247 CONST EnvId = 'TSENV';
  250. 248 VAR id1 : IDP;
  251. 249 BEGIN
  252. 250 id1 := Lib.SubAddr([0:4*4 AP]^,8) ;
  253. 251 RETURN id1^=Str5(EnvId);
  254. 252 END InEnv;
  255. 253
  256. 254
  257. 255
  258. 256 PROCEDURE Install ( P : PROC ; (* Procedure to be invoked *)
  259. 257 KBF : KBFlagSet; (* Shift state to invoke *)
  260. 258 Scan : SHORTCARD ; (* Invoking scancode (0=All) *)
  261. 259 heapsize : CARDINAL (* Minimum heap required *)
  262. 260 ) ;
  263. 261 VAR
  264. 262 hp,nhp : Storage.HeapRecPtr ;
  265. 263 R : SYSTEM.Registers ;
  266. 264 stack : ARRAY[0..1023] OF BYTE ;
  267. 265 termp : SYSTEM.PROCESS ;
  268. 266
  269. 267 BEGIN
  270. 268 IF InEnv() THEN
  271. 269 Lib.FatalError('Failed to install TSR: should be installed outside the TopSpeed Environment');
  272. 270 END ;
  273. 271 IF SKinstalled() THEN
  274. 272 Lib.FatalError('Failed to install TSR: should be installed BEFORE SideKick ');
  275. 273 END ;
  276. 274 ActivateScan := Scan ;
  277. 275 ActivateFlags := KBF ;
  278. 276 TSRproc := P ;
  279. 277
  280. 278 R.AH := 52 ;
  281. 279 Lib.Dos(R) ;
  282. 280 DosNest := [R.ES:R.BX] ; (* Dos nesting count *)
  283. 281 R.AH := 2FH ;
  284. 282 Lib.Dos(R) ;
  285. 283 ProgDTA := [R.ES:R.BX] ; (* Current DTA *)
  286. 284 R.AX := 5100H ;
  287. 285 Lib.Dos(R) ;
  288. 286 ProgPSP := R.BX ; (* Current PSP *)
  289. 287
  290. 288 (* Install Interrupt handlers *)
  291. 289 SetIrpt(09H,Int9);
  292. 290 SetIrpt(1CH,Int1C);
  293. 291 SetIrpt(28H,Int28);
  294. 292 SYSTEM.NEWPROCESS( TermProc, ADR(stack), SIZE(stack) , termp );
  295. 293 HeapSize := heapsize ;
  296. 294 TSRmode := Sleeping ;
  297. 295 REPEAT
  298. 296 SYSTEM.TRANSFER(MainProcess,termp) ;
  299. 297 Resident ;
  300. 298 UNTIL TSRmode = Dead ;
  301. 299 END Install ;
  302. 300
  303. 301 PROCEDURE DeInstall ;
  304. 302 TYPE
  305. 303 BP = POINTER TO SHORTCARD ;
  306. 304 CP = POINTER TO CARDINAL ;
  307. 305 VAR
  308. 306 s : CARDINAL ;
  309. 307 R : SYSTEM.Registers ;
  310. 308 BEGIN
  311. 309 IF TSRmode<>Dead THEN
  312. 310 TSRmode := Dead ;
  313. 311 ResetIrpt(09H);
  314. 312 ResetIrpt(1CH);
  315. 313 ResetIrpt(28H);
  316. 314 R.AH := 52H ;
  317. 315 Lib.Dos(R);
  318. 316 s := [R.ES:R.BX-2 CP]^;
  319. 317 WHILE [s:0 BP]^ = 4DH DO
  320. 318 IF [s:1 CP]^ = ProgPSP THEN
  321. 319 R.AH := 49H ;
  322. 320 R.ES := s+1 ;
  323. 321 Lib.Dos(R) ;
  324. 322 END ;
  325. 323 INC(s,[s:3 CP]^+1);
  326. 324 END ;
  327. 325 END ;
  328. 326 END DeInstall ;
  329. 327
  330. 328 VAR
  331. 329 Continue : PROC ;
  332. 330
  333. 331 PROCEDURE Closedown ;
  334. 332 BEGIN
  335. 333 DeInstall ;
  336. 334 Continue() ;
  337. 335 END Closedown ;
  338. 336
  339. 337
  340. 338 BEGIN
  341. 339 TSRmode := Dead ;
  342. 340 Lib.Terminate(Closedown,Continue) ;
  343. 341 END TSR.
  344. 342
  345. 343 (*======================================================*)
  346. 344
  347. 1 error