sysatari.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by the Free Pascal development team.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$define ATARI}
  12. unit sysatari;
  13. { Left to do : }
  14. { - Fix DOSError codes to conform to those of DOS (TP) }
  15. {$I os.inc}
  16. interface
  17. { used for single computations }
  18. const BIAS4 = $7f-1;
  19. {$I systemh.inc}
  20. {$I heaph.inc}
  21. const
  22. UnusedHandle = $ffff;
  23. StdInputHandle = 0;
  24. StdOutputHandle = 1;
  25. StdErrorHandle = $ffff;
  26. implementation
  27. {$I system.inc}
  28. {$I lowmath.inc}
  29. type
  30. plongint = ^longint;
  31. {$S-}
  32. procedure Stack_Check; assembler;
  33. { Check for local variable allocation }
  34. { On Entry -> d0 : size of local stack we are trying to allocate }
  35. asm
  36. XDEF STACKCHECK
  37. move.l sp,d1 { get value of stack pointer }
  38. sub.l d0,d1 { sp - stack_size }
  39. cmp.l __BREAK,d1
  40. bgt @st1nosweat
  41. move.l #202,d0
  42. jsr HALT_ERROR
  43. @st1nosweat:
  44. end;
  45. procedure halt(errnum : byte);
  46. begin
  47. do_exit;
  48. flush(stderr);
  49. asm
  50. clr.l d0
  51. move.b errnum,d0
  52. move.w d0,-(sp)
  53. move.w #$4c,-(sp)
  54. trap #1
  55. end;
  56. end;
  57. function paramcount : longint; assembler;
  58. asm
  59. clr.l d0
  60. move.w __ARGC,d0
  61. sub.w #1,d0
  62. end;
  63. function paramstr(l : longint) : string;
  64. function args : pointer; assembler;
  65. asm
  66. move.l __ARGS,d0
  67. end;
  68. var
  69. p : ^pchar;
  70. begin
  71. if (l>=0) and (l<=paramcount) then
  72. begin
  73. p:=args;
  74. paramstr:=strpas(p[l]);
  75. end
  76. else paramstr:='';
  77. end;
  78. procedure randomize;
  79. var
  80. hl : longint;
  81. begin
  82. asm
  83. movem.l d2/d3/a2/a3, -(sp) { save OS registers }
  84. move.w #17,-(sp)
  85. trap #14 { call xbios - random number }
  86. add.l #2,sp
  87. movem.l (sp)+,d2/d3/a2/a3
  88. move.l d0,hl { result in d0 }
  89. end;
  90. randseed:=hl;
  91. end;
  92. { This routine is used to grow the heap. }
  93. { But here we do a trick, we say that the }
  94. { heap cannot be regrown! }
  95. function sbrk( size: longint): longint;
  96. { on exit -1 = if fails. }
  97. Begin
  98. sbrk:=-1;
  99. end;
  100. {$I heap.inc}
  101. {****************************************************************************
  102. Low Level File Routines
  103. ****************************************************************************}
  104. procedure AllowSlash(p:pchar);
  105. var
  106. i : longint;
  107. begin
  108. { allow slash as backslash }
  109. for i:=0 to strlen(p) do
  110. if p[i]='/' then p[i]:='\';
  111. end;
  112. procedure do_close(h : longint);
  113. begin
  114. asm
  115. movem.l d2/d3/a2/a3,-(sp)
  116. move.l h,-(sp)
  117. move.w #$3e,-(sp)
  118. trap #1
  119. add.l #4,sp { restore stack ... }
  120. movem.l (sp)+,d2/d3/a2/a3
  121. end;
  122. end;
  123. procedure do_erase(p : pchar);
  124. begin
  125. AllowSlash(p);
  126. asm
  127. move.l d2,d6 { save d2 }
  128. movem.l d3/a2/a3,-(sp) { save regs }
  129. move.l p,-(sp)
  130. move.w #$41,-(sp)
  131. trap #1
  132. add.l #6,sp
  133. move.l d6,d2 { restore d2 }
  134. movem.l (sp)+,d3/a2/a3
  135. tst.w d0
  136. beq @doserend
  137. move.w d0,InOutRes
  138. @doserend:
  139. end;
  140. end;
  141. procedure do_rename(p1,p2 : pchar);
  142. begin
  143. AllowSlash(p1);
  144. AllowSlash(p2);
  145. asm
  146. move.l d2,d6 { save d2 }
  147. movem.l d3/a2/a3,-(sp)
  148. move.l p1,-(sp)
  149. move.l p2,-(sp)
  150. clr.w -(sp)
  151. move.w #$56,-(sp)
  152. trap #1
  153. lea 12(sp),sp
  154. move.l d6,d2 { restore d2 }
  155. movem.l (sp)+,d3/a2/a3
  156. tst.w d0
  157. beq @dosreend
  158. move.w d0,InOutRes { error ... }
  159. @dosreend:
  160. end;
  161. end;
  162. function do_write(h,addr,len : longint) : longint;
  163. begin
  164. asm
  165. move.l d2,d6 { save d2 }
  166. movem.l d3/a2/a3,-(sp)
  167. move.l addr,-(sp)
  168. move.l len,-(sp)
  169. move.w h,-(sp)
  170. move.w #$40,-(sp)
  171. trap #1
  172. lea 12(sp),sp
  173. move.l d6,d2 { restore d2 }
  174. movem.l (sp)+,d3/a2/a3
  175. tst.l d0
  176. bpl @doswrend
  177. move.w d0,InOutRes { error ... }
  178. @doswrend:
  179. move.l d0,@RESULT
  180. end;
  181. end;
  182. function do_read(h,addr,len : longint) : longint;
  183. begin
  184. asm
  185. move.l d2,d6 { save d2 }
  186. movem.l d3/a2/a3,-(sp)
  187. move.l addr,-(sp)
  188. move.l len,-(sp)
  189. move.w h,-(sp)
  190. move.w #$40,-(sp)
  191. trap #1
  192. lea 12(sp),sp
  193. move.l d6,d2 { restore d2 }
  194. movem.l (sp)+,d3/a2/a3
  195. tst.l d0
  196. bpl @dosrdend
  197. move.w d0,InOutRes { error ... }
  198. @dosrdend:
  199. move.l d0,@Result
  200. end;
  201. end;
  202. function do_filepos(handle : longint) : longint;
  203. begin
  204. asm
  205. move.l d2,d6 { save d2 }
  206. movem.l d3/a2/a3,-(sp)
  207. move.w #1,-(sp) { seek from current position }
  208. move.w handle,-(sp)
  209. move.l #0,-(sp) { with a seek offset of zero }
  210. move.w #$42,-(sp)
  211. trap #1
  212. lea 10(sp),sp
  213. move.l d6,d2 { restore d2 }
  214. movem.l (sp)+,d3/a2/a3
  215. move.l d0,@Result
  216. end;
  217. end;
  218. procedure do_seek(handle,pos : longint);
  219. begin
  220. asm
  221. move.l d2,d6 { save d2 }
  222. movem.l d3/a2/a3,-(sp)
  223. move.w #0,-(sp) { seek from start of file }
  224. move.w handle,-(sp)
  225. move.l pos,-(sp)
  226. move.w #$42,-(sp)
  227. trap #1
  228. lea 10(sp),sp
  229. move.l d6,d2 { restore d2 }
  230. movem.l (sp)+,d3/a2/a3
  231. end;
  232. end;
  233. function do_seekend(handle:longint):longint;
  234. var
  235. t: longint;
  236. begin
  237. asm
  238. move.l d2,d6 { save d2 }
  239. movem.l d3/a2/a3,-(sp)
  240. move.w #2,-(sp) { seek from end of file }
  241. move.w handle,-(sp)
  242. move.l #0,-(sp) { with an offset of 0 from end }
  243. move.w #$42,-(sp)
  244. trap #1
  245. lea 10(sp),sp
  246. move.l d6,d2 { restore d2 }
  247. movem.l (sp)+,d3/a2/a3
  248. move.l d0,t
  249. end;
  250. do_seekend:=t;
  251. end;
  252. function do_filesize(handle : longint) : longint;
  253. var
  254. aktfilepos : longint;
  255. begin
  256. aktfilepos:=do_filepos(handle);
  257. do_filesize:=do_seekend(handle);
  258. do_seek(handle,aktfilepos);
  259. end;
  260. procedure do_truncate (handle,pos:longint);
  261. begin
  262. do_seek(handle,pos);
  263. {!!!!!!!!!!!!}
  264. end;
  265. procedure do_open(var f;p:pchar;flags:longint);
  266. {
  267. filerec and textrec have both handle and mode as the first items so
  268. they could use the same routine for opening/creating.
  269. when (flags and $10) the file will be append
  270. when (flags and $100) the file will be truncate/rewritten
  271. when (flags and $1000) there is no check for close (needed for textfiles)
  272. }
  273. var
  274. i : longint;
  275. oflags: longint;
  276. begin
  277. AllowSlash(p);
  278. { close first if opened }
  279. if ((flags and $1000)=0) then
  280. begin
  281. case filerec(f).mode of
  282. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  283. fmclosed : ;
  284. else
  285. begin
  286. inoutres:=102; {not assigned}
  287. exit;
  288. end;
  289. end;
  290. end;
  291. { reset file handle }
  292. filerec(f).handle:=UnusedHandle;
  293. oflags:=$04;
  294. { convert filemode to filerec modes }
  295. case (flags and 3) of
  296. 0 : begin
  297. filerec(f).mode:=fminput;
  298. oflags:=$01;
  299. end;
  300. 1 : filerec(f).mode:=fmoutput;
  301. 2 : filerec(f).mode:=fminout;
  302. end;
  303. if (flags and $100)<>0 then
  304. begin
  305. filerec(f).mode:=fmoutput;
  306. oflags:=$02;
  307. end
  308. else
  309. if (flags and $10)<>0 then
  310. begin
  311. filerec(f).mode:=fmoutput;
  312. oflags:=$04;
  313. end;
  314. { empty name is special }
  315. if p[0]=#0 then
  316. begin
  317. case filerec(f).mode of
  318. fminput : filerec(f).handle:=StdInputHandle;
  319. fmappend,
  320. fmoutput : begin
  321. filerec(f).handle:=StdOutputHandle;
  322. filerec(f).mode:=fmoutput; {fool fmappend}
  323. end;
  324. end;
  325. exit;
  326. end;
  327. asm
  328. movem.l d2/d3/a2/a3,-(sp) { save used registers }
  329. cmp.l #4,oflags { check if append mode ... }
  330. bne @opencont2
  331. move.w #2,d0 { append mode... r/w open }
  332. bra @opencont1
  333. @opencont2:
  334. move.l oflags,d0 { use flag as source ... }
  335. @opencont1:
  336. move.w d0,-(sp)
  337. pea p
  338. move.w #$3d,-(sp)
  339. trap #1
  340. add.l #8,sp { restore stack of os call }
  341. movem.l (sp)+,d2/d3/a2/a3
  342. tst.l d0
  343. bpl @opennoerr
  344. move.w d0,InOutRes
  345. @opennoerr:
  346. move.l d0,i { get handle ... }
  347. end;
  348. filerec(f).handle:=i;
  349. if (flags and $10)<>0 then
  350. do_seekend(filerec(f).handle);
  351. end;
  352. {*****************************************************************************
  353. UnTyped File Handling
  354. *****************************************************************************}
  355. {$i file.inc}
  356. {*****************************************************************************
  357. Typed File Handling
  358. *****************************************************************************}
  359. {$i typefile.inc}
  360. {*****************************************************************************
  361. Text File Handling
  362. *****************************************************************************}
  363. {$i text.inc}
  364. {*****************************************************************************
  365. Directory Handling
  366. *****************************************************************************}
  367. procedure DosDir(func:byte;const s:string);
  368. var
  369. buffer : array[0..255] of char;
  370. begin
  371. move(s[1],buffer,length(s));
  372. buffer[length(s)]:=#0;
  373. AllowSlash(pchar(@buffer));
  374. asm
  375. move.l d2,d6 { save d2 }
  376. movem.l d3/a2/a3,-(sp)
  377. pea buffer
  378. move.b func,-(sp)
  379. trap #1
  380. add.l #6,sp
  381. move.l d6,d2 { restore d2 }
  382. movem.l (sp)+,d3/a2/a3
  383. tst.w d0
  384. beq @dosdirend
  385. move.w d0,InOutRes
  386. @dosdirend:
  387. end;
  388. end;
  389. procedure mkdir(const s : string);[IOCheck];
  390. begin
  391. DosDir($39,s);
  392. end;
  393. procedure rmdir(const s : string);[IOCheck];
  394. begin
  395. DosDir($3a,s);
  396. end;
  397. procedure chdir(const s : string);[IOCheck];
  398. begin
  399. DosDir($3b,s);
  400. end;
  401. procedure getdir(drivenr : byte;var dir : string);[IOCheck];
  402. var
  403. temp : array[0..255] of char;
  404. sof : pchar;
  405. i : longint;
  406. begin
  407. sof:=pchar(@dir[4]);
  408. asm
  409. move.l d2,d6 { save d2 }
  410. movem.l d3/a2/a3,-(sp)
  411. { Get dir from drivenr : 0=default, 1=A etc... }
  412. move.w drivenr,-(sp)
  413. { put (previously saved) offset in si }
  414. pea dir
  415. { call attos function 47H : Get dir }
  416. move.w #$47,-(sp)
  417. { make the call }
  418. trap #1
  419. add.l #8,sp
  420. move.l d6,d2 { restore d2 }
  421. movem.l (sp)+,d3/a2/a3
  422. end;
  423. { Now Dir should be filled with directory in ASCIIZ, }
  424. { starting from dir[4] }
  425. dir[0]:=#3;
  426. dir[2]:=':';
  427. dir[3]:='\';
  428. i:=4;
  429. { conversation to Pascal string }
  430. while (dir[i]<>#0) do
  431. begin
  432. { convert path name to DOS }
  433. if dir[i]='/' then
  434. dir[i]:='\';
  435. dir[0]:=chr(i);
  436. inc(i);
  437. end;
  438. { upcase the string (FPKPascal function) }
  439. dir:=upcase(dir);
  440. if drivenr<>0 then { Drive was supplied. We know it }
  441. dir[1]:=chr(65+drivenr-1)
  442. else
  443. begin
  444. asm
  445. move.l d2,d6 { save d2 }
  446. movem.l d3/a2/a3,-(sp)
  447. move.w #$19,-(sp)
  448. trap #1
  449. add.l #2,sp
  450. move.l d6,d2 { restore d2 }
  451. movem.l (sp)+,d3/a2/a3
  452. end;
  453. dir[1]:=chr(i);
  454. end;
  455. end;
  456. {*****************************************************************************
  457. SystemUnit Initialization
  458. *****************************************************************************}
  459. procedure OpenStdIO(var f:text;mode:word;hdl:longint);
  460. begin
  461. Assign(f,'');
  462. TextRec(f).Handle:=hdl;
  463. TextRec(f).Mode:=mode;
  464. TextRec(f).InOutFunc:=@FileInOutFunc;
  465. TextRec(f).FlushFunc:=@FileInOutFunc;
  466. TextRec(f).Closefunc:=@fileclosefunc;
  467. end;
  468. begin
  469. { Initialize ExitProc }
  470. ExitProc:=Nil;
  471. { to test stack depth }
  472. loweststack:=maxlongint;
  473. { Setup heap }
  474. InitHeap;
  475. { Setup stdin, stdout and stderr }
  476. OpenStdIO(Input,fmInput,StdInputHandle);
  477. OpenStdIO(Output,fmOutput,StdOutputHandle);
  478. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  479. { Reset IO Error }
  480. InOutRes:=0;
  481. end.
  482. {
  483. $Log$
  484. Revision 1.3 1998-07-01 14:40:20 carl
  485. + new stack checking implemented
  486. + IOCheck for chdir , getdir , mkdir and rmdir
  487. Revision 1.1.1.1 1998/03/25 11:18:47 root
  488. * Restored version
  489. Revision 1.8 1998/02/23 02:27:39 carl
  490. * make it link correctly
  491. Revision 1.7 1998/02/06 16:33:02 carl
  492. * oops... commited wrong file
  493. + do_open is now standard with other platforms
  494. Revision 1.5 1998/01/31 19:32:51 carl
  495. - removed incorrect $define
  496. Revision 1.4 1998/01/27 10:55:45 peter
  497. * Word Handles from -1 -> $ffff
  498. Revision 1.3 1998/01/25 22:44:14 peter
  499. * Using uniform layout
  500. }