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