sysatari.pas 14 KB

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