0CD.ASM
上传用户:hstrip
上传日期:2007-01-06
资源大小:51k
文件大小:73k
源码类别:

SCSI/ASPI

开发平台:

Pascal

  1. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  2. ;圹 RCS (Revision Control System) Version Log                                圹
  3. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  4. ;
  5. ; $Log: 0cd.asm $
  6. ; Revision 1.40  1995/12/06 22:13:29  Lasse
  7. ; Fixed so that -a was disabled if mscdex was loaded.
  8. ;
  9. ; Revision 1.39  1995/12/05 22:11:53  Lasse
  10. ; Adjusted the revision messages
  11. ;
  12. ; Revision 1.38  1995/12/05 22:00:45  Lasse
  13. ; Version 7.0; Removes data segment when going resident, shrinked down to
  14. ; 6.5 Kb of memory from 8.7 Kb. Also, fixed a bug when allocating more
  15. ; drives than available consecutively. Also, inserted rcs keywords in a
  16. ; message
  17. ;
  18. ; Revision 1.37  1995/12/05 09:05:14  Lasse
  19. ; Version 6.7; now co-exists with mscdex, and also enables audio through-
  20. ; put.
  21. ;
  22. ; Revision 1.36  1995/12/04 00:56:07  Lasse
  23. ; Version 6.6; Now works with worms too, and simulates the following new
  24. ; device requests:
  25. ;   Play
  26. ;   Stop
  27. ; also, the AudioStatus function has been augmented to react on the Play
  28. ; and Stop functions, and the HeadLocation function will return different
  29. ; values, as though the cd was playing or moving around.
  30. ; Also, the -a option will make 0cd simulate FakeCD.
  31. ;
  32. ; Revision 1.35  1995/12/03 02:35:45  Lasse
  33. ; Version 6.5; Fixed the root-directory subst problem which came back :(
  34. ;
  35. ; Revision 1.34  1995/11/26 09:46:54  Lasse
  36. ; Version 6.4; Fixed several bugs with the DiskFree function
  37. ;
  38. ; Revision 1.33  1995/11/16 06:36:22  Lasse
  39. ; Fixed a bug in the makecd program, and an inconsistency in 0cd
  40. ;
  41. ; Revision 1.32  1995/11/16 06:14:39  Lasse
  42. ; Put Decrunch into 0cd.asm for maximum distributability
  43. ;
  44. ; Revision 1.31  1995/11/16 06:04:28  Lasse
  45. ; Version 6.2
  46. ;
  47. ; Revision 1.30  1995/11/16 05:24:59  Lasse
  48. ; Commented all code; Done some minor cosmetic changes, tidied up the
  49. ; code a bit
  50. ;
  51. ; Revision 1.29  1995/11/14 22:04:22  Lasse
  52. ; If last character in directory was  then redirection failed; fixed!
  53. ;
  54. ; Revision 1.28  1995/11/14 21:57:59  Lasse
  55. ; Removed the "Unmangling" of filename
  56. ;
  57. ; Revision 1.27  1995/11/14 21:46:19  Lasse
  58. ; Version 6.2; Fixed so that magic carpet works; Fixed so that DiskFree(d:)
  59. ; where d: is a cd-rom now returns correct data
  60. ;
  61. ; Revision 1.26  1995/11/14 19:50:33  Lasse
  62. ; Bug in previous revision concerning the drive letter in speed messages;
  63. ; fixed
  64. ;
  65. ; Revision 1.25  1995/11/14 19:48:43  Lasse
  66. ; Fixed so that speed message included correct drive letter
  67. ;
  68. ; Revision 1.24  1995/11/14 19:29:30  Lasse
  69. ; Version 6.1; Super speed emulation enabled
  70. ;
  71. ; Revision 1.23  1995/11/14 19:02:11  Lasse
  72. ; Updated the usage message, and renamed VTC to data
  73. ;
  74. ; Revision 1.22  1995/11/14 18:51:36  Lasse
  75. ; Version 6.0; Now simulates speed of cd-rom; Also read sector 16 (system
  76. ; data)
  77. ;
  78. ; Revision 1.21  1995/11/12 21:52:52  Lasse
  79. ; Version 5.0; fixed a couple of bugs with the audio track information
  80. ;
  81. ; Revision 1.20  1995/11/12 08:14:22  Lasse
  82. ; Version 4.1
  83. ;
  84. ; Revision 1.19  1995/11/12 08:09:58  Lasse
  85. ; Removed some old dummy-stuff
  86. ;
  87. ; Revision 1.18  1995/11/12 06:44:56  Lasse
  88. ; Audio Status now responds music paused; fix necessary for MechWarrior 2
  89. ;
  90. ; Revision 1.17  1995/11/12 03:39:43  Lasse
  91. ; Fixed the return to directory bug
  92. ;
  93. ; Revision 1.16  1995/11/12 03:24:55  Lasse
  94. ; Bug-fix; couldn't supply more than name.ext, no dir to run
  95. ;
  96. ; Revision 1.15  1995/11/12 03:21:29  Lasse
  97. ; Version 4; supply name of program to run
  98. ;
  99. ; Revision 1.14  1995/11/12 02:34:58  Lasse
  100. ; Fixed so that it reads audio data also
  101. ;
  102. ; Revision 1.13  1995/11/11 22:51:03  Lasse
  103. ; Fixed so cd-roms could be redirected to the root of a drive
  104. ;
  105. ; Revision 1.12  1995/11/11 22:48:52  Lasse
  106. ; Fixed a bug which caused strange symbols in 'dir' listings
  107. ;
  108. ; Revision 1.11  1995/11/11 22:39:32  Lasse
  109. ; Fixed so it didn't automatically write protect cd-roms unless the user
  110. ; asked for it
  111. ;
  112. ; Revision 1.10  1995/11/11 20:50:50  Lasse
  113. ; DiskFree function now clears carry flag
  114. ;
  115. ; Revision 1.9  1995/11/11 20:44:24  Lasse
  116. ; Version 3.1; added option to supply name of .vtc file
  117. ;
  118. ; Revision 1.8  1995/11/11 20:15:29  Lasse
  119. ; Returns dummy filenames, and uses CD0.VTC - CD7.VTC instead of DIR.VTC
  120. ; so that the same directory may be used for different cd's.
  121. ;
  122. ; Revision 1.7  1995/11/11 05:55:23  Lasse
  123. ; Fixed so it reads the VTOC into memory and returns it upon request.
  124. ;
  125. ; Revision 1.6  1995/11/10 23:14:47  Lasse
  126. ; Fixed the volume label bug that appeared in the last revision.
  127. ;
  128. ; Revision 1.5  1995/11/10 23:05:40  Lasse
  129. ; Fixed a bug when checking more than 8 drives past the first emulated
  130. ; cd-rom drive.
  131. ;
  132. ; Revision 1.4  1995/11/07 22:15:01  Lasse
  133. ; Version 2.0
  134. ;
  135. ; Revision 1.3  1995/11/07 22:13:19  Lasse
  136. ; Now saves current drive and directory and restores them when the sub-
  137. ; process exits. Also has self-installed check code now.
  138. ;
  139. ; Revision 1.2  1995/11/07 21:50:29  Lasse
  140. ; Moved all string procedures into 0cd.asm itself. Tidied up some of the
  141. ; code. Replace the uppercase functions. Fixed so that the GetDirEntry call
  142. ; to MSCDEX will go through (possibly returning garbage, but...) and some
  143. ; other stuff.
  144. ;
  145. ; Revision 1.1  1995/11/07 20:15:56  Lasse
  146. ; Initial revision
  147. ;
  148. ;
  149. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  150. ;圹 Assembler options and directives                                         圹
  151. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  152. ideal ; IDEAL assembly mode
  153. stacksize = 60h ; Size of stack (words)
  154. p386 ; Select the processor
  155. p387 ; Support for math coprocessor
  156. model tiny, pascal ; Always must be TINY model
  157. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  158. ;圹 Initialized data segment                                                 圹
  159. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  160. dataseg ; Initialized data segment
  161. MaxCDs = 8
  162. HookMsg db '0cd: installed', 13, 10, 0
  163. MSCDEX db '0cd error: mscdex already installed', 13, 10, 0
  164. Installed db '0cd error: already installed', 13, 10, 0
  165. NoRedirs db '0cd error: no redirections specified', 13, 10, 0
  166. UnknownOp db '0cd error: unknown command line parameter: ', 0
  167. InvOption db '0cd: invalid option ',0
  168. TooManyCDs db '0cd error: cannot handle more than ',48+MaxCDs
  169. db ' drives', 13, 10, 0
  170. No66Msg db '0cd error: int 66h not available', 13, 10, 0
  171. NoDrives db '0cd error: no drives available', 13, 10, 0
  172. NotRoom db '0cd error: no more drive letters available', 13, 10, 0
  173. CDSize db '0cd: host drive(s) and cd-rom(s) report host drive(s) size', 13, 10, 0
  174. CD0 db '0cd: host drive(s) and cd-rom(s) report 0 bytes free', 13, 10, 0
  175. IsProt db '0cd: cd-rom(s) are write protected', 13, 10, 0
  176. NotProt db '0cd: cd-rom(s) are not write protected', 13, 10, 0
  177. DataTooBig db '0cd error: data file is too big (>65535 bytes)', 13, 10, 0
  178. DataNoMem db '0cd error: no memory for data file', 13, 10, 0
  179. RunProg db '0cd: program to run is ', 0
  180. UnknownSpd db '0cd error: unknown speed option ', 0
  181. InvDrive db '0cd warning: can only adjust drive letter before redirections', 13, 10, 0
  182. SuccessMsg db '0cd: functions will succeed with dummy data', 13, 10, 0
  183. FailMsg db '0cd: functions will fail with no data', 13, 10, 0
  184. AltMsg db '0cd: alternate simulation enabled', 13, 10, 0
  185. TruMsg db '0cd: audio through-put enabled', 13, 10, 0
  186. NoMSCDEX db '0cd warning: no mscdex detected, audio through-put not enabled', 13, 10, 0
  187. CoMsg db '0cd: mscdex co-existance enabled', 13, 10, 0
  188. UnknownMSC db '0cd error: unknown mscdex option ',0
  189. TooFew db '0cd error: not enough consecutive drive letters, use the /lx option', 13, 10, 0
  190. UnknownSim db '0cd error: unknown simulation option ',0
  191. SimMsg1 db '0cd: drive '
  192. SimDrv db 'E'
  193. db ': simulates a ',0
  194. SimMsg2 db 'physical drive', 13, 10, 0
  195. SimMsg3 db 'substed drive', 13, 10, 0
  196. SimMsg4 db 'remote or cd-rom drive', 13, 10, 0
  197. SpeedMsg1 db '0cd: drive '
  198. SpeedDrv db 'E'
  199. db ': is a',0
  200. SpeedMsg2 db ' drive', 13, 10, 0
  201. SingleMsg db ' single speed',0
  202. DoubleMsg db ' double speed',0
  203. TripleMsg db ' triple speed',0
  204. QuadraMsg db ' quadra speed',0
  205. SexaMsg db ' sexa speed',0
  206. OctaMsg db 'n octa speed',0
  207. SuperMsg db ' super speed',0
  208. ReadData1 db '0cd: data for drive '
  209. ReadData2 db '?'
  210. ReadData3 db ': read into memory from ', 0
  211. Prompt1 db '0cd: mounted ', 0
  212. Prompt2 db ': in ', 0
  213. DriveID db 0, 0
  214. AnyRedir db 0
  215. CSEnv db 'COMSPEC=',0
  216. UsageMsg db '0cd usage: 0cd [options] <directory> [<directory> ... ]', 13, 10
  217. db '0cd options: -q         = quiet; no messages except for error messages', 13, 10
  218. db '             -0         = host and cd-rom drives report 0 bytes free', 13, 10
  219. db '             -w         = cd-rom drives are write protected', 13, 10
  220. db '             -dfilename = supply name of data file', 13, 10
  221. db '             -rfilename = supply name of program to run',13,10
  222. db '             -sx        = supply speed of drive (x=s, 1, 2, 3, 4, 6 or 8)', 13, 10
  223. db '             -i0        = simulate physical drive', 13, 10
  224. db '             -i1        = simulate substed drive', 13, 10
  225. db '             -i2        = simulate remote or cd-rom drive (default)', 13, 10
  226. db '             -f         = failure if no cd-rom data', 13, 10
  227. db '             -a         = alternate simulation', 13, 10
  228. db '             -mx        = mscdex co-existance level (x=0-3, default=0)', 13, 10
  229. db '             -v         = show revision information', 13, 10, 0
  230. CRLF db 13, 10, 0
  231. Line db 30 dup (0)
  232. PathName db 128 dup (0)
  233. DataName db 128 dup (0)
  234. RevMsg db '0cd: revision $Revision: 1.40 $', 13, 10
  235. db '0cd: state $State: Exp $', 13, 10
  236. db '0cd: source $Source: D:/ASM/PROJECTS/0CD/RCS/0cd.asm $', 13, 10
  237. db '0cd: rcsfile $RCSfile: 0cd.asm $', 13, 10
  238. db 0
  239. Label EndOfData word
  240. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  241. ;圹 Uninitialized data segment                                               圹
  242. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  243. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  244. ;圹 Code segment                                                             圹
  245. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  246. assume cs:@code, 
  247. ds:@data, 
  248. es:@data
  249. codeseg ; Code segment
  250.  
  251. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  252. ;圹 Macro declarations                                                       圹
  253. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  254. macro iCLC
  255. push bp ; Preserve BP register
  256. mov bp,sp ; Set BP to stack pointer
  257. and [word ptr bp+6],0fffeh ; Modify flags on the stack
  258. pop bp ; Restore BP register
  259. endm
  260. macro iSTC
  261. push bp ; Preserve BP register
  262. mov bp,sp ; Set BP to stack pointer
  263. or [word ptr bp+6],0001h ; Modify flags on the stack
  264. pop bp ; Restore BP register
  265. endm
  266. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  267. ;圹 Program initialization                                                   圹
  268. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  269. StartUpCode ; Insert startup code
  270. mov sp,offset TheStack ; Fix stack pointers
  271. mov bx,offset EndOfData ; Get end of data segment
  272. shr bx,4 ; Make segment count
  273. add bx,1 ; Make last segment count
  274. mov ah,4ah ; Fn 4ah = Resize memory block
  275. int 21h ; Call dos interrupt
  276. push cs ; Point ds to
  277. pop ds ; data segment (after code)
  278. push cs ; Point es to
  279. pop es ; data segment (after code)
  280. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  281. ;圹 User-code                                                                圹
  282. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  283. call SaveDir
  284. call GetCOMSPEC
  285. call Init
  286. call Report
  287. call Hook
  288. call MinMem
  289. call Exec, cs offset ProgName, cs offset Params
  290. call UnHook
  291. call ReturnDir
  292. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  293. ;圹 Exit program here, returning 0000h as ExitCode (ERRORLEVEL in DOS)       圹
  294. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  295. ExitCode 0000h ; Return to dos, clear up heap
  296. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  297. ;圹 Procedure/function declarations                                          圹
  298. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  299. ; Code segment variables
  300. OldDir db 79 dup (0)
  301. OldDrive db 0
  302. ProgName db 128 dup (0)
  303. Params db '/C '
  304. RunName db '0CDSTART.BAT',0
  305. db 115 dup (0)
  306. SimType db 2
  307. SimFlag dw 0100000010000000b
  308. CoMSCDEX db 0
  309. FirstRealCD db 0
  310. AudioTru db 0
  311. AltSimul db 0
  312. DoFailure db 0
  313. CDPlaying dw 0001h
  314. CDPos dw 0010h
  315. CurSpeed db 2
  316. CurDelay dw 6200
  317. UnHookMsg db '0cd: removed', 13, 10, 0
  318. InitMsg db '0cd: version 7.1', 13, 10, 0
  319. Inited db 0
  320. Datas db 2*MaxCDs dup (0)
  321. FirstID db 0
  322. LastID db 0
  323. IsRun db 0
  324. RetZero db 0
  325. WriteProt db 0
  326. Quiet db 0
  327. DriveCount db 0
  328. DriveSpeeds dw MaxCDs dup (0)
  329. DeviceHdr dw -1, -1
  330. dw 0100100001000000b
  331. dw Strategy
  332. dw Strategy ; No interrupt
  333. db '0CD-CDx',0
  334. db 0,0
  335. dw stacksize dup (0) ; Set up space for stack
  336. Label TheStack Word ; Here begins the stack
  337. ; Strategy procedure
  338. proc Strategy far
  339. ret ; Return to caller
  340. endp
  341. ; MinMem procedure
  342. proc MinMem
  343. mov ah,62h ; Dos Fn 62h = Get PSP in bx
  344. int 21h ; Call dos interrupt
  345. mov es,bx ; Store in es for realloc
  346. mov ah,4ah ; Dos Fn 4ah = Realloc
  347. lea bx,[HookMsg] ; Get offset of data
  348. shr bx,4 ; Calculate segments
  349. inc bx ; Adjust for last segment
  350. int 21h ; Reallocate memory
  351. ret ; Return to caller
  352. endp
  353. ; GetCDData procedure
  354. ; returns segment in es, or 0-segment if failure
  355. proc GetCDData
  356. arg @@DriveID:word
  357. local @@Handle:word, @@NewSeg:word, @@Size:word
  358. uses ax, bx, si
  359. mov [@@NewSeg],0 ; No segment yet
  360. cmp [byte ptr ds:DataName],0 ; Got a filename of datafile ?
  361. je @@Exit ; No --> @@Exit
  362. mov ah,3dh ; Dos Fn 3dh = Open file
  363. lea dx,[DataName] ; Filename in dx:dx
  364. mov al,00h ; Open mode in al
  365. int 21h ; Call DOS interrupt
  366. jc @@Exit ; Error --> @@Exit
  367. mov [@@Handle],ax ; Save file handle
  368. mov ax,4202h ; Dos Fn 42 = LSeek
  369. mov bx,[@@Handle] ; Filehandle in bx
  370. xor cx,cx ; High 16 bits of position
  371. xor dx,dx ; Low 16 bits of position
  372. int 21h ; Call DOS interrupt
  373. test dx,dx ; File larger than 64K ?
  374. jz @@OkSize ; No --> @@OkSize
  375. mov ah,3eh ; Dos Fn 3eh = Close file
  376. mov bx,[@@Handle] ; Filehandle in bx
  377. int 21h ; Call DOS interrupt
  378. mov [cs:Quiet],00h ; Turn of quiet mode
  379. call LStrWrite, offset DataTooBig ; Write error msg
  380. call CleanUp ; Clean up
  381. ExitCode 0001h ; Exit to DOS
  382. @@OkSize:
  383. mov [@@Size],ax ; Save size of file
  384. shr ax,4 ; Divide by 16
  385. inc ax ; And add 1
  386. mov bx,ax ; Number of segments in bx
  387. mov ah,48h ; Dos Fn 48h = AllocMem
  388. int 21h ; Call DOS interrupt
  389. jc @@NoMem ; Error --> @@NoMem
  390. mov es,ax ; Segment in es
  391. mov [@@NewSeg],ax ; Store new segment
  392. mov ax,4200h ; Dos Fn 42 = LSeek
  393. mov bx,[@@Handle] ; Filehandle in bx
  394. xor cx,cx ; High 16 bits of position
  395. xor dx,dx ; Low 16 bits of position
  396. int 21h ; Call DOS interrupt
  397. mov ah,3fh ; Dos Fn 3fh = Read file
  398. mov bx,[@@Handle] ; Filehandle in bx
  399. push ds ; Save ds
  400. push es ; Put ds ...
  401. pop ds ; ... in es
  402. xor dx,dx ; High 16 bits of size in dx
  403. mov cx,[@@Size] ; Low 16 bits of size in cx
  404. int 21h ; Call DOS interrupt
  405. pop ds ; Restore ds
  406. mov al,[byte ptr @@DriveID] ; Get driveletter
  407. mov [ReadData2],al ; Update message text
  408. call LStrWrite, offset ReadData1 ; Write text
  409. call LStrWrite, offset DataName ; Write filename
  410. call LStrWrite, offset CRLF ; Newline
  411. mov bx,[@@Handle] ; Filehandle in bx
  412. mov ah,3eh ; Dos Fn 3eh = Close file
  413. int 21h ; Call DOS interrupt
  414. jmp @@Exit ; Exit
  415. @@NoMem:
  416. mov bx,[@@Handle] ; Filehandle in bx
  417. mov ah,3eh ; Dos Fn 3eh = Close file
  418. int 21h ; Call DOS interrupt
  419. mov [cs:Quiet],00h ; Turn off quiet mode
  420. call LStrWrite, offset DataNoMem ; Write error msg
  421. call CleanUp ; Clean up
  422. ExitCode 0001h ; Exit to dos
  423. @@Exit:
  424. lea si,[Datas] ; ds:si point to Datas
  425. mov cx,[@@DriveID] ; Get drive letter
  426. sub cl,[cs:FirstID] ; Make 0-based
  427. cmp cl,0 ; First drive ?
  428. je @@DoExit ; Yes --> @@DoExit
  429. @@Loop:
  430. add si,2 ; Next data index
  431. dec cl ; One less to skip
  432. jnz @@Loop ; More --> @@Loop
  433. @@DoExit:
  434. mov es,[@@NewSeg] ; Return segment in es
  435. mov [ds:si],es ; Save segment in Datas
  436. ret ; Return to caller
  437. endp
  438. ; Report procedure
  439. proc Report
  440. cmp [cs:CoMSCDEX],01h ; MSCDEX co-existance ?
  441. jne @@NoCoEXIST
  442. call LStrWrite, offset CoMsg ; Write message
  443. @@NoCoExist:
  444. cmp [cs:AudioTru],00h ; Audio throughput ?
  445. je @@NoTru ; No --> @@NoTru
  446. call LStrWrite, offset TruMsg ; Write message
  447. @@NoTru:
  448. cmp [cs:AltSimul],00h ; Alternate simulation ?
  449. je @@NoAlt ; No --> @@NoAlt
  450. call LStrWrite, offset AltMsg ; Write message
  451. @@NoAlt:
  452. cmp [cs:DoFailure],00h ; Failure or success ?
  453. je @@Success
  454. call LStrWrite, offset FailMsg ; Write message
  455. jmp @@OkFail
  456. @@Success:
  457. call LStrWrite, offset SuccessMsg ; Write message
  458. @@OkFail:
  459. cmp [cs:WriteProt],00h ; Write-protected ?
  460. je @@NotProt ; No --> @@NotProt
  461. call LStrWrite, offset IsProt ; Write message
  462. jmp @@Size ; --> @@Size
  463. @@NotProt:
  464. call LStrWrite, offset NotProt ; Write message
  465. @@Size:
  466. cmp [cs:RetZero],00h ; Zero disk free ?
  467. je @@NotZero ; No --> @@NotZero
  468. call LStrWrite, offset CD0 ; Write message
  469. jmp @@Exit ; Exit
  470. @@NotZero:
  471. call LStrWrite, offset CDSize ; Write message
  472. @@Exit:
  473. call LStrWrite, offset CRLF ; Write an empty line
  474. ret ; Return to caller
  475. endp
  476. ; SaveDir procedure
  477. proc SaveDir
  478. uses ax, si, dx
  479. mov ah,47h ; Dos Fn 47h = GetCurDir
  480. lea si,[OldDir+1] ; Destination in ds:si
  481. push ds
  482. push cs
  483. pop ds
  484. mov [byte ptr ds:si-1],'' ; Make  relative
  485. mov dl,00h ; Set to current drive
  486. int 21h ; Call DOS interrupt
  487. pop ds
  488. mov ah,19h ; Dos Fn 19h = GetCurDrive
  489. int 21h ; Call DOS interrupt
  490. mov [cs:OldDrive],al ; Save drive
  491. ret ; Return to caller
  492. endp
  493. ; ReturnDir procedure
  494. proc ReturnDir
  495. uses ax, dx
  496. mov ah,0eh ; Dos Fn 0eh = SetCurDrive
  497. mov dl,[cs:OldDrive] ; Drive no in dl
  498. int 21h ; Call DOS interrupt
  499. mov ah,3bh ; Dos Fn 3bh = SetCurDir
  500. lea dx,[OldDir] ; Directory in ds:dx
  501. push ds
  502. push cs
  503. pop ds
  504. int 21h ; Call DOS interrupt
  505. pop ds
  506. ret ; Return to caller
  507. endp
  508. ; LStrWrite procedure
  509. proc LStrWrite
  510. arg @@Str:word
  511. cmp [cs:Quiet],1 ; Quiet mode ?
  512. je @@Exit ; Yes --> @@Exit
  513. cmp [cs:Inited],0 ; Already shown version ?
  514. jne @@Ok ; Yes --> @@Ok
  515. mov [cs:Inited],1 ; Set version shown flag
  516. call StrWrite, cs offset InitMsg ; Show version message
  517. @@Ok:
  518. call StrWrite, [@@Str] ; Write text
  519. @@Exit:
  520. ret ; Return to caller
  521. endp
  522. ; Init procedure
  523. proc Init
  524. call GetFirstDrive
  525. call ReadDescription
  526. call Needed
  527. call CheckMSCDEX
  528. ret
  529. endp
  530. ; GetCOMSPEC procedure
  531. proc GetCOMSPEC
  532. uses ax, si, di, es, ds
  533. mov ah,62h ; Dos Fn 62h = Get PSP
  534. int 21h ; Call DOS interrupt
  535. mov es,bx ; Segment of PSP in es
  536. mov es,[es:002ch] ; Get environment segment
  537. xor si,si ; Start of environment
  538. @@Loop:
  539. call StrLIComp, es si, ds offset CSEnv, 8 ; COMSPEC=xxx ?
  540. jc @@Next ; No --> @@Next
  541. add si,8 ; Skip to xxx
  542. call StrCopy, cs offset ProgName, es si ; Save program name
  543. jmp @@Exit ; Exit
  544. @@Next:
  545. inc si ; Next character
  546. cmp [byte ptr es:si],0 ; At end of string ?
  547. jne @@Next ; No --> @@Next
  548. inc si ; Skip end-of-string char
  549. cmp [byte ptr es:si],0 ; End of environment ?
  550. jne @@Loop ; No --> @@Loop
  551. @@Exit:
  552. ret ; Return to caller
  553. endp
  554. ; Needed procedure
  555. proc Needed
  556. cmp [AnyRedir],1 ; Any redirections at all ?
  557. je @@Exit ; Yes --> @@Exit
  558. call LStrWrite, offset NoRedirs ; Write error message
  559. call CleanUp ; Clean up
  560. ExitCode 0001h ; Exit to dos
  561. @@Exit:
  562. call CheckFile ; Check for program to run
  563. ret ; Return to caller
  564. endp
  565. ; CheckFile procedure
  566. proc CheckFile
  567. mov ax,3d00h ; Dos Fn 3d = Open file
  568. push ds
  569. push cs
  570. pop ds
  571. lea dx,[RunName] ; Filename in ds:dx
  572. int 21h ; Call DOS interrupt
  573. pop ds
  574. jc @@NoFile ; Error --> @@NoFile
  575. mov bx,ax ; Filehandle in bx
  576. mov ah,3eh ; Dos Fn 3eh = Close file
  577. int 21h ; Call DOS interrupt
  578. call LStrWrite, offset RunProg ; Show run message
  579. push ds cs ; Save ds and put cs ...
  580. pop ds ; ... into ds
  581. call LStrWrite, offset RunName ; Show name of program
  582. pop ds ; Restore ds
  583. call LStrWrite, offset CRLF ; Newline
  584. jmp @@Exit ; Exit
  585. @@NoFile:
  586. mov [byte ptr cs:Params],0 ; No parameters to COMSPEC
  587. @@Exit:
  588. ret ; Return to caller
  589. endp
  590. ; GetCDS procedure
  591. ; Returns pointer in es:bx, and carry set if success, or 0:0 in es:bx and
  592. ; carry clear if failure
  593. proc GetCDS
  594. arg @@DriveID:word
  595. uses ax
  596. call UpCase, [@@DriveID] ; Make letter uppercase
  597. mov [@@DriveID],ax ; Store in @@DriveID
  598. mov ah,52h ; Dos Fn 52h = Get DosSysVars
  599. int 21h ; Call DOS interrupt
  600. add bx,16h ; Skip to CDS entry
  601. les bx,[dword ptr es:bx] ; Get pointer to CDS in es:bx
  602. mov al,'A' ; First drive letter in CDS
  603. @@Loop:
  604. cmp al,[byte ptr @@DriveID] ; Correct CDS record ?
  605. je @@Found ; Yes --> @@Found
  606. add bx,88 ; Skip record
  607. inc al ; Next drive letter
  608. cmp al,'[' ; Beyond end of CDS ?
  609. jb @@Loop ; No --> @@Loop
  610. xor bx,bx ; Zero offset
  611. mov es,bx ; Zero segment
  612. clc ; Signal failure via carry
  613. jmp @@Exit ; Exit
  614. @@Found:
  615. stc ; Signal success via carry
  616. @@Exit:
  617. ret ; Return
  618. endp
  619. ; GetFirstDrive procedure
  620. proc GetFirstDrive
  621. local @@DriveID:word
  622. uses ax
  623. mov [@@DriveID],'D' ; First available drive letter
  624. @@Loop:
  625. call GetCDS, [@@DriveID] ; Get CDS entry for drive
  626. jnc @@Exit ; Failure --> @@Exit
  627. cmp [word ptr es:bx+67],0000h ; Drive available ?
  628. jne @@Next ; No --> @@Next
  629. cmp [word ptr es:bx+69],0000h ; Drive available ?
  630. jne @@Next ; No --> @@Next
  631. cmp [word ptr es:bx+71],0000h ; Drive available ?
  632. jne @@Next ; No --> @@Next
  633. mov al,[byte ptr @@DriveID] ; Get drive ID
  634. mov [DriveID],al ; Store ID
  635. jmp @@Exit ; Exit
  636. @@Next:
  637. inc [@@DriveID] ; Next ID
  638. cmp [@@DriveID],'[' ; Beyond available IDs?
  639. je @@Err ; Yes --> @@Err
  640. jmp @@Loop ; Loop
  641. @@Exit:
  642. mov al,[DriveID] ; Get drive ID
  643. mov [cs:FirstID],al ; Save as first ID
  644. ret ; Return to caller
  645. @@Err:
  646. mov [cs:Quiet],0 ; Turn off quiet mode
  647. call LStrWrite, offset NoDrives ; Write error message
  648. call CleanUp ; Clean up
  649. ExitCode 0001h ; Exit to dos
  650. endp
  651. ; CheckMSCDEX procedure
  652. proc CheckMSCDEX
  653. push 0dadah ; Put 0dadah on stack
  654. mov ax,1100h ; Multiplex Fn 1100h = MSCDEX
  655. mov si,'0C' ; si:ds = '0CD6' ...
  656. mov di,'D7' ; ...
  657. int 2fh ; Call multiplex interrupt
  658. pop bx ; Get stack entry
  659. cmp al,0ffh ; MSCDEX installed ?
  660. jne @@NoMSCDEX ; No --> @@NoMSCDEX
  661. cmp bx,0adadh ; Correct entry on stack ?
  662. jne @@NoMSCDEX ; No --> @@NoMSCDEX
  663. @@Installed:
  664. cmp [cs:AudioTru],01h ; Audio throughput ?
  665. je @@ExitInstalled ; Yes --> @@ExitInstalled
  666. cmp si,'7D' ; 0cd signature ?
  667. jne @@MSC ; No --> @@MSC
  668. cmp di,'C0' ; ...
  669. jne @@MSC ; ...
  670. call LStrWrite, offset Installed ; Show installed message
  671. jmp @@Quit ; Exit to dos
  672. @@NoMSCDEX:
  673. cmp [cs:AudioTru],01h ; Audio through-put enabled ?
  674. jne @@Exit ; No --> @@Exit
  675. call LStrWrite, offset NoMSCDEX ; Write warning message
  676. mov [cs:AudioTru],00h ; Disable audio throughput
  677. jmp @@Exit ; Exit
  678. @@MSC:
  679. mov [cs:AltSimul],00h ; Disable alternate simulation
  680. cmp [cs:CoMSCDEX],01h ; MSCDEX co-existance ?
  681. je @@Exit ; Yes --> @@Exit
  682. call LStrWrite, offset MSCDEX ; Show MSCDEX message
  683. @@Quit:
  684. call CleanUp ; Clean up
  685. ExitCode 0001h ; Exit to dos
  686. @@ExitInstalled:
  687. mov [cs:AltSimul],00h ; Disable alternate simulation
  688. mov ax,1500h ; Get number of drives
  689. int 2fh ; Call old driver
  690. mov [cs:FirstRealCD],cl ; Store first unit
  691. @@Exit:
  692. ret ; Return to caller
  693. endp
  694. ; ReadDescription procedure
  695. proc ReadDescription
  696. local @@File:word
  697. mov ah,62h ; Dos Fn 62h = Get PSP
  698. int 21h ; Call DOS interrupt
  699. mov es,bx ; Segment of PSP in es
  700. mov si,81h ; Offset 81h = Parameters
  701. lea di,[Line] ; Point ds:di to Line
  702. mov [byte ptr ds:di],0 ; Terminate Line variable
  703. mov cl,[es:si-1] ; Get number of characters
  704. cmp cl,0 ; Any at all ?
  705. je @@Exit ; No --> @@Exit
  706. @@Loop:
  707. mov al,[es:si] ; Get character
  708. inc si ; Skip character
  709. cmp al,09h ; Tab character ?
  710. je @@Space ; Yes --> @@Space
  711. cmp al,20h ; Space character
  712. je @@Space ; Yes --> @@Space
  713. cmp al,0dh ; End of parameters ?
  714. je @@Space ; Yes --> @@Space
  715. mov [ds:di],al ; Store character in Line
  716. inc di ; Skip character in Line
  717. mov [byte ptr ds:di],0 ; Terminate Line variable
  718. @@Next:
  719. dec cl ; One less character to process
  720. jnz @@Loop ; More --> @@Loop
  721. call Parse ; Parse current parameter
  722. jmp @@Exit ; Exit
  723. @@Space:
  724. cmp [byte ptr Line],0 ; Parameter ?
  725. je @@NoLine ; No --> @@NoLine
  726. call Parse ; Parse current parameter
  727. @@NoLine:
  728. mov [byte ptr Line],0 ; Empty Line variable
  729. lea di,[Line] ; Rewind pointer to Line
  730. jmp @@Next ; Next character
  731. @@Exit:
  732. ret ; Return to caller
  733. endp
  734. ; Parse procedure
  735. proc Parse
  736. uses si, ax, cx, bx, ds, es
  737. cmp [byte ptr ds:Line],'/' ; Option character ?
  738. je @@Option ; Yes --> @@Option
  739. cmp [byte ptr ds:Line],'-' ; Option character ?
  740. je @@Option ; Yes --> @@Option
  741. call Redirect ; Redirect new drive
  742. jmp @@Exit ; Exit
  743. @@Option:
  744. mov al,[byte ptr ds:Line+1] ; Get option character
  745. call UpCase, ax ; Convert to uppercase
  746. cmp al,'V' ; Revision option ?
  747. je @@ShowRev
  748. cmp al,'M' ; MSCDEX option ?
  749. je @@MSCDEX ; Yes --> @@MSCDEX
  750. cmp al,'A' ; Alternate option ?
  751. je @@Alt ; Yes --> @@Alt
  752. cmp al,'F' ; Failure option ?
  753. je @@Failure ; Yes --> @@Failure
  754. cmp al,'I' ; Simulation option ?
  755. je @@Simulate ; Yes --> @@Simulate
  756. cmp al,'R' ; Run option ?
  757. je @@SetRun ; Yes --> @@SetRun
  758. cmp al,'D' ; DataFile option ?
  759. je @@Data ; Yes --> @@Data
  760. cmp al,'0' ; 0-free option ?
  761. je @@ZeroRet ; Yes --> @@ZeroRet
  762. cmp al,'L' ; Letter option ?
  763. je @@NewLetter ; Yes --> @@NewLetter
  764. cmp al,'Q' ; Quiet mode option ?
  765. je @@Quiet ; Yes --> @@Quiet
  766. cmp al,'?' ; Help option ?
  767. je @@Usage ; Yes --> @@Usage
  768. cmp al,'W' ; Write-protect option ?
  769. je @@WriteProt ; Yes --> @@WriteProt
  770. cmp al,'S' ; Speed option ?
  771. je @@SetSpeed ; Yes --> @@SetSpeed
  772. @@NotRedir:
  773. mov [cs:Quiet],0 ; Turn off quiet mode
  774. call LStrWrite, offset UnknownOp ; Write error message
  775. call LStrWrite, offset Line ; Write offending option
  776. call LStrWrite, offset CRLF ; Newline
  777. call CleanUp ; Clean up
  778. ExitCode 0001h ; Exit to dos
  779. @@ShowRev:
  780. call LStrWrite, offset RevMsg ; Show revision message
  781. call CleanUp ; Clean up
  782. ExitCode 0000h ; Exit to dos
  783. @@MSCDEX:
  784. mov al,[ds:Line+2] ; Get mscdex selection
  785. cmp al,'0' ; Default ?
  786. je @@Exit ; Yes --> @@Exit
  787. cmp al,'1' ; Audio through-put ?
  788. je @@Tru ; Yes --> @@Tru
  789. cmp al,'2' ; Coexist ?
  790. je @@CoExist ; Yes --> @@Coexist
  791. cmp al,'3' ; Coexist + audio through-put ?
  792. je @@CoExistTru ; Yes --> @@CoExistTru
  793. call LStrWrite, offset UnknownMSC ; Write error message
  794. call LStrWrite, offset Line ; Write offending option
  795. call LStrWrite, offset CRLF ; Newline
  796. call CleanUp ; Clean up
  797. ExitCode 0001h ; Exit to dos
  798. @@CoExist:
  799. mov [cs:CoMSCDEX],01h ; Set coexist flag
  800. jmp @@Exit ; Exit
  801. @@CoExistTru:
  802. mov [cs:CoMSCDEX],01h ; Set coexist flag
  803. @@Tru:
  804. mov [cs:AudioTru],01h ; Set audio throughput flag
  805. jmp @@Exit ; Exit
  806. @@Alt:
  807. mov [cs:AltSimul],01h ; Set alternate simulation flag
  808. jmp @@Exit ; Exit
  809. @@Failure:
  810. mov [cs:DoFailure],01h ; Set failure flag
  811. jmp @@Exit
  812. @@Simulate:
  813. mov al,[ds:Line+2] ; Get simulation selection
  814. sub al,'0' ; Calculate simulation no
  815. mov [cs:SimType],al ; Save it
  816. add al,'0' ; Adjust back to digits
  817. cmp al,'0' ; Physical simulation ?
  818. je @@SimPhys ; Yes --> @@SimPhys
  819. cmp al,'1' ; Subst simulation ?
  820. je @@SimSubst ; Yes --> @@SimSubst
  821. cmp al,'2' ; Remote simulation ?
  822. je @@SimRemote ; Yes --> @@SimRemote
  823. call LStrWrite, offset UnknownSim ; Write error message
  824. call LStrWrite, offset Line ; Write offending option
  825. call LStrWrite, offset CRLF ; Newline
  826. call CleanUp ; Clean up
  827. ExitCode 0001h ; Exit to dos
  828. @@SimPhys:
  829. mov [cs:SimFlag],0100000000000000b ; Save flags
  830. jmp @@Exit ; Exit
  831. @@SimSubst:
  832. mov [cs:SimFlag],0101000000000000b ; Save flags
  833. jmp @@Exit ; Exit
  834. @@SimRemote:
  835. mov [cs:SimFlag],0100000010000000b ; Save flags
  836. jmp @@Exit ; Exit
  837. @@SetSpeed:
  838. mov al,[ds:Line+2] ; Get speed selection
  839. sub al,'0' ; Calculate speed no
  840. mov [cs:CurSpeed],al ; Save it
  841. add al,'0' ; Adjust back to characters
  842. cmp al,'s' ; Super speed mode ?
  843. je @@Super ; Yes --> @@Super
  844. cmp al,'S' ; Super speed mode ?
  845. je @@Super ; Yes --> @@Super
  846. cmp al,'1' ; Single spin ?
  847. je @@Single ; Yes --> @@Single
  848. cmp al,'2' ; Double spin ?
  849. je @@Double ; Yes --> @@Double
  850. cmp al,'3' ; Triple spin ?
  851. je @@Triple ; Yes --> @@Triple
  852. cmp al,'4' ; Quadra spin ?
  853. je @@Quadra ; Yes --> @@Quadra
  854. cmp al,'6' ; Sexa spin ?
  855. je @@Sexa ; Yes --> @@Sexa
  856. cmp al,'8' ; Octa spin ?
  857. je @@Octa ; Yes --> @@Octa
  858. mov [cs:Quiet],0 ; Turn off quiet mode
  859. call LStrWrite, offset UnknownSpd ; Write error message
  860. call LStrWrite, offset Line ; Write offending option
  861. call LStrWrite, offset CRLF ; Newline
  862. call CleanUp ; Clean up
  863. ExitCode 0001h ; Exit to dos
  864. @@Super:
  865. mov [cs:CurSpeed],0 ; Set super speed mode
  866. mov [cs:CurDelay],0 ; Set super speed delay
  867. jmp @@Exit ; Exit
  868. @@Single:
  869. mov [cs:CurDelay],13000 ; Set single spin delay
  870. jmp @@Exit ; Exit
  871. @@Double:
  872. mov [cs:CurDelay],6200 ; Set double spin delay
  873. jmp @@Exit ; Exit
  874. @@Triple:
  875. mov [cs:CurDelay],4200 ; Set triple spin delay
  876. jmp @@Exit ; Exit
  877. @@Quadra:
  878. mov [cs:CurDelay],3100 ; Set quadra spin delay
  879. jmp @@Exit ; Exit
  880. @@Sexa:
  881. mov [cs:CurDelay],2000 ; Set sexa spin delay
  882. jmp @@Exit ; Exit
  883. @@Octa:
  884. mov [cs:CurDelay],1700 ; Set octa spin delay
  885. jmp @@Exit ; Exit
  886. @@Data:
  887. lea si,[Line+2] ; /Dxxx, xxx in ds:si
  888. lea di,[DataName] ; DataName in ds:di
  889. cld ; Forward copy
  890. @@DataLoop:
  891. lodsb ; Get character
  892. mov [ds:di],al ; Store character
  893. inc di ; Skip character
  894. test al,al ; End of parameter ?
  895. jnz @@DataLoop ; No --> @@DataLoop
  896. call TrueName, ds offset DataName ; Fix
  897. jmp @@Exit ; Exit
  898. @@SetRun:
  899. lea si,[Line+2] ; /Rxxx, xxx in ds:si
  900. lea di,[RunName] ; RunName in ds:di
  901. cld ; Forward copy
  902. @@SetRunLoop:
  903. lodsb ; Get character
  904. mov [cs:di],al ; Store character
  905. inc di ; Skip character
  906. test al,al ; End of parameter ?
  907. jnz @@SetRunLoop ; No --> @@SetRunLoop
  908. call TrueName, cs offset RunName ; Fix
  909. jmp @@Exit ; Exit
  910. @@ZeroRet:
  911. mov [cs:RetZero],1 ; Set zero free flag
  912. jmp @@Exit ; Exit
  913. @@WriteProt:
  914. mov [cs:WriteProt],1 ; Set write-protect flag
  915. jmp @@Exit ; Exit
  916. @@NewLetter:
  917. cmp [AnyRedir],01h ; Any redirections already ?
  918. je @@OnlyBeforeFirst ; Yes --> @@OnlyBeforeFirst
  919. mov al,[byte ptr ds:Line+2] ; Get drive letter
  920. call UpCase, ax ; Convert to uppercase
  921. cmp al,'D' ; <D ?
  922. jb @@NotOk ; Yes --> @@NotOk
  923. cmp al,'Z' ; >Z ?
  924. ja @@NotOk ; Yes --> @@NotOk
  925. mov [cs:FirstID],al ; Save first id to use
  926. mov [DriveID],al ; Save current id to use
  927. jmp @@Exit ; Exit
  928. @@OnlyBeforeFirst:
  929. mov [cs:Quiet],0 ; Turn off quiet mode
  930. call LStrWrite, offset InvDrive ; Write error message
  931. call LStrWrite, offset Line ; Write offending option
  932. call LStrWrite, offset CRLF ; Newline
  933. call CleanUp ; Clean up
  934. ExitCode 0001h ; Exit to dos
  935. @@NotOk:
  936. mov [cs:Quiet],0 ; Turn off quiet mode
  937. call LStrWrite, offset InvOption ; Write error message
  938. call LStrWrite, offset Line ; Write offending option
  939. call LStrWrite, offset CRLF ; Newline
  940. call CleanUp ; Clean up
  941. ExitCode 0001h ; Exit to dos
  942. @@Quiet:
  943. mov [cs:Quiet],01h ; Turn on quiet mode
  944. jmp @@Exit ; Exit
  945. @@Usage:
  946. mov [cs:Quiet],0 ; Turn off quiet mode
  947. call LStrWrite, offset UsageMsg ; Write error message
  948. Call CleanUp ; Clean up
  949. ExitCode 0000h ; Exit to dos
  950. @@Exit:
  951. ret ; Return to caller
  952. endp
  953. ; Redirect procedure
  954. proc Redirect far
  955. uses si, ax, es, bx
  956. local @@TempCDS:dword
  957. cmp [cs:DriveCount],MaxCDs ; Already redirected max ?
  958. jb @@RoomForMore ; No --> @@RoomForMore
  959. mov [cs:Quiet],0 ; Turn off quiet mode
  960. call LStrWrite, offset TooManyCDs ; Write error message
  961. call CleanUp ; Clean up
  962. ExitCode 0001h ; Exit to dos
  963. @@RoomForMore:
  964. cmp [DriveID],'[' ; Exhausted drive letters ?
  965. jb @@OkDrives ; No --> @@OkDrives
  966. mov [cs:Quiet],0 ; Turn off quiet mode
  967. call LStrWrite, offset NotRoom ; Write error message
  968. call CleanUp ; Clean up
  969. ExitCode 0001h ; Exit to dos
  970. @@OkDrives:
  971. mov [AnyRedir],1 ; Set redirected flag
  972. call LStrWrite, offset Prompt1 ; Write message
  973. call LStrWrite, offset DriveID ; Write new drive id
  974. call LStrWrite, offset Prompt2 ; Write rest of message
  975. call StrCopy, ds offset PathName, ds offset Line ; Copy path
  976. call TrueName, ds offset PathName ; Fix it
  977. push si ; Save si
  978. lea si,[PathName] ; Pathname in ds:si
  979. @@CheckBackslash:
  980. cmp [byte ptr ds:si],00h ; End of pathname ?
  981. je @@OkEnd ; Yes --> @@OkEnd
  982. inc si ; Next character
  983. jmp @@CheckBackslash ; Loop
  984. @@OkEnd:
  985. cmp [byte ptr ds:si-1],00h ; Last character was 
  986. jne @@OkBackslash ; No --> @@OkBackslash
  987. mov [byte ptr ds:si-1],'' ; Remove last
  988. mov [byte ptr ds:si],00h ; Remove last
  989. @@OkBackslash:
  990. pop si ; Restore si
  991. call LStrWrite, offset PathName ; Write pathname
  992. call LStrWrite, offset CRLF ; Newline
  993. mov al,[byte ptr PathName] ; Get drive letter
  994. call GetCDS, ax ; Get CDS pointer
  995. mov [word ptr @@TempCDS],bx ; Save offset
  996. mov [word ptr @@TempCDS+2],es ; Save segment
  997. mov al,[DriveID] ; Get drive id
  998. call GetCDS, ax ; Get CDS pointer
  999. cmp [word ptr es:bx+67],0000h ; Drive letter available
  1000. jne @@NotAvail ; No --> @@NotAvail
  1001. cmp [word ptr es:bx+69],0000h ; Drive letter available
  1002. jne @@NotAvail ; No --> @@NotAvail
  1003. cmp [word ptr es:bx+71],0000h ; Drive letter available
  1004. jne @@NotAvail ; No --> @@NotAvail
  1005. call CopyData, [@@TempCDS], es bx, 88 ; Copy host CDS
  1006. call StrCopy, es bx, ds offset PathName ; Copy pathname
  1007. call StrLen, ds offset PathName ; Calculate length of path
  1008. mov si,ax ; Get length
  1009. add si,bx ; Adjust into CDS
  1010. cmp [byte ptr es:si-1],'' ; Last was  ?
  1011. jne @@OkLength ; No --> @@OkLength
  1012. dec ax ; Adjust path
  1013. @@OkLength:
  1014. mov [es:bx+79],ax ; Hide redirected path
  1015. mov ax,[cs:SimFlag] ; Get flags
  1016. xor ax,1111111111111111b ; Make mask
  1017. and [es:bx+67],ax ; Mask out bits to set
  1018. xor ax,1111111111111111b ; Make flag
  1019. or [es:bx+67],ax ; Set bits
  1020. mov al,[DriveID] ; Get drive id
  1021. mov [SimDrv],al ; Update simulation message
  1022. call LStrWrite, offset SimMsg1 ; Write simulation message
  1023. cmp [cs:SimType],00h ; Simulate physical ?
  1024. je @@Sim00 ; Yes --> @@Sim00
  1025. cmp [cs:SimType],01h ; Simulate substed ?
  1026. je @@Sim01 ; Yes --> @@Sim01
  1027. @@Sim02:
  1028. call LStrWrite, offset SimMsg4 ; Write physical message
  1029. jmp @@SimOk ; Ok
  1030. @@NotAvail:
  1031. call LStrWrite, offset TooFew ; Write error message
  1032. call CleanUp ; Clean up
  1033. ExitCode 0001h ; Exit to dos
  1034. @@Sim00:
  1035. call LStrWrite, offset SimMsg2 ; Write substed message
  1036. jmp @@SimOk ; Ok
  1037. @@Sim01:
  1038. call LStrWrite, offset SimMsg3 ; Write remote message
  1039. @@SimOk:
  1040. mov al,[DriveID] ; Get drive id
  1041. call SetSpeed,ax ; Set speed of drive
  1042. call FixDrive ; Update dos buffers for drive
  1043. mov al,[DriveID] ; Get drive id
  1044. mov [cs:LastID],al ; Update LastID
  1045. call GetCDData, ax ; Read data from file
  1046. mov al,[DriveID] ; Get drive id
  1047. inc [byte ptr DriveID] ; Update DriveID
  1048. inc [byte ptr cs:DriveCount] ; Update DriveCount
  1049. mov [SpeedDrv],al ; Update message
  1050. call LStrWrite, offset SpeedMsg1 ; Write message
  1051. cmp [cs:CurSpeed],0 ; Superspeed ?
  1052. jne @@NotSuper ; No --> @@NotSuper
  1053. call LStrWrite, offset SuperMsg ; Write super message
  1054. jmp @@SpeedOk ; --> @@SpeedOk
  1055. @@NotSuper:
  1056. cmp [cs:CurSpeed],1 ; Single spin ?
  1057. jne @@NotSingle ; No --> @@NotSingle
  1058. call LStrWrite, offset SingleMsg ; Write single message
  1059. jmp @@SpeedOk ; --> @@SpeedOk
  1060. @@NotSingle:
  1061. cmp [cs:CurSpeed],2 ; Double spin ?
  1062. jne @@NotDouble ; No --> @@NotDouble
  1063. call LStrWrite, offset DoubleMsg ; Write double message
  1064. jmp @@SpeedOk ; --> @@SpeedOk
  1065. @@NotDouble:
  1066. cmp [cs:CurSpeed],3 ; Triple spin ?
  1067. jne @@NotTriple ; No --> @@NotTriple
  1068. call LStrWrite, offset TripleMsg ; Write triple message
  1069. jmp @@SpeedOk ; --> @@SpeedOk
  1070. @@NotTriple:
  1071. cmp [cs:CurSpeed],4 ; Quadra spin ?
  1072. jne @@NotQuadra ; No --> @@NotQuadra
  1073. call LStrWrite, offset QuadraMsg ; Write quadra message
  1074. jmp @@SpeedOk ; --> @@SpeedOk
  1075. @@NotQuadra:
  1076. cmp [cs:CurSpeed],6 ; Sexa spin ?
  1077. jne @@NotSexa ; No --> @@NotSexa
  1078. call LStrWrite, offset SexaMsg ; Write sexa message
  1079. jmp @@SpeedOk ; --> @@SpeedOk
  1080. @@NotSexa:
  1081. call LStrWrite, offset OctaMsg ; Write octa message
  1082. @@SpeedOk:
  1083. call LStrWrite, offset SpeedMsg2 ; Write end of message
  1084. ret ; Return to caller
  1085. endp
  1086. ; SetSpeed procedure
  1087. proc SetSpeed
  1088. arg @@DriveID:word
  1089. uses ax, bx
  1090. mov bl,[byte ptr @@DriveID] ; Get drive id
  1091. sub bl,[cs:FirstID] ; Make 0-based
  1092. xor bh,bh ; Make 16-bit
  1093. shl bx,1 ; Multiply with 2 (make index)
  1094. mov ax,[CurDelay] ; Get current delay
  1095. mov [cs:DriveSpeeds+bx],ax ; Save in DriveSpeeds
  1096. ret ; Return to caller
  1097. endp
  1098. ; FixDrive procedure
  1099. proc FixDrive
  1100. uses ax, dx
  1101. lea dx,[PathName] ; PathName in ds:dx
  1102. mov al,[DriveID] ; Get drive id
  1103. mov [PathName],al ; Store in pathname
  1104. mov [byte ptr PathName+1],':' ; Make into 'D:',0
  1105. mov [byte ptr PathName+2],'' ; ...
  1106. mov [byte ptr PathName+3],0 ; ...
  1107. mov ah,3bh ; Dos Fn 3bh = ChDir
  1108. int 21h ; Call DOS interrupt
  1109. ret ; Return to caller
  1110. endp
  1111. ; CopyData procedure
  1112. proc CopyData far
  1113. arg @@Source:dword, @@Dest:dword, @@Length:word
  1114. uses ds, si, es, di, cx
  1115. cld ; Forward copy
  1116. lds si,[dword ptr @@Source] ; Source in ds:si
  1117. les di,[dword ptr @@Dest] ; Destination in es:di
  1118. mov cx,[@@Length] ; Length in cx
  1119. rep movsb ; Copy it
  1120. ret ; Return to caller
  1121. endp
  1122. ; TrueName procedure
  1123. proc TrueName far
  1124. arg @@Dest:dword
  1125. uses ax, ds, es, si, di
  1126. mov ah,60h ; Dos Fn 60h = TrueName
  1127. lds si,[dword ptr @@Dest] ; Source in ds:si
  1128. les di,[dword ptr @@Dest] ; Destination in es:di
  1129. int 21h ; Call DOS interrupt
  1130. ret ; Return to caller
  1131. endp
  1132. ; ZeroDefault procedure
  1133. proc ZeroDefault
  1134. arg @@DriveNo:word
  1135. mov al,[byte ptr @@DriveNo]
  1136. cmp al,0 ; Default drive (0) ?
  1137. je @@IsDefault ; Yes --> @@IsDefault
  1138. add al,'@' ; Convert to A-Z
  1139. jmp @@Exit ; Exit
  1140. @@IsDefault:
  1141. mov ah,19h ; Dos Fn 19h = GetCurDrive
  1142. int 21h ; Call DOS interrupt
  1143. add al,'A' ; Convert to A-Z
  1144. @@Exit:
  1145. ret ; Return to caller
  1146. endp
  1147. ; IsOwn procedure
  1148. proc IsOwn
  1149. arg @@DriveID:word, @@Redirect:word
  1150. uses ax, es, bx, dx
  1151. call UpCase, [@@DriveID] ; Convert id to uppercase
  1152. mov [@@DriveID],ax ; Store new id
  1153. cmp [@@Redirect],0 ; Redirect before checking ?
  1154. jne @@CheckIt ; No --> @@CheckIt
  1155. mov al,[byte ptr @@DriveID] ; Get drive id in al
  1156. cmp al,[cs:FirstID] ; < First ID ?
  1157. jb @@Nope ; Yes --> @@Nope
  1158. cmp al,[cs:LastID] ; > Last ID ?
  1159. ja @@Nope ; Yes --> @@Nope
  1160. jmp @@GotIt ; Got it
  1161. @@CheckIt:
  1162. mov al,[cs:FirstID] ; Get first emulated id
  1163. @@GetLoop:
  1164. call GetCDS,ax ; Get CDS entry
  1165. mov bl,[es:bx] ; Get host drive letter
  1166. cmp bl,[byte ptr @@DriveID] ; Id to check ?
  1167. je @@GotIt ; Yes --> @@GotIt
  1168. inc al ; Next drive
  1169. cmp al,[cs:LastID] ; Our drive ?
  1170. jbe @@GetLoop ; Yes --> @@GetLoop
  1171. @@Nope:
  1172. clc ; Signal external drive
  1173. jmp @@Exit ; Exit
  1174. @@GotIt:
  1175. stc ; Signal own drive
  1176. @@Exit:
  1177. ret ; Return to caller
  1178. endp
  1179. ; NewInt21
  1180. OldInt21 dw 0,0
  1181. proc NewInt21 far
  1182. cmp ah,4eh ; FindFirst function ?
  1183. je @@FindFirst ; Yes --> @@FindFirst
  1184. cmp ah,36h ; DiskFree function ?
  1185. je @@DiskFree ; Yes --> @@DiskFree
  1186. cmp [cs:WriteProt],00h ; Writeprotect flag ?
  1187. je @@NotWriteProtected ; No --> @@NotWriteProtected
  1188. cmp ah,3ch ; CreateFile function ?
  1189. je @@DoKillSomething ; Yes --> @@DoKillSomething
  1190. cmp ah,0fh ; Open FCB function ?
  1191. je @@DoFCB ; Yes --> @@DoFCB
  1192. cmp ah,16h ; Create FCB function ?
  1193. je @@DoFCB ; Yes --> @@DoFCB
  1194. cmp ah,17h ; Rename FCB function ?
  1195. je @@DoFCB ; Yes --> @@DoFCB
  1196. cmp ah,39h ; MkDir function ?
  1197. je @@DoKillSomething ; Yes --> @@DoKillSomething
  1198. cmp ah,3ah ; RmDir function ?
  1199. je @@DoKillSomething ; Yes --> @@DoKillSomething
  1200. cmp ah,41h ; Delete file function ?
  1201. je @@DoKillSomething ; Yes --> @@DoKillSomething
  1202. @@NotWriteProtected:
  1203. jmp @@CallOld ; Call old interrupt handler
  1204. @@DoKillSomething:
  1205. push si ; Save si
  1206. mov si,dx ; ds:dx = Filename
  1207. cmp [byte ptr ds:si+1],':' ; Contains drive letter ?
  1208. je @@HasDriveToKill ; Yes --> @@HasDriveToKill
  1209. push ax ; Save ax
  1210. mov ah,19h ; Dos Fn 19h = GetCurDrive
  1211. int 21h ; Call DOS interrupt
  1212. mov [@@TempB],al ; Save drive letter
  1213. pop ax ; Restore ax
  1214. mov al,[@@TempB] ; Drive letter in al
  1215. pop si ; Restore si
  1216. add al,'A' ; Convert to A-Z
  1217. jmp @@KillIt ; --> @@KillIt
  1218. @@HasDriveToKill:
  1219. mov al,[ds:si] ; Get drive letter
  1220. pop si ; Restore si
  1221. @@KillIt:
  1222. call IsOwn, ax, 0000h ; Our drive ?
  1223. jnc @@CallOld ; No --> @@CallOld
  1224. iSTC ; Signal error
  1225. mov ax,0013h ; Write protected error
  1226. iret ; Return to interrupt caller
  1227. @@DoFCB:
  1228. push si ; Save si
  1229. mov si,dx ; Filename in ds:si
  1230. mov al,[ds:si] ; Get drive no
  1231. pop si ; Restore si
  1232. call ZeroDefault, ax ; Calculate drive letter
  1233. call IsOwn, ax, 0001h ; Our drive ?
  1234. jnc @@CallOld ; No --> @@CallOld
  1235. mov al,0ffh ; Signal error
  1236. iret ; Return to interrupt caller
  1237. @@DiskFree:
  1238. cmp [cs:RetZero],1 ; Return zero free ?
  1239. jne @@CallOld ; No --> @@CallOld
  1240. push ax bx cx dx ; Save registers
  1241. call ZeroDefault, dx ; Calculate drive letter
  1242. call IsOwn, ax, 0000h ; Our drive ?
  1243. jc @@FakeIt ; Yes --> @@FakeIt
  1244. call IsOwn, ax, 0001h ; Our drive ?
  1245. jnc @@NotFree ; No --> @@NotFree
  1246. @@GotIt:
  1247. pop dx cx bx ax ; Restore registers
  1248. int 66h ; Call old interrupt handler
  1249. cmp ax,0ffffh ; Error ?
  1250. je @@DiskFreeError ; No --> @@NoDiskFreeError
  1251. xor bx,bx ; 0 clusters free
  1252. @@DiskFreeError:
  1253. iret ; Return to interrupt caller
  1254. @@FakeIt:
  1255. pop dx cx bx ax ; Restore registers
  1256. push ax dx ds si ; Save registers
  1257. call ZeroDefault, dx ; Calculate drive id
  1258. call GetData, ax ; Get cd data structure
  1259. jc @@NoFreeData ; Error --> @@NoFreeData
  1260. mov ax,[ds:si+153] ; Get sectors per cluster
  1261. mov bx,[ds:si+155] ; Get available clusters
  1262. mov cx,[ds:si+157] ; Get bytes per sector
  1263. mov dx,[ds:si+159] ; Get total clusters
  1264. pop si ds ; Restore registers
  1265. add sp,4 ; Remove two words from stack
  1266. iCLC ; Signal ok
  1267. iret ; Return to interrupt caller
  1268. @@NoFreeData:
  1269. pop si ds dx ax ; Restore registers
  1270. mov ax,0001h ; 1 sector per cluster
  1271. mov bx,0000h ; 0 sectors free
  1272. mov cx,0800h ; 2048 bytes per sector
  1273. mov dx,0ffffh ; 65535 total clusters
  1274. iCLC ; Signal ok
  1275. iret ; Return to interrupt caller
  1276. @@NotFree:
  1277. pop dx cx bx ax ; Restore registers
  1278. jmp @@CallOld ; Call old interrutp handler
  1279. @@FindFirst:
  1280. test cx,0008h ; Volume label search ?
  1281. jz @@CallOld ; No --> @@CallOld
  1282. @@CheckLabel:
  1283. push es bx ds si ax dx ; Save registers
  1284. mov si,dx ; Filename in ds:si
  1285. cmp [byte ptr ds:si+1],':' ; Contains drive letter ?
  1286. je @@OkDrive ; Yes --> @@OkDrive
  1287. push ax ; Save ax
  1288. mov ah,19h ; Dos Fn 19h = GetCurDrive
  1289. int 21h ; Call DOS interrupt
  1290. mov [@@TempB],al ; Save drive letter
  1291. pop ax ; Restore ax
  1292. mov al,[@@TempB] ; Get drive letter
  1293. mov bl,al ; Put drive letter in bl
  1294. jmp @@CheckDrive ; --> @@CheckDrive
  1295. @@OkDrive:
  1296. mov bl,[ds:si] ; Get drive letter
  1297. push ax ; Save ax
  1298. call UpCase, bx ; Convert to uppercase
  1299. mov bx,ax ; Put new letter in bx
  1300. pop ax ; Restore ax
  1301. @@CheckDrive:
  1302. cmp bl,[cs:FirstID] ; Our drive ?
  1303. jb @@DoCallOld ; No --> @@DoCallOld
  1304. cmp bl,[cs:LastID] ; Our drive ?
  1305. ja @@DoCallOld ; No --> @@DoCallOld
  1306. jmp @@CheckOk ; --> @@CheckOk
  1307. @@DoCallOld:
  1308. pop dx ax si ds bx es ; Restore registers
  1309. jmp @@CallOld ; Call old interrupt handler
  1310. @@CheckOk:
  1311. call GetData, bx ; Get cd data
  1312. jc @@NoLabel ; No data --> @@NoLabel
  1313. add si,141 ; Adjust offset
  1314. cmp [byte ptr ds:si],0 ; Label ?
  1315. je @@NoLabel ; No --> @@NoLabel
  1316. mov ah,2fh ; Get DTA pointer
  1317. int 21h ; Call DOS interrupt
  1318. mov [byte ptr es:bx+15h],08h ; Set attribute
  1319. mov [word ptr es:bx+16h],0000h ; Zero time
  1320. mov [word ptr es:bx+18h],0000h ; Zero date
  1321. mov [word ptr es:bx+1ah],0000h ; Zero size low
  1322. mov [word ptr es:bx+1ch],0000h ; Zero size high
  1323. add bx,001eh ; Adjust offset
  1324. @@Loop:
  1325. mov al,[ds:si] ; Get character
  1326. inc si ; Skip character read
  1327. mov [es:bx],al ; Store character
  1328. inc bx ; Skip character stored
  1329. test al,al ; End of label ?
  1330. jnz @@Loop ; No --> @@Loop
  1331. pop dx ax si ds bx es ; Restore registers
  1332. iCLC ; Signal success
  1333. jmp @@Exit ; Exit
  1334. @@NoLabel:
  1335. pop dx ax si ds bx es ; Restore registers
  1336. iSTC ; Signal failure
  1337. mov ax,0002h ; File not found error
  1338. iret ; Return to interrupt caller
  1339. @@CallOld:
  1340. jmp [dword ptr cs:OldInt21] ; Call old interrupt handler
  1341. @@Exit:
  1342. iret ; Return to interrupt caller
  1343. @@TempB db 1
  1344. @@TempW dw 0
  1345. endp
  1346. ; GetData procedure
  1347. proc GetData
  1348. uses cx
  1349. arg @@DriveID:word
  1350. mov cx,[@@DriveID] ; Get drive ID
  1351. cmp cl,[cs:FirstID] ; Our drive ?
  1352. jb @@NoData ; No --> @@NoData
  1353. cmp cl,[cs:LastID] ; Our drive ?
  1354. ja @@NoData ; No --> @@NoData
  1355. lea si,[Datas] ; ds:si --> Datas
  1356. sub cl,[cs:FirstID] ; Make drive id 0-based
  1357. cmp cl,0 ; First id ?
  1358. je @@OkData ; Yes --> @@OkData
  1359. @@NextData:
  1360. add si,2 ; Next index in Datas
  1361. dec cl ; Next drive
  1362. jnz @@NextData ; More --> @@NextData
  1363. @@OkData:
  1364. mov si,[cs:si] ; Get segment of data
  1365. test si,si ; Data there ?
  1366. jz @@NoData ; No --> @@NoData
  1367. mov ds,si ; Put segment in ds
  1368. xor si,si ; Zero offset
  1369. clc ; Signal success
  1370. jmp @@Exit ; Exit
  1371. @@NoData:
  1372. stc ; Signal failure
  1373. @@Exit:
  1374. ret ; Return to caller
  1375. endp
  1376. ; NewInt2F
  1377. OldInt2F dw 0,0
  1378. proc NewInt2f far
  1379. mov [cs:@@OldAX],ax
  1380. cmp ax,1100h ; MSCDEX check ?
  1381. je @@CheckMSCDEX ; Yes --> @@CheckMSCDEX
  1382. cmp ax,1500h ; Installation check ?
  1383. je @@CheckInstall ; Yes --> @@CheckInstall
  1384. cmp ax,1501h ; DeviceList function ?
  1385. je @@DeviceList ; Yes --> @@DeviceList
  1386. cmp ax,1502h ; GetCopyright function ?
  1387. je @@GetFileName ; Yes --> @@GetFileName
  1388. cmp ax,1503h ; GetAbstract function ?
  1389. je @@GetFilename ; Yes --> @@GetFileName
  1390. cmp ax,1504h ; GetBibliographical function ?
  1391. je @@GetFilename ; Yes --> @@GetFileName
  1392. cmp [cs:AltSimul],01h ; Alternate simulation ?
  1393. je @@AltSimul
  1394. cmp ax,1505h ; VTOC read function ?
  1395. je @@ReadVTOC ; Yes --> @@ReadVTOC
  1396. cmp ax,1508h ; Absolute read function ?
  1397. je @@AbsRead ; Yes --> @@AbsRead
  1398. cmp ax,1509h ; Absolute write function ?
  1399. je @@Dummy ; Yes --> @@Dummy
  1400. cmp ax,150bh ; DriveCheck function ?
  1401. je @@DriveCheck ; Yes --> @@DriveCheck
  1402. cmp ax,150ch ; Version check function ?
  1403. je @@GetVersion ; Yes --> @@CheckVersion
  1404. cmp ax,150eh ; Descriptor function ?
  1405. je @@GetDescriptorPreference ; Yes --> @@GetDescriptorPreference
  1406. cmp ax,150fh ; Get directory entry ?
  1407. je @@GetDirEntry ; Yes --> @@GetDirEntry
  1408. cmp ax,1510h ; Device request ?
  1409. je @@DeviceRqz ; Yes --> @@DeviceRqz
  1410. cmp ax,150dh ; DriveList function ?
  1411. je @@DriveList ; Yes --> @@DriveList
  1412. @@CallOld:
  1413. mov ax,[cs:@@OldAX]
  1414. jmp [dword ptr cs:OldInt2F] ; Call old interrupt handler
  1415. @@AltSimul:
  1416. cmp ax,150bh ; DriveCheck function ?
  1417. je @@DriveCheck ; Yes --> @@DriveCheck
  1418. cmp ax,150ch ; Version check function ?
  1419. je @@GetVersion ; Yes --> @@CheckVersion
  1420. cmp ax,150dh ; DriveList function ?
  1421. je @@DriveList ; Yes --> @@DriveList
  1422. cmp ax,1510h ; Device request ?
  1423. je @@SuccessDev ; Yes --> @@SuccessDev
  1424. jmp @@CallOld ; Call old
  1425. @@AbsRead:
  1426. test dx,dx ; Sector count > 0 ?
  1427. jz @@ReadFinished ; Yes --> @@ReadFinished
  1428. push cx ds si ; Save registers
  1429. add cl,'A' ; Convert drive letter to A-Z
  1430. push ax ; Save ax
  1431. call GetSpeed, cx ; Get drive speed
  1432. mov [@@DelaySize],ax ; Save speed of delay
  1433. pop ax ; Restore ax
  1434. call GetData, cx ; Get cd data
  1435. jc @@NoAbsRead ; Error --> @@NoAbsRead
  1436. mov si,[ds:si+2] ; Adjust offset
  1437. cmp si,0ffffh ; Sector data ?
  1438. je @@NoAbsRead ; No --> @@NoAbsRead
  1439. push bx dx ; Save registers
  1440. @@ReadDataLoop:
  1441. push ds si es bx ; Save registers
  1442. call DeCrunch, ds si, es bx ; Decrunch sector data
  1443. pop bx es si ds ; Restore registers
  1444. add bx,2048 ; Next sector offset
  1445. dec dx ; One less sector to read
  1446. jnz @@ReadDataLoop ; More --> @@ReadDataLoop
  1447. pop dx bx si ds cx ; Restore registers
  1448. @@ReadFinished:
  1449. push ax cx dx ; Save registers
  1450. cmp [@@DelaySize],0 ; Any delay ?
  1451. je @@NoDelay ; No --> @@NoDelay
  1452. @@DelayLoop:
  1453. test dx,dx ; Sectors = 0 ?
  1454. jz @@NoDelay ; Yes --> @@NoDelay
  1455. push dx ; Save dx
  1456. mov ah,86h ; AT Fn 86h = Wait
  1457. mov cx,0 ; High 16 bit of delay
  1458. mov dx,[@@DelaySize] ; Low 16 bit of delay
  1459. int 15h ; Call AT interrupt
  1460. pop dx ; Restore dx
  1461. dec dx ; One less delay to perform
  1462. jmp @@DelayLoop ; Loop
  1463. @@NoDelay:
  1464. pop dx cx ax ; Restore registers
  1465. iCLC ; Signal success
  1466. iret ; Return to interrupt caller
  1467. @@NoAbsRead:
  1468. pop si ds cx ; Restore registers
  1469. cmp [cs:DoFailure],01h ; Failure on exit ?
  1470. jne @@Dummy ; No --> @@Dummy
  1471. iSTC ; Signal failure
  1472. mov ax,0015h ; Drive not ready error
  1473. iret ; Return to interrupt caller
  1474. @@GetDescriptorPreference:
  1475. cmp bx,0 ; Get function ?
  1476. je @@GetPreference ; Yes --> @@GetPreference
  1477. iCLC ; Signal success
  1478. iret ; Return to interrupt caller
  1479. @@GetPreference:
  1480. mov dx,0100h ; Set return bits
  1481. iCLC ; Signal success
  1482. iret ; Return to interrupt caller
  1483. @@Dummy:
  1484. iCLC ; Signal success
  1485. iret ; Return to interrupt caller
  1486. @@ReadVTOC:
  1487. push ds si ; Save registers
  1488. add cl,'A' ; Convert id to A-Z
  1489. call GetData, cx ; Get cd data
  1490. jc @@HasNoVTOC ; Error --> @@HasNoVTOC
  1491. mov si,[ds:si] ; Adjust offset
  1492. @@GetVTOC:
  1493. cmp [word ptr ds:si],0ffffh ; Last sector ?
  1494. je @@ReadFlags ; Yes --> @@ReadFlags
  1495. cmp [ds:si],dx ; Sector wanted ?
  1496. je @@ReadTheVTOC ; Yes --> @@ReadFlags
  1497. add si,2 ; Skip index word
  1498. add si,[word ptr ds:si] ; Skip _ax+_flags+data
  1499. jmp @@GetVTOC ; Loop
  1500. @@ReadTheVTOC:
  1501. push ax cx si ; Save registers
  1502. add si,8 ; Adjust offset
  1503. call DeCrunch, ds si, es bx ; Decrunch sector
  1504. pop si cx ax ; Restore registers
  1505. @@ReadFlags:
  1506. mov ax,[word ptr ds:si+6] ; Get flags to return
  1507. push bp ; Save bp
  1508. mov bp,sp ; Point bp to sp in stack
  1509. mov [word ptr bp+10],ax ; Adjust flags on stack
  1510. pop bp ; Restore bp
  1511. mov ax,[word ptr ds:si+4] ; Get ax to return
  1512. pop si ds ; Restore registers
  1513. cmp [cs:DoFailure],01h ; Failure on exit ?
  1514. jne @@Dummy ; No --> @@Dummy
  1515. mov al,17h
  1516. iSTC ; Signal failure
  1517. iret ; Return to interrupt caller
  1518. @@HasNoVTOC:
  1519. pop si ds ; Restore registers
  1520. @@NoVTOC:
  1521. cmp [cs:DoFailure],01h ; Failure on exit ?
  1522. jne @@Dummy ; No --> @@Dummy
  1523. iSTC ; Signal failure
  1524. mov al,17h ; Error code
  1525. iret ; Return to interrupt caller
  1526. @@DeviceRqz:
  1527. mov cl,[cs:FirstRealCD] ; Get the real cd-drive
  1528. mov al,[byte ptr es:bx+2] ; Get device command code
  1529. cmp al,1 ; Media check function ?
  1530. je @@ErrRqz ; Yes --> @@ErrRqz
  1531. cmp al,2 ; Build BPB ?
  1532. je @@ErrRqz ; Yes --> @@ErrRqz
  1533. cmp al,3 ; IOCTL input ?
  1534. je @@IOCTLI ; Yes --> @@IOCTLI
  1535. cmp al,4 ; Input ?
  1536. je @@ErrRqz ; Yes --> @@ErrRqz
  1537. cmp al,5 ; Nondestructive read ?
  1538. je @@ErrRqz ; Yes --> @@ErrRqz
  1539. cmp al,6 ; Input status ?
  1540. je @@ErrRqz ; Yes --> @@ErrRqz
  1541. cmp al,8 ; Output ?
  1542. je @@ErrRqz ; Yes --> @@ErrRqz
  1543. cmp al,9 ; Output with verify ?
  1544. je @@ErrRqz ; Yes --> @@ErrRqz
  1545. cmp al,10 ; Output status ?
  1546. je @@ErrRqz ; Yes --> @@ErrRqz
  1547. cmp al,11 ; Output flush ?
  1548. je @@ErrRqz ; Yes --> @@ErrRqz
  1549. cmp al,12 ; IOCTL output ?
  1550. je @@IOCTLO ; Yes --> @@IOCTLO
  1551. cmp al,15 ; Removable media ?
  1552. je @@ErrRqz ; Yes --> @@ErrRqz
  1553. cmp al,16 ; Output until busy ?
  1554. je @@ErrRqz ; Yes --> @@ErrRqz
  1555. cmp al,129 ; Reserved ?
  1556. je @@ErrRqz ; Yes --> @@ErrRqz
  1557. cmp al,132 ; Play audio ?
  1558. je @@Play ; Yes --> @@Play
  1559. cmp al,133 ; Stop audio ?
  1560. je @@Stop ; Yes --> @@Stop
  1561. cmp al,134 ; Read long verify ?
  1562. je @@ErrRqz ; Yes --> @@ErrRqz
  1563. cmp al,135 ; Write long verify ?
  1564. je @@ErrRqz ; Yes --> @@ErrRqz
  1565. cmp al,136 ; Resume audio ?
  1566. je @@Play ; Yes --> @@Play
  1567. @@SuccessDev:
  1568. mov [word ptr es:bx+03],0100h ; Set success status
  1569. iret ; Return to interrupt caller
  1570. @@Play:
  1571. cmp [cs:AudioTru],01h ; Audio through-put ?
  1572. je @@CallOld ; Yes --> @@CallOld
  1573. mov [cs:CDPlaying],0000h ; Set flags
  1574. jmp @@SuccessDev ; Success
  1575. @@Stop:
  1576. cmp [cs:AudioTru],01h ; Audio through-put ?
  1577. je @@CallOld ; Yes --> @@CallOld
  1578. mov [cs:CDPlaying],0001h ; Set flags
  1579. jmp @@SuccessDev ; Success
  1580. @@FailureDev:
  1581. mov [byte ptr es:bx+04],80h ; Set success status
  1582. mov [byte ptr es:bx+03],al ; Set failure code
  1583. iret ; Return to interrupt caller
  1584. @@IOCTLO:
  1585. cmp [cs:AudioTru],01h ; Audio through-put ?
  1586. je @@CallOld ; Yes --> @@CallOld
  1587. jmp @@SuccessDev ; Set success status
  1588. @@IOCTLI:
  1589. mov [word ptr es:bx+03],0 ; Signal ok for now
  1590. push es bx ; Save registers
  1591. les bx,[es:bx+14] ; Get pointer to data
  1592. mov al,[es:bx] ; Get data command byte
  1593. pop bx es ; Restore registers
  1594. cmp al,0 ; Address of device header ?
  1595. je @@NotReady ; Yes --> @@NotReady
  1596. cmp al,1 ; Location of head ?
  1597. je @@HeadPos ; Yes --> @@HeadPos
  1598. cmp al,4 ; Info about audio channels ?
  1599. je @@AudioChannelInfo ; Yes --> @@AudioChannelInfo
  1600. cmp al,5 ; Read drive bytes ?
  1601. je @@NotReady ; Yes --> @@NotReady
  1602. cmp al,6 ; Status of device ?
  1603. je @@DeviceStatus ; Yes --> @@DeviceStatus
  1604. cmp al,7 ; Size of sectors ?
  1605. je @@SectorSize ; Yes --> @@SectorSize
  1606. cmp al,8 ; Size of disk ?
  1607. je @@VolumeSize ; Yes --> @@VolumeSize
  1608. cmp al,9 ; MediaChanged ?
  1609. je @@MediaChanged ; Yes --> @@MediaChanged
  1610. cmp al,10 ; Info about audio disk ?
  1611. je @@AudioDiskInfo ; Yes --> @@AudioDiskInfo
  1612. cmp al,11 ; Info about audio track ?
  1613. je @@AudioTrackInfo ; Yes --> @@AudioTrackInfo
  1614. cmp al,12 ; Info about Q-channel ?
  1615. je @@NotReady ; Yes --> @@NotReady
  1616. cmp al,13 ; Info about sub-channel ?
  1617. je @@NotReady ; Yes --> @@NotReady
  1618. cmp al,14 ; Get UPC Code ?
  1619. je @@UPCCode ; Yes --> @@UPCCode
  1620. cmp al,15 ; Info about audio status ?
  1621. je @@AudioStatus ; Yes --> @@AudioStatus
  1622. @@NotReady:
  1623. mov [word ptr es:bx+03],3+32768 ; Signal not ready
  1624. iret ; Return to interrupt caller
  1625. @@AudioStatus:
  1626. cmp [cs:AudioTru],01h ; Audio through-put ?
  1627. je @@CallOld ; Yes --> @@CallOld
  1628. push ax es bx ; Save registers
  1629. les bx,[es:bx+14] ; Get pointer to data
  1630. mov ax,[cs:CDPlaying] ; Get flags
  1631. mov [es:bx+1],ax ; Set flags
  1632. pop bx es ax ; Restore registers
  1633. iCLC ; Signal success
  1634. iret ; Return to interrupt caller
  1635. @@HeadPos:
  1636. cmp [cs:AudioTru],01h ; Audio through-put ?
  1637. je @@CallOld ; Yes --> @@CallOld
  1638. push es bx ; Save registers
  1639. les bx,[es:bx+14] ; Get pointer to data
  1640. push ax ds
  1641. mov ax,[cs:CDPos] ; Get old position
  1642. inc ax ; Move to next position
  1643. jnz @@OkPos ; Looped around ?
  1644. mov ax,0010h ; Set to start of tracks
  1645. @@OkPos:
  1646. mov [cs:CDPos],ax ; Store for next read
  1647. mov [es:bx+1],ax ; Set location
  1648. mov [word ptr es:bx+3],0000h ; ...
  1649. pop bx es ; Restore registers
  1650. iCLC ; Signal success
  1651. iret ; Return to interrupt caller
  1652. @@AudioChannelInfo:
  1653. cmp [cs:AudioTru],01h ; Audio through-put ?
  1654. je @@CallOld ; Yes --> @@CallOld
  1655. push es bx ; Save registers
  1656. les bx,[es:bx+14] ; Get pointer to data
  1657. mov [word ptr es:bx+1],0FF00h ; Set channel 0
  1658. mov [word ptr es:bx+3],0FF01h ; Set channel 1
  1659. mov [word ptr es:bx+5],0FF02h ; Set channel 2
  1660. mov [word ptr es:bx+7],0FF03h ; Set channel 3
  1661. pop bx es ; Restore registers
  1662. iCLC ; Signal success
  1663. iret ; Return to interrupt caller
  1664. @@DeviceStatus:
  1665. cmp [cs:AudioTru],01h ; Audio through-put ?
  1666. je @@CallOld ; Yes --> @@CallOld
  1667. push es bx ; Save registers
  1668. les bx,[es:bx+14] ; Get pointer to data
  1669. mov [word ptr es:bx+1],0000001110110110b ; Set status
  1670. mov [word ptr es:bx+3],00000h ; ...
  1671. pop bx es ; Restore registers
  1672. iCLC ; Signal success
  1673. iret ; Return to interrupt caller
  1674. @@SectorSize:
  1675. push ds si ; Save registers
  1676. mov cl,[es:bx+1] ; Get drive id
  1677. add cl,[cs:FirstID] ; Convert to A-Z
  1678. call GetData, cx ; Get data
  1679. jc @@NoSectorSize ; No data --> @@NoSectorSize
  1680. push es bx ; Save registers
  1681. les bx,[es:bx+14] ; Get pointer to data
  1682. mov ax,[ds:si+4] ; Get sector size
  1683. mov [es:bx+1],ax ; Store sector size
  1684. mov al,[ds:si+6] ; ...
  1685. mov [es:bx+3],al ; ...
  1686. pop bx es si ds ; Restore registers
  1687. iCLC ; Signal success
  1688. iret ; Return to interrupt caller
  1689. @@NoSectorSize:
  1690. pop si ds ; Restore registers
  1691. mov al,17 ; Failure code
  1692. jmp @@FailureDev ; Failure
  1693. iret ; Return to interrupt caller
  1694. @@VolumeSize:
  1695. push ds si ; Save registers
  1696. mov cl,[es:bx+1] ; Get drive id
  1697. add cl,[cs:FirstID] ; Convert to A-Z
  1698. call GetData, cx ; Get data
  1699. jc @@NoVolumeSize ; No data --> @@NoVolumeSize
  1700. push es bx ; Save registers
  1701. les bx,[es:bx+14] ; Get pointer to data
  1702. mov ax,[ds:si+7] ; Get volume size
  1703. mov [es:bx+1],ax ; Store volume size
  1704. mov ax,[ds:si+9] ; ...
  1705. mov [es:bx+3],ax ; ...
  1706. pop bx es si ds ; Restore registers
  1707. iCLC ; Signal success
  1708. iret ; Return to interrupt caller
  1709. @@NoVolumeSize:
  1710. pop si ds ; Restore registers
  1711. cmp [cs:DoFailure],01h ; Failure on exit ?
  1712. jne @@SuccessDev ; No --> @@SuccessDev
  1713. mov al,17 ; Failure code
  1714. jmp @@FailureDev
  1715. @@MediaChanged:
  1716. cmp [cs:AudioTru],01h ; Audio through-put ?
  1717. je @@CallOld ; Yes --> @@CallOld
  1718. push es bx ; Save registers
  1719. les bx,[es:bx+14] ; Get pointer to data
  1720. mov [byte ptr es:bx+1],01h ; Set media not changed flag
  1721. pop bx es ; Restore registers
  1722. iCLC ; Signal success
  1723. iret ; Return to interrupt caller
  1724. @@AudioDiskInfo:
  1725. cmp [cs:AudioTru],01h ; Audio through-put ?
  1726. je @@CallOld ; Yes --> @@CallOld
  1727. push ds si ; Save registers
  1728. mov cl,[es:bx+1] ; Get drive id
  1729. add cl,[cs:FirstID] ; Convert to A-Z
  1730. call GetData, cx ; Get data
  1731. jc @@NoAudioDiskInfo ; No data --> @@NoAudioDiskInfo
  1732. push es bx ; Save registers
  1733. les bx,[es:bx+14] ; Get pointer to data
  1734. mov ax,[ds:si+11] ; Get info data
  1735. mov [es:bx+1],ax ; Store info data
  1736. mov ax,[ds:si+13] ; ...
  1737. mov [es:bx+3],ax ; ...
  1738. mov ax,[ds:si+15] ; ...
  1739. mov [es:bx+5],ax ; ...
  1740. pop bx es si ds ; Restore registers
  1741. iCLC ; Signal success
  1742. iret ; Return to interrupt caller
  1743. @@NoAudioDiskInfo:
  1744. cmp [cs:AudioTru],01h ; Audio through-put ?
  1745. je @@CallOld ; Yes --> @@CallOld
  1746. pop si ds ; Restore registers
  1747. cmp [cs:DoFailure],01h ; Failure on exit ?
  1748. jne @@SuccessDev ; No --> @@SuccessDev
  1749. mov al,17 ; Failure code
  1750. jmp @@FailureDev ; Failure
  1751. @@AudioTrackInfo:
  1752. cmp [cs:AudioTru],01h ; Audio through-put ?
  1753. je @@CallOld ; Yes --> @@CallOld
  1754. push ds si es bx ; Save registers
  1755. mov cl,[es:bx+1] ; Get drive id
  1756. add cl,[cs:FirstID] ; Convert to A-Z
  1757. call GetData, cx ; Get data
  1758. jc @@NoAudioTrackInfo ; No data --> @@NoAudioTrackInfo
  1759. add si,161 ; Adjust offset
  1760. les bx,[es:bx+14] ; Get pointer to data
  1761. mov al,[es:bx+1] ; Get track no
  1762. cmp al,[ds:si] ; Track < first track on cd ?
  1763. jb @@NoAudioTrackInfo ; Yes --> @@NoAudioTrackInfo
  1764. cmp al,[ds:si+1] ; Track > last track on cd ?
  1765. ja @@NoAudioTrackInfo ; Yes --> @@NoAudioTrackInfo
  1766. add si,2 ; Adjust offset
  1767. sub al,[ds:si-2] ; Make track 0-based
  1768. cmp al,0 ; First track ?
  1769. je @@ReadTrackInfo ; Yes --> @@ReadTrackInfo
  1770. @@SkipLoop:
  1771. add si,5 ; Adjust offset
  1772. dec al ; Next track
  1773. jnz @@SkipLoop ; More --> @@SkipLoop
  1774. @@ReadTrackInfo:
  1775. mov ax,[ds:si] ; Get track info data
  1776. mov [es:bx+2],ax ; Store track info data
  1777. mov ax,[ds:si+2] ; ...
  1778. mov [es:bx+4],ax ; ...
  1779. mov al,[ds:si+4] ; ...
  1780. mov [es:bx+6],al ; ...
  1781. pop bx es si ds ; Restore registers
  1782. iCLC ; Signal success
  1783. iret ; Return to interrupt caller
  1784. @@NoAudioTrackInfo:
  1785. pop bx es si ds ; Restore registers
  1786. cmp [cs:DoFailure],01h ; Failure on exit ?
  1787. jne @@SuccessDev ; No --> @@SuccessDev
  1788. mov al,17 ; Failure code
  1789. jmp @@FailureDev ; Failure
  1790. @@UPCCode:
  1791. push ds si ; Save registers
  1792. mov cl,[es:bx+1] ; Get drive id
  1793. add cl,[cs:FirstID] ; Convert to A-Z
  1794. call GetData, cx ; Get data
  1795. jc @@NoUPCCode ; No data --> @@NoUPCCode
  1796. push es bx ; Save registers
  1797. les bx,[es:bx+14] ; Get pointer to data
  1798. mov ax,[ds:si+17] ; Get upc code
  1799. mov [es:bx+1],ax ; Store upc code
  1800. mov ax,[ds:si+19] ; ...
  1801. mov [es:bx+3],ax ; ...
  1802. mov ax,[ds:si+21] ; ...
  1803. mov [es:bx+5],ax ; ...
  1804. mov ax,[ds:si+23] ; ...
  1805. mov [es:bx+7],ax ; ...
  1806. mov ax,[ds:si+25] ; ...
  1807. mov [es:bx+9],ax ; ...
  1808. pop bx es si ds ; Restore registers
  1809. jmp @@SuccessDev ; Success
  1810. @@NoUPCCode:
  1811. pop si ds ; Restore registers
  1812. mov al,17 ; Failure code
  1813. jmp @@FailureDev ; Failure
  1814. @@ErrRqz:
  1815. mov [word ptr es:bx+03],3+32768 ; Set invalid request code
  1816. iret ; Return to interrupt caller
  1817. @@GetDirEntry:
  1818. iCLC ; Signal success
  1819. mov [byte ptr es:bx],0 ; Zero pathname
  1820. push es ; Save register
  1821. mov es,si ; Get segment
  1822. mov [byte ptr es:di+26],0 ; Zero pathname
  1823. mov [byte ptr es:di+27],0 ; Zero pathname
  1824. pop es ; Restore register
  1825. mov ax,1 ; ISO9660 cd format
  1826. iret ; Return to interrupt caller
  1827. @@DriveList:
  1828. push cx bx ; Save registers
  1829. mov cl,[cs:FirstID] ; Get first id
  1830. sub cl,'A' ; Calculate first drive no
  1831. mov ch,[cs:DriveCount] ; Get number of drives
  1832. @@DriveLoop:
  1833. mov [es:bx],cl ; Store drive no
  1834. inc bx ; Next drive no
  1835. dec ch ; One less drive
  1836. jnz @@DriveLoop ; More --> @@DriveLoop
  1837. pop bx cx ; Restore registers
  1838. iCLC ; Success
  1839. iret ; Return to interrupt caller
  1840. @@GetVersion:
  1841. mov bx,0217h ; Version 2.23 (mscdex)
  1842. iCLC ; Signal success
  1843. iret ; Return to interrupt caller
  1844. @@DriveCheck:
  1845. mov bx,cx ; Get drive id
  1846. add bl,'A' ; Convert to A-Z
  1847. cmp bl,[cs:FirstID] ; Our drive ?
  1848. jb @@NotACD ; No --> @@NotACD
  1849. cmp bl,[cs:LastID] ; Our drive ?
  1850. ja @@NotACD ; No --> @@NotACD
  1851. mov al,01h ; Signal cd rom
  1852. jmp @@RetIt ; Return it
  1853. @@NotACD:
  1854. mov al,00h ; Signal not a cd rom
  1855. @@RetIt:
  1856. mov bx,0adadh ; Set extensions supported
  1857. mov ah,00h ; Zero high 8 bit of return
  1858. iret ; Return to interrupt caller
  1859. @@DeviceList:
  1860. push ax bx cx si di ; Save registers
  1861. lea si,[DeviceHdr] ; ds:si = DeviceHdr
  1862. mov cl,[cs:DriveCount] ; Get number of drives
  1863. xor ax,ax ; Zero ax
  1864. xor di,di ; Zero di
  1865. @@DeviceLoop:
  1866. mov [es:bx],al ; Store subunit no
  1867. mov [es:bx+3],si ; Store offset of device
  1868. mov [es:bx+1],di ; Store
  1869. inc al
  1870. add bx,5 ; Next entry
  1871. dec cl ; One less drive
  1872. jnz @@DeviceLoop ; More --> @@DeviceLoop
  1873. pop di si cx bx ax ; Restore registers
  1874. iret ; Return to interrupt caller
  1875. @@CheckInstall:
  1876. cmp bx,0 ; Check ?
  1877. jne @@CallOld ; No --> @@CallOld
  1878. xor ch,ch ; Zero high 8 bit
  1879. mov cl,[cs:FirstID] ; Get drive id
  1880. sub cl,'A' ; Make 0-based
  1881. xor bh,bh ; No more than 255 drives!
  1882. mov bl,[cs:DriveCount] ; Get drivecount
  1883. iret ; Return to interrupt caller
  1884. @@GetFileName:
  1885. push ds si ; Save registers
  1886. add cl,'A' ; Make id A-Z
  1887. call GetData, cx ; Get data
  1888. jc @@NoCD ; No data --> @@NoCD
  1889. add si,27 ; Adjust offset
  1890. @@ReadIt:
  1891. cmp al,02h ; Need to adjust offset ?
  1892. je @@OkRead ; No --> @@OkRead
  1893. add si,38 ; Adjust offset
  1894. dec al ; Adjust counter
  1895. jmp @@ReadIt ; Loop
  1896. @@OkRead:
  1897. push bx cx ; Save register
  1898. mov cx,38 ; Number of characters to copy
  1899. cld ; Forward copy
  1900. rep movsb ; Copy filename
  1901. pop cx bx si ds ; Restore registers
  1902. iCLC ; Signal success
  1903. iret ; Return to interrupt caller
  1904. @@NoCD:
  1905. pop si ds ; Restore registers
  1906. cmp [cs:DoFailure],01h ; Failure on exit ?
  1907. jne @@Dummy ; No --> @@Dummy
  1908. iSTC ; Signal failure
  1909. mov ax,000fh ; Drive not ready error
  1910. jmp @@Exit ; Exit
  1911. @@CheckMSCDEX:
  1912. push bp ; Save bp
  1913. mov bp,sp ; Point bp to sp
  1914. cmp [word ptr bp+8],0dadah ; Installation check ?
  1915. je @@YesMSCDEX ; Yes --> @@YesMSCDEX
  1916. pop bp ; Restore bp
  1917. jmp @@CallOld ; Call old handler
  1918. @@YesMSCDEX:
  1919. mov [word ptr bp+8],0adadh ; Adjust stack
  1920. pop bp ; Restore bp
  1921. cmp si,'0C' ; Self-check ?
  1922. jne @@NotSelf ; No --> @@NotSelf
  1923. cmp di,'D7' ; Self-check ?
  1924. jne @@NotSelf ; No --> @@NotSelf
  1925. mov si,'7D' ; Adjust si
  1926. mov di,'C0' ; and di
  1927. push cs ; Put code segment
  1928. pop es ; into es
  1929. @@NotSelf:
  1930. mov al,0ffh ; Signal success
  1931. @@Exit:
  1932. iret ; Return to interrupt caller
  1933. @@DelaySize dw 3200
  1934. @@OldAX dw 0
  1935. endp
  1936. ; GetSpeed procedure
  1937. proc GetSpeed
  1938. arg @@DriveID:word
  1939. uses bx
  1940. mov bl,[byte ptr @@DriveID] ; Get Drive ID
  1941. sub bl,[cs:FirstID] ; Make 0-based
  1942. xor bh,bh ; Zero high 8 bit (make index)
  1943. shl bx,1 ; Make word-index
  1944. mov ax,[cs:DriveSpeeds+bx] ; Get drive speed from table
  1945. ret ; Return to caller
  1946. endp
  1947. ; SetIntVec procedure
  1948. proc SetIntVec
  1949. arg @@IntNo:word, @@Vector:dword
  1950. uses ax, ds, dx
  1951. mov ah,25h ; Dos Fn 25h = SetIntVec
  1952. mov al,[byte ptr @@IntNo] ; Interrupt no in al
  1953. lds dx,[dword ptr @@Vector] ; Vector in ds:dx
  1954. int 21h ; Call DOS interrupt
  1955. ret ; Return to caller
  1956. endp
  1957. ; GetIntVec procedure
  1958. proc GetIntVec
  1959. arg @@IntNo:word
  1960. uses ax
  1961. mov ah,35h ; Dos Fn 35h = GetIntVec
  1962. mov al,[byte ptr @@IntNo] ; Interrupt no in al
  1963. int 21h ; Call DOS interrupt
  1964. ret ; Return to caller
  1965. endp
  1966. ; Hook procedure
  1967. proc Hook
  1968. call GetIntVec, 66h ; Get interrupt vector 66h
  1969. test bx,bx ; Any vector there ?
  1970. jnz @@No66 ; Yes --> @@No66
  1971. mov bx,es ; Get segment in bx
  1972. test bx,bx ; Vector there ?
  1973. jnz @@No66 ; Yes --> @@No6
  1974. mov ah,62h ; Dos Fn 62h = Get PSP
  1975. int 21h ; Call DOS interrupt
  1976. mov es,bx ; Put segment in es
  1977. mov es,[es:002ch] ; Get environment segment
  1978. mov ah,49h ; Dos Fn 49h = FreeMem
  1979. int 21h ; Call DOS interrupt
  1980. call GetIntVec, 21h ; Get interrupt vector 21h
  1981. call SetIntVec, 66h, es bx ; Make copy at vector 66h
  1982. mov [word ptr cs:OldInt21],bx ; Save vector 21h
  1983. mov [word ptr cs:OldInt21+2],es ; ...
  1984. call GetIntVec, 2Fh ; Get interrupt vector 2fh
  1985. mov [word ptr cs:OldInt2F],bx ; Save vector 2fh
  1986. mov [word ptr cs:OldInt2F+2],es ; ...
  1987. call SetIntVec, 21h, cs offset NewInt21 ; Set new int 21h
  1988. call SetIntVec, 2Fh, cs offset NewInt2F ; Set new int 2fh
  1989. call LStrWrite, offset HookMsg ; Write message
  1990. ret ; Return to caller
  1991. @@No66:
  1992. mov [cs:Quiet],00h ; Turn off quiet mode
  1993. call LStrWrite, offset No66Msg ; Write error message
  1994. call CleanUp ; Clean up
  1995. ExitCode 0001h ; Exit to dos
  1996. endp
  1997. ; CleanUp procedure
  1998. proc CleanUp
  1999. lea si,[Datas] ; Point ds:si to Datas
  2000. mov cx,MaxCDs ; Get number of CDs
  2001. @@DataLoop:
  2002. mov ah,49h ; Dos Fn 49h = FreeMem
  2003. mov bx,[cs:si] ; Get segment of data
  2004. test bx,bx ; Any data there ?
  2005. jz @@NextData ; No --> @@NextData
  2006. mov es,bx ; Put segment in es
  2007. int 21h ; Call DOS interrupt
  2008. @@NextData:
  2009. add si,2 ; Next index of Datas
  2010. dec cx ; One less CD do clean up
  2011. jnz @@DataLoop ; More --> @@DataLoop
  2012. mov al,[cs:FirstID] ; Get drive ID of first cd
  2013. @@Loop:
  2014. call GetCDS, ax ; Get cd data
  2015. xor cx,cx ; Zero cx
  2016. mov [es:bx],al ; Set old drive letter
  2017. mov [byte ptr es:bx+1],':' ; Set to 'D:', 0
  2018. mov [byte ptr es:bx+2],'' ; ...
  2019. mov [byte ptr es:bx+3],0 ; ...
  2020. mov [word ptr es:bx+79],2 ; ...
  2021. mov [word ptr es:bx+67],0 ; Fix up drive bit flags
  2022. mov [es:bx+69],cx ; Remove drive pointer
  2023. mov [es:bx+71],cx ; ...
  2024. @@Next:
  2025. inc al ; Next drive letter
  2026. cmp al,[cs:LastID] ; Beyond last cd ?
  2027. jbe @@Loop ; No --> @@Loop
  2028. ret ; Return to interrupt caller
  2029. endp
  2030. ; UnHook procedure
  2031. proc UnHook
  2032. call CleanUp ; Clean up
  2033. call SetIntVec, 66h, 0 0 ; Restore int 66h
  2034. call SetIntVec, 21h, [dword ptr OldInt21] ; Restore int 21h
  2035. call SetIntVec, 2Fh, [dword ptr OldInt2F] ; Restore int 2fh
  2036. push ds cs ; Save ds and put cs ...
  2037. pop ds ; ... into ds
  2038. call LStrWrite, offset UnHookMsg ; Write message
  2039. pop ds ; Restore ds
  2040. ret ; Return to caller
  2041. endp
  2042. ; Exec procedure
  2043. proc Exec
  2044. arg @@ProgName:dword, @@Params:dword
  2045. uses ds, dx, es, bx, ax, si, di ; Save registers
  2046. lds si,[dword ptr @@Params] ; Source in ds:si
  2047. cmp [byte ptr ds:si],'&' ; Dummy letter ?
  2048. jne @@OkLetter ; No --> @@OkLetter
  2049. mov al,[cs:FirstID] ; Get cd letter
  2050. mov [ds:si],al ; Update parameter
  2051. @@OkLetter:
  2052. push cs ; Put cs ...
  2053. pop es ; ... in es
  2054. lea di,[@@LocalPms+1] ; es:di = Destination
  2055. cld ; Forward direction
  2056. @@Loop:
  2057. mov [cs:@@EPB+4],cs ; Save segment
  2058. lodsb ; Get character
  2059. stosb ; Store it
  2060. test al,al ; Finished yet ?
  2061. jnz @@Loop ; No --> @@Loop
  2062. mov al,0dh ; End of parameters
  2063. stosb ; Store it
  2064. sub di,offset @@LocalPms ; Calculate length+1
  2065. dec di ; Calculate length
  2066. mov ax,di ; Store in ax
  2067. mov [@@LocalPMS],al ; Store length byte
  2068. mov ax,4b00h ; Fn 4bh = exec, 00=load+exec
  2069. lds dx,[@@ProgName] ; ds:dx = progname
  2070. push cs ; Put cs ...
  2071. pop es ; ... in es
  2072. lea bx,[@@EPB] ; Point es:bx to EPB
  2073. int 21h ; Call dos interrupt
  2074. int 3
  2075. ret ; Return to caller
  2076. @@EPB dw 0
  2077. dw offset @@LocalPms
  2078. dw 0
  2079. dw 0,0
  2080. dw 0,0
  2081. @@LocalPms db 0
  2082. db 128 dup (0)
  2083. endp
  2084. ; StrLIComp procedure
  2085. proc StrLIComp
  2086. arg @@Dest:dword, @@Source:dword, @@Length:word
  2087. uses ds, es, si, di, cx, bx
  2088. lds si,[dword ptr @@Dest] ; Destination in ds:si
  2089. les di,[dword ptr @@Source] ; Source in es:di
  2090. cld ; Forward copy
  2091. mov cx,[@@Length] ; Length in cx
  2092. jcxz @@Equal ; No bytes --> @@Equal
  2093. @@Loop:
  2094. lodsb ; Get character from dest
  2095. mov bl,[es:di] ; Get character from source
  2096. inc di ; Next char in source
  2097. call UpCase, ax ; Convert to uppercase
  2098. push ax ; Save it
  2099. call UpCase, bx ; Convert to uppercase
  2100. mov bx,ax ; Put it back in bx
  2101. pop ax ; Restore ax
  2102. cmp al,bl ; a<b or a>b ?
  2103. jb @@Less ; a<b --> @@Less
  2104. ja @@More ; a>b --> @@More
  2105. cmp al,0 ; End of strings ?
  2106. je @@Equal ; Yes --> @@Equal
  2107. dec cx ; One less character
  2108. jnz @@Loop ; More --> @@Loop
  2109. @@Equal:
  2110. xor al,al ; Zero al
  2111. clc ; Signal equal
  2112. jmp @@Exit ; Exit
  2113. @@Less:
  2114. mov al,-1 ; Signal less
  2115. stc ; Signal different
  2116. jmp @@Exit ; Exit
  2117. @@More:
  2118. mov al,1 ; Signal more
  2119. stc ; Signal different
  2120. @@Exit:
  2121. ret ; Return to caller
  2122. endp
  2123. ; StrWrite procedure
  2124. proc StrWrite
  2125. arg @@Source:word ; Set up parameters
  2126. uses dx, si, ax ; Preserve registers
  2127. mov si,[@@Source] ; Point ds:si to string
  2128. cld ; Forward read
  2129. @@Loop:
  2130. lodsb ; Get character
  2131. or al,al ; At end of string ?
  2132. jz @@Exit ; Yes --> @@Exit
  2133. mov dl,al ; Put character in dl
  2134. mov ah,02h ; Fn 02h = Print character
  2135. int 21h ; Call dos interrupt
  2136. jmp @@Loop ; Loop for more characters
  2137. @@Exit:
  2138. ret ; Return
  2139. endp
  2140. ; StrCopy procedure
  2141. proc StrCopy
  2142. arg @@Dest:dword, @@Source:dword ; Set up parameters
  2143. uses ds, si, es, di ; Preserve registers
  2144. lds si,[@@Source] ; Point ds:si to @@Source
  2145. les di,[@@Dest] ; Point es:di to @@Dest
  2146. cld ; Forward copy
  2147. @@Loop:
  2148. lodsb ; Get byte
  2149. stosb ; Store byte
  2150. or al,al ; At end of string ?
  2151. jnz @@Loop ; No --> @@Loop
  2152. mov ax,[word @@Dest] ; Return dest offset in ax
  2153. ret ; Return
  2154. endp
  2155. ; StrLen procedure
  2156. proc StrLen
  2157. uses ds, si
  2158. arg @@Source:dword ; Set up parameters
  2159. xor ax,ax ; Zero length
  2160. lds si,[dword ptr @@Source] ; Source in ds:si
  2161. @@Loop:
  2162. cmp [byte ptr ds:si],0 ; End of string
  2163. je @@Exit ; Yes --> @@Exit
  2164. inc si ; Next character
  2165. inc ax ; Increment counter
  2166. jmp @@Loop ; Loop
  2167. @@Exit:
  2168. ret ; Return to caller
  2169. endp
  2170. ; UpCase procedure
  2171. proc UpCase
  2172. arg @@Character:word ; Set up parameters
  2173. uses bx
  2174. push [@@Character] ; Put character in stack
  2175. mov ax,1213h ; Multiplex Fn 1213h = UpCase
  2176. int 2fh ; Call multiplex interrupt
  2177. pop bx ; Restore bx
  2178. ret ; Return
  2179. endp
  2180. ; StrUpper procedure
  2181. proc StrUpper
  2182. arg @@Dest:dword ; Set up parameters
  2183. uses bx, cx, ds, si ; Preserve registers
  2184. lds si,[@@Dest] ; Point ds:si to string
  2185. @@Loop:
  2186. mov al,[ds:si] ; Get character
  2187. or al,al ; Is at end ?
  2188. jz @@Exit ; Yes --> @@Exit
  2189. push ax ; Put character on stack
  2190. mov ax,1213h ; Multiplex Fn 1213h = UpCase
  2191. int 2fh ; Call multiplex interrupt
  2192. pop bx ; Restore bx
  2193. mov [ds:si],al ; Store back in string
  2194. inc si ; Go to next character
  2195. jmp @@Loop ; Loop
  2196. @@Exit:
  2197. mov ax,[word @@Dest] ; Return string
  2198. ret ; Return
  2199. endp
  2200. ; DeCrunch procedure
  2201. proc DeCrunch
  2202. arg @@Source:dword, @@Dest:dword ; Parameters
  2203. uses ds, es, si, di, bx, dx ; Preserve registers
  2204. lds si,[dword @@Source] ; Point DS:SI to source
  2205. les di,[dword @@Dest] ; Point ES:DI to destination
  2206. cld ; Forward direction
  2207. lodsw ; Get size of raw data
  2208. mov cx,ax ; Put in cx
  2209. lodsw ; Get DLE 1/2
  2210. mov dx,ax ; Put in dl/dh
  2211. @@loop1:
  2212. jcxz @@exit ; When no more --> @@exit
  2213. lodsb ; Get one byte of data
  2214. cmp al,dl ; Is RLE ?
  2215. je @@unrle ; Yes --> @@unrle
  2216. cmp al,dh ; Is LZ ?
  2217. je @@unlz ; Yes --> @@unlz
  2218. stosb ; Store raw data
  2219. loop @@loop1 ; Loop while more data
  2220. jmp @@exit ; Exit when done
  2221. @@unrle:
  2222. lodsb ; Get high-byte of count
  2223. cmp al,0ffh ; Is only one dle ?
  2224. je @@storedle1 ; Yes --> @@storedle1
  2225. mov ah,al ; Store in ah
  2226. lodsb ; Get low-byte of count
  2227. cmp ax,cx ; Too big ?
  2228. ja @@exit ; Yes --> @@exit
  2229. sub cx,ax ; Decrement main counter
  2230. push cx ; Save main counter
  2231. mov cx,ax ; Use local counter
  2232. lodsb ; Get byte to repeat cx times
  2233. rep stosb ; Store repetition
  2234. pop cx ; Restore main counter
  2235. jmp @@loop1 ; Loop for more data
  2236. @@storedle1:
  2237. mov al,dl ; Get DLE 1
  2238. stosb ; Store it
  2239. loop @@loop1 ; Loop for more data
  2240. jmp @@exit ; Exit when done
  2241. @@unlz:
  2242. lodsb ; Get high-byte of count
  2243. cmp al,0ffh ; Is only one dle ?
  2244. je @@storedle2 ; Yes --> @@storedle2
  2245. mov ah,al ; Put in ah
  2246. lodsb ; Get low-byte of count
  2247. cmp ax,cx ; Too big ?
  2248. ja @@exit ; Yes --> @@exit
  2249. sub cx,ax ; Decrement main counter
  2250. push cx ; Save main counter
  2251. mov cx,ax ; Use local counter
  2252. lodsw ; Get distance to look back
  2253. mov bx,ax ; Store in bx
  2254. push ds si ; Save some registers
  2255. push es ; Copy es
  2256. pop ds ; To ds
  2257. mov si,di ; Copy di to si
  2258. sub si,bx ; Go back to start of data
  2259. rep movsb ; Move bytes
  2260. pop si ds cx ; Restore registers
  2261. jmp @@loop1 ; Loop for more data
  2262. @@storedle2:
  2263. mov al,dh ; Get DLE 2
  2264. stosb ; Store it
  2265. loop @@loop1 ; Loop for more data
  2266. @@exit:
  2267. mov ax,si ; Get offset of next byte
  2268. mov cx,si ; Into ax and cx
  2269. lds si,[dword @@Source] ; Get original pointer
  2270. sub cx,si ; Calculate difference
  2271. ret ; Return
  2272. endp
  2273. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  2274. ;圹 End of source-file                                                       圹
  2275. ;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹
  2276. end ; End of source-file