OVL.MOD 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. MODULE ovl;
  2. (* Copyright (C) 1987-1992 Clarion Software Corporation *)
  3. IMPORT Lib,Str,FIO,IO,Storage;
  4. (*%F _fdata*) Make program in XLarge or MThread model (*%E*)
  5. CONST
  6. MaxOverlay = 9;
  7. TYPE
  8. String = ARRAY [0..99] OF CHAR;
  9. tUnit = RECORD
  10. Name:String;
  11. Start:LONGCARD;
  12. StartSeg:CARDINAL; (* == CARDINAL(Start DIV 16) *)
  13. Diff:CARDINAL; (* in paras between new and old position *)
  14. Overlay:[0..MaxOverlay];
  15. UnitPadding:ARRAY [1..128-( SIZE(String)+4+2+2+2 )] OF BYTE;
  16. END;
  17. tfix=RECORD
  18. locoff:SHORTCARD; (* high 4 bits = overlay number *)
  19. locseg:CARDINAL;
  20. target:CARDINAL;
  21. END;
  22. texeheader = RECORD
  23. magic : CARDINAL;
  24. sizemod512 : CARDINAL;
  25. sizediv512 : CARDINAL;
  26. numrelocitem : CARDINAL;
  27. headerparas : CARDINAL;
  28. heapminparas : CARDINAL;
  29. heapmaxparas : CARDINAL;
  30. initialss : CARDINAL;
  31. initialsp : CARDINAL;
  32. checksum : CARDINAL;
  33. initialip : CARDINAL;
  34. initialcs : CARDINAL;
  35. relocations : CARDINAL;
  36. ovrlay : CARDINAL;
  37. undocumented : CARDINAL;
  38. (* relocation items follow *)
  39. END;
  40. Str4 = ARRAY[0..3] OF CHAR ;
  41. VAR
  42. exefile,exefile1,mapfile,ovlfile,newmapfile:FIO.File;
  43. nmap:CARDINAL;
  44. map:ARRAY [1..300] OF tUnit;
  45. ovlheaders:ARRAY [0..MaxOverlay] OF RECORD
  46. Alloc: LONGCARD; (* total size *)
  47. Init: LONGCARD; (* size of initialised part *)
  48. nifix: CARDINAL;
  49. nefix: CARDINAL;
  50. copyr: Str4 ; (* used for checking overlay version *)
  51. END;
  52. ovlfiles:ARRAY [0..MaxOverlay] OF CARDINAL;
  53. PROCEDURE Erase(a:ARRAY OF CHAR);
  54. BEGIN
  55. IF FIO.Exists(a) THEN FIO.Erase(a); END;
  56. END Erase;
  57. PROCEDURE GiveBuf( f:FIO.File );
  58. TYPE buf = ARRAY [0..517] OF BYTE;
  59. VAR bufp :POINTER TO buf;
  60. BEGIN
  61. Storage.ALLOCATE(bufp,SIZE(buf));
  62. FIO.AssignBuffer(f,bufp^);
  63. END GiveBuf;
  64. PROCEDURE ReadHex(s:ARRAY OF BYTE;i:CARDINAL):LONGCARD;
  65. VAR res:LONGCARD; c:SHORTCARD;
  66. BEGIN
  67. res := 0;
  68. LOOP
  69. c := SHORTCARD(s[i]);
  70. INC(i);
  71. CASE CHAR(c) OF
  72. 'A'..'F': c := c - ( SHORTCARD('A') - 10 ) ;
  73. | '0'..'9': c := c - SHORTCARD('0');
  74. ELSE EXIT;
  75. END;
  76. res := res * 16 + VAL(LONGCARD, c );
  77. END;
  78. RETURN res;
  79. END ReadHex;
  80. PROCEDURE ReadMap;
  81. CONST
  82. delim = Str.CHARSET{' '};
  83. VAR
  84. done:BOOLEAN; i:CARDINAL;
  85. sname,gname,token,line:String;
  86. start:LONGCARD;
  87. BEGIN
  88. nmap := 0;
  89. REPEAT
  90. FIO.RdStr(mapfile,line) ;
  91. UNTIL (line[0]<>CHAR(0)) AND (line[1]>='0') AND (line[1]<='9') ;
  92. LOOP
  93. (* IO.WrStr(line);IO.WrLn; *)
  94. IF Str.Length(line) < 60 THEN EXIT END;
  95. Str.Item( token, line, delim, 0 );
  96. start := ReadHex( token,0 );
  97. Str.Item( sname, line, delim, 3 );
  98. Str.Item( gname, line, delim, 5 );
  99. IF ( Str.Compare(gname,'(none)') = 0 ) THEN
  100. gname := sname;
  101. END;
  102. IF ( nmap = 0 )
  103. OR ( Str.Compare(gname,map[nmap].Name) <> 0 )
  104. THEN
  105. INC(nmap);
  106. WITH map[nmap] DO
  107. Name := gname;
  108. Start := start;
  109. StartSeg := CARDINAL(start DIV 16);
  110. Overlay := 0;
  111. END;
  112. END;
  113. FIO.RdStr(mapfile,line);
  114. END;
  115. map[nmap+1] := map[nmap]; (* sentinel *)
  116. END ReadMap;
  117. PROCEDURE too_small_check;
  118. VAR i:CARDINAL;
  119. BEGIN
  120. FOR i := 1 TO nmap-1 DO
  121. IF ( map[i+1].StartSeg = map[i].StartSeg )
  122. AND ( map[i+1].Overlay <> map[i].Overlay ) THEN
  123. IO.WrStr( map[i].Name);
  124. IO.WrStr(' too small !!');
  125. IO.WrLn;
  126. HALT;
  127. END;
  128. END;
  129. END too_small_check;
  130. PROCEDURE ReadOvl;
  131. VAR c:CHAR;
  132. PROCEDURE nextc;
  133. BEGIN
  134. c := FIO.RdChar(ovlfile);
  135. END nextc;
  136. VAR
  137. ovln:CARDINAL;
  138. name:String;
  139. i:CARDINAL;
  140. BEGIN
  141. LOOP
  142. LOOP
  143. nextc;
  144. WHILE c <= ' ' DO
  145. IF c = CHAR(1AH) THEN EXIT END;
  146. nextc;
  147. END;
  148. IF c = ';' THEN (* comment *)
  149. WHILE c >= ' ' DO nextc END ;
  150. ELSE
  151. EXIT ;
  152. END ;
  153. END ;
  154. IF c = CHAR(1AH) THEN EXIT END;
  155. ovln := 0;
  156. WHILE ( c >= '0' ) AND ( c <= '9' ) DO
  157. ovln := ovln*10 + ORD(c) - ORD('0');
  158. nextc;
  159. END;
  160. WHILE c = ' ' DO nextc END;
  161. i := 0;
  162. WHILE ( c > ' ' ) DO
  163. name[i] := c;
  164. INC(i);
  165. nextc;
  166. END;
  167. name[i] := CHAR(0);
  168. (* search table *)
  169. i := 0;
  170. LOOP
  171. INC(i);
  172. IF i > nmap THEN
  173. IO.WrStr('Segment/group name ');
  174. IO.WrStr(name);
  175. IO.WrStr(' not found');
  176. IO.WrLn;
  177. EXIT;
  178. END;
  179. WITH map[i] DO
  180. IF Str.Compare( Name, name ) = 0 THEN
  181. Overlay := ovln;
  182. EXIT;
  183. END;
  184. END;
  185. END;
  186. END;
  187. END ReadOvl;
  188. VAR newseg_in_exe:BOOLEAN;
  189. PROCEDURE newseg( seg,off:CARDINAL ):CARDINAL;
  190. VAR loc:LONGCARD;
  191. k:CARDINAL;
  192. BEGIN
  193. loc := 16*VAL(LONGCARD,seg) + VAL(LONGCARD,off);
  194. k := 1;
  195. (* search for location segment = k *)
  196. WHILE ( k <= nmap ) AND ( loc >= map[k].Start ) DO INC(k) END;
  197. DEC(k);
  198. newseg_in_exe := ( map[k].Overlay = 0 );
  199. RETURN seg - map[k].Diff;
  200. END newseg;
  201. PROCEDURE hex(n:CARDINAL):CHAR;
  202. BEGIN
  203. n := n MOD 16;
  204. IF n > 9 THEN
  205. RETURN CHAR( n + ORD('A') - 10 )
  206. ELSE
  207. RETURN CHAR( n + ORD('0') );
  208. END;
  209. END hex;
  210. PROCEDURE EditMap;
  211. VAR line:String;
  212. i:CARDINAL;
  213. seg,off:CARDINAL;
  214. addr:LONGCARD;
  215. BEGIN
  216. FIO.Seek(mapfile,0);
  217. LOOP
  218. FIO.RdStr(mapfile,line);
  219. newseg_in_exe := TRUE;
  220. IF FIO.EOF THEN EXIT END;
  221. IF ( line[0] = ' ' ) AND ( line[5] = ':' ) THEN
  222. seg := CARDINAL(ReadHex(line,1));
  223. off := CARDINAL(ReadHex(line,6));
  224. seg := newseg( seg, off );
  225. line[4] := hex(seg); seg := seg DIV 16;
  226. line[3] := hex(seg); seg := seg DIV 16;
  227. line[2] := hex(seg); seg := seg DIV 16;
  228. line[1] := hex(seg); seg := seg DIV 16;
  229. ELSIF ( line[0] = ' ' ) AND ( line[6] = 'H' ) THEN
  230. addr := ReadHex(line,1);
  231. seg := CARDINAL(addr DIV 16);
  232. off := CARDINAL(addr) MOD 16;
  233. seg := newseg( seg, off );
  234. addr := LONGCARD(seg)*16 + LONGCARD(off) + ReadHex(line,15);
  235. line[4] := hex(seg); seg := seg DIV 16;
  236. line[3] := hex(seg); seg := seg DIV 16;
  237. line[2] := hex(seg); seg := seg DIV 16;
  238. line[1] := hex(seg); seg := seg DIV 16;
  239. seg := CARDINAL(addr DIV 16);
  240. line[11] := hex(seg); seg := seg DIV 16;
  241. line[10] := hex(seg); seg := seg DIV 16;
  242. line[9] := hex(seg); seg := seg DIV 16;
  243. line[8] := hex(seg); seg := seg DIV 16;
  244. END;
  245. (* IF NOT newseg_in_exe THEN
  246. IO.WrStr(line);
  247. IO.WrLn;
  248. END;
  249. *)
  250. IF newseg_in_exe THEN
  251. IF line[0] <> CHAR(0) THEN
  252. FIO.WrStr(newmapfile,line);
  253. END;
  254. FIO.WrLn(newmapfile);
  255. END;
  256. END;
  257. END EditMap;
  258. PROCEDURE PrintMap;
  259. VAR i:CARDINAL;
  260. BEGIN
  261. FOR i := 1 TO nmap DO
  262. WITH map[i] DO
  263. IO.WrStr(' Start='); IO.WrLngCard(Start,6);
  264. IO.WrStr(' Diff='); IO.WrCard(Diff,5);
  265. IO.WrCard(Overlay,3);
  266. IO.WrStr(' ');
  267. IO.WrStr(Name);
  268. IO.WrLn;
  269. END;
  270. END;
  271. END PrintMap;
  272. PROCEDURE ChkRead( VAR buf:ARRAY OF BYTE; count:CARDINAL );
  273. BEGIN
  274. IF FIO.RdBin( exefile, buf, count ) <> count THEN
  275. IO.WrStr('?? on read');
  276. HALT;
  277. END;
  278. END ChkRead;
  279. PROCEDURE ChkRead1( VAR buf:ARRAY OF BYTE; count:CARDINAL );
  280. BEGIN
  281. IF FIO.RdBin( exefile1, buf, count ) <> count THEN
  282. IO.WrStr('?? on read');
  283. HALT;
  284. END;
  285. END ChkRead1;
  286. PROCEDURE Copy(src,dst:CARDINAL; count:CARDINAL):CARDINAL;
  287. VAR amount:CARDINAL; actual:CARDINAL;
  288. buf:ARRAY [0..0FFFH] OF SHORTCARD;
  289. res:CARDINAL;
  290. BEGIN
  291. res := 0;
  292. WHILE count > 0 DO
  293. amount := count;
  294. IF amount > SIZE(buf) THEN
  295. amount := SIZE(buf);
  296. END;
  297. actual := FIO.RdBin( src, buf, amount );
  298. IF actual <> 0 THEN
  299. FIO.WrBin( dst, buf, actual );
  300. END;
  301. DEC(count,amount);
  302. INC(res,actual);
  303. END;
  304. RETURN res;
  305. END Copy;
  306. PROCEDURE LongCopy(src,dst:CARDINAL; count:LONGCARD);
  307. VAR junk:CARDINAL;
  308. BEGIN
  309. WHILE count > 8000H DO
  310. junk := Copy(src,dst,8000H);
  311. DEC(count,8000H);
  312. END;
  313. junk := Copy( src,dst,CARDINAL(count) );
  314. END LongCopy;
  315. PROCEDURE resetexe;
  316. VAR filename:ARRAY[0..255] OF CHAR;
  317. BEGIN
  318. Str.Concat( filename, Lib.CommandLine^, '.exe');
  319. exefile := FIO.Create(filename);
  320. END resetexe;
  321. PROCEDURE MakeFix( k:CARDINAL; loc:LONGCARD; j:CARDINAL; target:CARDINAL; internalfix:BOOLEAN );
  322. VAR
  323. tmp:CARDINAL;
  324. fix:tfix;
  325. BEGIN
  326. (*
  327. IO.WrStr('k='); IO.WrCard(k,1);
  328. IO.WrStr('j='); IO.WrCard(j,1);
  329. IO.WrStr( ' map[k].Overlay=' ); IO.WrCard( ORD(map[k].Overlay),1 );
  330. IO.WrStr( ' map[j].Overlay=' ); IO.WrCard( ORD(map[j].Overlay),1 );
  331. IO.WrStr( ' loc=' ); IO.WrLngCard( loc, 1 );
  332. IO.WrStr( ' target=' ); IO.WrCard( target, 1 );
  333. IO.WrLn;
  334. *)
  335. IF internalfix THEN
  336. IF map[k].Overlay = 0 THEN
  337. IF map[j].Overlay <> 0 THEN
  338. RETURN; (* overlay 0 requires only internal fixups to itself *)
  339. END;
  340. END;
  341. INC( ovlheaders[map[k].Overlay].nifix );
  342. tmp := j; j := k; k := tmp;
  343. ELSE
  344. IF map[j].Overlay = 0 THEN RETURN END;
  345. IF map[j].Overlay = map[k].Overlay THEN RETURN END;
  346. INC( ovlheaders[map[j].Overlay].nefix );
  347. END;
  348. fix.locoff := ( SHORTCARD(loc) MOD 16 ) + 16*SHORTCARD( map[k].Overlay );
  349. fix.locseg := CARDINAL(loc DIV 16);
  350. fix.target := target;
  351. FIO.WrBin( ovlfiles[map[j].Overlay], fix, SIZE(fix) );
  352. END MakeFix;
  353. PROCEDURE Main;
  354. VAR
  355. exe:texeheader;
  356. dummy:CARDINAL;
  357. i,j,k:CARDINAL;
  358. hsize:LONGCARD;
  359. filename:String;
  360. ext:ARRAY[0..3] OF CHAR;
  361. pad:ARRAY[0..15] OF SHORTCARD;
  362. padsize:CARDINAL;
  363. copysize:CARDINAL;
  364. target:CARDINAL;
  365. internalfix:BOOLEAN;
  366. fixlocabs:LONGCARD;
  367. fsize:LONGCARD;
  368. hpage:CARDINAL;
  369. fix:tfix;
  370. exefix:RECORD off,seg:CARDINAL END;
  371. file:CARDINAL;
  372. BEGIN
  373. ChkRead( exe, SIZE(exe) );
  374. hsize := VAL(LONGCARD,exe.headerparas)*16;
  375. FOR i := 0 TO MaxOverlay DO
  376. ovlfiles[i] := CARDINAL(-1);
  377. WITH ovlheaders[i] DO
  378. Alloc := 0;
  379. Init := 0;
  380. nifix := 0;
  381. nefix := 0;
  382. copyr := 'JPI' ;
  383. END;
  384. END;
  385. FOR i := 0 TO 15 DO pad[i] := 0 END;
  386. (* Now read through exe file redistributing segments *)
  387. FIO.Seek( exefile, hsize );
  388. FOR i := 1 TO nmap DO
  389. WITH map[i] DO
  390. WITH ovlheaders[Overlay] DO
  391. file := ovlfiles[Overlay];
  392. IF file = CARDINAL(-1) THEN
  393. ext := '.ov ';
  394. ext[3] := CHAR( Overlay+ORD('0') );
  395. Str.Concat( filename, Lib.CommandLine^, ext );
  396. file := FIO.Create( filename );
  397. ovlfiles[Overlay] := file;
  398. FIO.WrBin( file, pad, 16 );
  399. END;
  400. padsize := ( CARDINAL(Start) - CARDINAL(Alloc) ) MOD 16;
  401. FIO.WrBin( file, pad, padsize );
  402. INC( Init, VAL(LONGCARD, padsize) );
  403. INC( Alloc, VAL(LONGCARD,padsize) );
  404. Diff := CARDINAL(Start DIV 16) - CARDINAL(Alloc DIV 16);
  405. copysize := CARDINAL(map[i+1].Start-Start);
  406. INC( Init, VAL(LONGCARD, Copy( exefile, file, copysize ) ) );
  407. INC( Alloc , VAL(LONGCARD,copysize) ) ;
  408. END;
  409. END;
  410. END;
  411. (* OK. We now have the overlay files, so work out the fixups *)
  412. (* First allocate buffers for overlays *)
  413. FOR i := 0 TO MaxOverlay DO
  414. IF ovlfiles[i] <> CARDINAL(-1) THEN
  415. GiveBuf( ovlfiles[i] );
  416. END;
  417. END;
  418. FOR internalfix := FALSE TO TRUE DO
  419. FIO.Seek( exefile1, VAL(LONGCARD,exe.relocations) );
  420. FOR i := 1 TO exe.numrelocitem DO
  421. ChkRead1( exefix, SIZE(exefix) );
  422. fixlocabs := VAL(LONGCARD,exefix.off)+16*VAL(LONGCARD,exefix.seg);
  423. FIO.Seek( exefile, hsize+fixlocabs);
  424. ChkRead( target, SIZE(target) );
  425. k := 1;
  426. (* search for location segment = k *)
  427. WHILE ( k <= nmap ) AND ( fixlocabs >= map[k].Start ) DO INC(k) END;
  428. DEC(k);
  429. (*
  430. IO.WrCard(target,1);
  431. IO.WrStr(' at ');
  432. IO.WrLngCard(fixlocabs,1);
  433. IO.WrLn;
  434. *)
  435. j := 0;
  436. LOOP (* search for target segment = j *)
  437. INC(j);
  438. IF ( j > nmap ) OR ( target < map[j].StartSeg ) THEN
  439. DEC(j);
  440. MakeFix( k, fixlocabs - VAL(LONGCARD,map[k].Diff)*16,
  441. j, target - map[j].Diff, internalfix );
  442. EXIT;
  443. END;
  444. END;
  445. END;
  446. END;
  447. (* Phew ! *)
  448. (* Now save the headers *)
  449. FOR i := 0 TO MaxOverlay DO
  450. WITH ovlheaders[i] DO
  451. file := ovlfiles[i];
  452. IF file <> CARDINAL(-1) THEN
  453. FIO.Seek( file, 0 );
  454. FIO.WrBin( file, ovlheaders[i], 16 );
  455. END;
  456. END;
  457. END;
  458. (* Now rewrite exe file *)
  459. resetexe;
  460. hpage := ( 4*ovlheaders[0].nifix + SIZE(texeheader) + 511 ) DIV 512;
  461. hsize := VAL(LONGCARD,hpage * 512);
  462. FIO.Seek( exefile, VAL(LONGCARD,512*hpage) );
  463. file := ovlfiles[0];
  464. FIO.Seek( file, 16 );
  465. LongCopy( file, exefile, ovlheaders[0].Init );
  466. FIO.Seek( exefile, 0 );
  467. exe.numrelocitem := ovlheaders[0].nifix;
  468. exe.headerparas := hpage*32;
  469. exe.relocations := SIZE(texeheader);
  470. exe.initialcs := newseg(exe.initialcs,exe.initialip);
  471. exe.initialss := newseg(exe.initialss,16);
  472. fsize := FIO.Size(exefile);
  473. exe.sizemod512 := CARDINAL(fsize) MOD 512;
  474. exe.sizediv512 := CARDINAL((fsize+511) DIV 512);
  475. FIO.WrBin( exefile, exe, SIZE(texeheader) );
  476. FOR i := 1 TO ovlheaders[0].nifix DO
  477. dummy := FIO.RdBin( file, fix, SIZE(fix) );
  478. fixlocabs := VAL(LONGCARD,fix.locoff)+16*VAL(LONGCARD,fix.locseg);
  479. FIO.Seek( exefile, hsize+fixlocabs);
  480. FIO.WrBin( exefile, fix.target, 2 );
  481. (*
  482. IO.WrStr('Repatch at');
  483. IO.WrLngCard( hsize+fixlocabs,1 );
  484. IO.WrStr(' value ');
  485. IO.WrCard( fix.target, 1 );
  486. IO.WrLn;
  487. *)
  488. FIO.Seek( exefile, VAL(LONGCARD, SIZE(texeheader) + (i-1)*4 ) );
  489. exefix.off := VAL(CARDINAL,fix.locoff);
  490. exefix.seg := fix.locseg;
  491. FIO.WrBin( exefile, exefix, SIZE(exefix) );
  492. END;
  493. (* close buffered ovl files *)
  494. FOR i := 0 TO MaxOverlay DO
  495. IF ovlfiles[i] <> CARDINAL(-1) THEN
  496. FIO.Close( ovlfiles[i] );
  497. END;
  498. END;
  499. END Main;
  500. VAR filename:ARRAY[0..255] OF CHAR;
  501. PROCEDURE init;
  502. VAR
  503. renname : FIO.PathStr ;
  504. BEGIN
  505. Str.Concat( filename, Lib.CommandLine^, '.exe');
  506. exefile := FIO.Open(filename); (* no buffering because random access *)
  507. exefile1 := FIO.Open(filename); GiveBuf(exefile1);
  508. Str.Concat( filename, Lib.CommandLine^, '.ovl');
  509. ovlfile := FIO.Open(filename); GiveBuf(ovlfile);
  510. Str.Concat( filename, Lib.CommandLine^, '.map');
  511. Str.Concat( renname, Lib.CommandLine^, '.omp');
  512. Erase(renname) ;
  513. FIO.Rename(filename,renname);
  514. mapfile := FIO.Open(renname); GiveBuf(mapfile);
  515. newmapfile := FIO.Create(filename); GiveBuf(newmapfile);
  516. END init;
  517. BEGIN
  518. init;
  519. ReadMap;
  520. ReadOvl;
  521. too_small_check;
  522. Main;
  523. (* PrintMap; *)
  524. EditMap;
  525. Str.Concat( filename, Lib.CommandLine^, '.ov0');
  526. Erase(filename) ;
  527. FIO.Close(newmapfile) ;
  528. END ovl.
  529.