omfbase.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. {
  2. Copyright (c) 2015 by Nikolay Nikolov
  3. Contains Relocatable Object Module Format (OMF) definitions
  4. This is the object format used on the i8086-msdos platform.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit omfbase;
  19. {$i fpcdefs.inc}
  20. interface
  21. {$H+}
  22. uses
  23. cclasses,
  24. owbase;
  25. const
  26. { OMF record types }
  27. RT_THEADR = $80; { Translator Header Record }
  28. RT_LHEADR = $82; { Library Module Header Record }
  29. RT_COMENT = $88; { Comment Record }
  30. RT_MODEND = $8A; { Module End Record }
  31. RT_MODEND32 = $8B;
  32. RT_EXTDEF = $8C; { External Names Definition Record }
  33. RT_PUBDEF = $90; { Public Names Definition Record }
  34. RT_PUBDEF32 = $91;
  35. RT_LINNUM = $94; { Line Numbers Record }
  36. RT_LINNUM32 = $95;
  37. RT_LNAMES = $96; { List of Names Record }
  38. RT_SEGDEF = $98; { Segment Definition Record }
  39. RT_SEGDEF32 = $99;
  40. RT_GRPDEF = $9A; { Group Definition Record }
  41. RT_FIXUPP = $9C; { Fixup Record }
  42. RT_FIXUPP32 = $9D;
  43. RT_LEDATA = $A0; { Logical Enumerated Data Record }
  44. RT_LEDATA32 = $A1;
  45. RT_LIDATA = $A2; { Logical Iterated Data Record }
  46. RT_LIDATA32 = $A3;
  47. RT_COMDEF = $B0; { Communal Names Definition Record }
  48. RT_BAKPAT = $B2; { Backpatch Record }
  49. RT_BAKPAT32 = $B3;
  50. RT_LEXTDEF = $B4; { Local External Names Definition Record }
  51. RT_LEXTDEF32 = $B5;
  52. RT_LPUBDEF = $B6; { Local Public Names Definition Record }
  53. RT_LPUBDEF32 = $B7;
  54. RT_LCOMDEF = $B8; { Local Communal Names Definition Record }
  55. RT_CEXTDEF = $BC; { COMDAT External Names Definition Record }
  56. RT_COMDAT = $C2; { Initialized Communal Data Record }
  57. RT_COMDAT32 = $C3;
  58. RT_LINSYM = $C4; { Symbol Line Numbers Record }
  59. RT_LINSYM32 = $C5;
  60. RT_ALIAS = $C6; { Alias Definition Record }
  61. RT_NBKPAT = $C8; { Named Backpatch Record }
  62. RT_NBKPAT32 = $C9;
  63. RT_LLNAMES = $CA; { Local Logical Names Definition Record }
  64. RT_VERNUM = $CC; { OMF Version Number Record }
  65. RT_VENDEXT = $CE; { Vendor-specific OMF Extension Record }
  66. { OMF comment class }
  67. CC_Translator = $00; { language translator (compiler or assembler) name }
  68. CC_IntelCopyright = $01;
  69. CC_IntelReservedRangeStart = $02;
  70. CC_IntelReservedRangeEnd = $9B;
  71. CC_LibrarySpecifierObsolete = $81;
  72. CC_MsDosVersionObsolete = $9C;
  73. CC_MemoryModel = $9D;
  74. CC_DOSSEG = $9E;
  75. CC_DefaultLibrarySearchName = $9F;
  76. CC_OmfExtension = $A0;
  77. CC_NewOmfExtension = $A1;
  78. CC_LinkPassSeparator = $A2;
  79. CC_LIBMOD = $A3;
  80. CC_EXESTR = $A4;
  81. CC_INCERR = $A6;
  82. CC_NOPAD = $A7;
  83. CC_WKEXT = $A8;
  84. CC_LZEXT = $A9;
  85. CC_Comment = $DA;
  86. CC_Compiler = $DB;
  87. CC_Date = $DC;
  88. CC_Timestamp = $DD;
  89. CC_User = $DF;
  90. CC_DependencyFileBorland = $E9;
  91. CC_CommandLineMicrosoft = $FF;
  92. type
  93. TOmfSegmentAlignment = (
  94. saAbsolute = 0,
  95. saRelocatableByteAligned = 1,
  96. saRelocatableWordAligned = 2,
  97. saRelocatableParaAligned = 3,
  98. saRelocatablePageAligned = 4, { 32-bit linkers extension }
  99. saRelocatableDWordAligned = 5, { 32-bit linkers extension }
  100. saNotSupported = 6,
  101. saNotDefined = 7);
  102. TOmfSegmentCombination = (
  103. scPrivate = 0,
  104. scReserved1 = 1,
  105. scPublic = 2,
  106. scReserved3 = 3,
  107. scPublic4 = 4, { same as scPublic }
  108. scStack = 5,
  109. scCommon = 6,
  110. scPublic7 = 7); { same as scPublic }
  111. TOmfSegmentUse = (suUse16, suUse32);
  112. { TOmfOrderedNameCollection }
  113. TOmfOrderedNameCollection = class
  114. private
  115. FStringList: array of string;
  116. function GetCount: Integer;
  117. function GetString(Index: Integer): string;
  118. procedure SetString(Index: Integer; AValue: string);
  119. public
  120. function Add(const S: string): Integer;
  121. procedure Clear;
  122. property Strings [Index: Integer]: string read GetString write SetString; default;
  123. property Count: Integer read GetCount;
  124. end;
  125. { TOmfRawRecord }
  126. TOmfRawRecord = class
  127. private
  128. function GetChecksumByte: Byte;
  129. function GetRecordLength: Word;
  130. function GetRecordType: Byte;
  131. procedure SetChecksumByte(AValue: Byte);
  132. procedure SetRecordLength(AValue: Word);
  133. procedure SetRecordType(AValue: Byte);
  134. public
  135. RawData: array [-3..65535] of Byte;
  136. property RecordType: Byte read GetRecordType write SetRecordType;
  137. property RecordLength: Word read GetRecordLength write SetRecordLength;
  138. function ReadStringAt(Offset: Integer; out s: string): Integer;
  139. function WriteStringAt(Offset: Integer; s: string): Integer;
  140. function ReadIndexedRef(Offset: Integer; out IndexedRef: Integer): Integer;
  141. function WriteIndexedRef(Offset: Integer; IndexedRef: Integer): Integer;
  142. procedure CalculateChecksumByte;
  143. function VerifyChecksumByte: boolean;
  144. property ChecksumByte: Byte read GetChecksumByte write SetChecksumByte;
  145. procedure ReadFrom(aReader: TObjectReader);
  146. procedure WriteTo(aWriter: TObjectWriter);
  147. end;
  148. { TOmfParsedRecord }
  149. TOmfParsedRecord = class
  150. public
  151. procedure DecodeFrom(RawRecord: TOmfRawRecord);virtual;abstract;
  152. procedure EncodeTo(RawRecord: TOmfRawRecord);virtual;abstract;
  153. end;
  154. { TOmfRecord_THEADR }
  155. TOmfRecord_THEADR = class(TOmfParsedRecord)
  156. private
  157. FModuleName: string;
  158. public
  159. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  160. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  161. property ModuleName: string read FModuleName write FModuleName;
  162. end;
  163. { TOmfRecord_COMENT }
  164. TOmfRecord_COMENT = class(TOmfParsedRecord)
  165. private
  166. FCommentType: Byte;
  167. FCommentClass: Byte;
  168. FCommentString: string;
  169. function GetNoList: Boolean;
  170. function GetNoPurge: Boolean;
  171. procedure SetNoList(AValue: Boolean);
  172. procedure SetNoPurge(AValue: Boolean);
  173. public
  174. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  175. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  176. property CommentType: Byte read FCommentType write FCommentType;
  177. property CommentClass: Byte read FCommentClass write FCommentClass;
  178. property CommentString: string read FCommentString write FCommentString;
  179. property NoPurge: Boolean read GetNoPurge write SetNoPurge;
  180. property NoList: Boolean read GetNoList write SetNoList;
  181. end;
  182. { TOmfRecord_LNAMES }
  183. TOmfRecord_LNAMES = class(TOmfParsedRecord)
  184. private
  185. FNames: TOmfOrderedNameCollection;
  186. FNextIndex: Integer;
  187. public
  188. constructor Create;
  189. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  190. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  191. property Names: TOmfOrderedNameCollection read FNames write FNames;
  192. property NextIndex: Integer read FNextIndex write FNextIndex;
  193. end;
  194. { TOmfRecord_SEGDEF }
  195. TOmfRecord_SEGDEF = class(TOmfParsedRecord)
  196. FAlignment: TOmfSegmentAlignment;
  197. FCombination: TOmfSegmentCombination;
  198. FUse: TOmfSegmentUse;
  199. FFrameNumber: Word;
  200. FOffset: Byte;
  201. FIs32Bit: Boolean;
  202. FSegmentLength: Int64; { int64, because it can be 2**32 }
  203. FSegmentNameIndex: Integer;
  204. FClassNameIndex: Integer;
  205. FOverlayNameIndex: Integer;
  206. public
  207. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  208. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  209. property Alignment: TOmfSegmentAlignment read FAlignment write FAlignment;
  210. property Combination: TOmfSegmentCombination read FCombination write FCombination;
  211. property Use: TOmfSegmentUse read FUse write FUse;
  212. property FrameNumber: Word read FFrameNumber write FFrameNumber;
  213. property Offset: Byte read FOffset write FOffset;
  214. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  215. property SegmentLength: Int64 read FSegmentLength write FSegmentLength;
  216. property SegmentNameIndex: Integer read FSegmentNameIndex write FSegmentNameIndex;
  217. property ClassNameIndex: Integer read FClassNameIndex write FClassNameIndex;
  218. property OverlayNameIndex: Integer read FOverlayNameIndex write FOverlayNameIndex;
  219. end;
  220. TSegmentList = array of Integer;
  221. { TOmfRecord_GRPDEF }
  222. TOmfRecord_GRPDEF = class(TOmfParsedRecord)
  223. private
  224. FGroupNameIndex: Integer;
  225. FSegmentList: TSegmentList;
  226. public
  227. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  228. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  229. property GroupNameIndex: Integer read FGroupNameIndex write FGroupNameIndex;
  230. property SegmentList: TSegmentList read FSegmentList write FSegmentList;
  231. end;
  232. implementation
  233. uses
  234. verbose;
  235. { TOmfOrderedNameCollection }
  236. function TOmfOrderedNameCollection.GetString(Index: Integer): string;
  237. begin
  238. Result:=FStringList[Index-1];
  239. end;
  240. function TOmfOrderedNameCollection.GetCount: Integer;
  241. begin
  242. Result:=Length(FStringList);
  243. end;
  244. procedure TOmfOrderedNameCollection.SetString(Index: Integer; AValue: string);
  245. begin
  246. FStringList[Index-1]:=AValue;
  247. end;
  248. function TOmfOrderedNameCollection.Add(const S: string): Integer;
  249. begin
  250. Result:=Length(FStringList)+1;
  251. SetLength(FStringList,Result);
  252. FStringList[Result-1]:=S;
  253. end;
  254. procedure TOmfOrderedNameCollection.Clear;
  255. begin
  256. SetLength(FStringList,0);
  257. end;
  258. { TOmfRawRecord }
  259. function TOmfRawRecord.GetRecordType: Byte;
  260. begin
  261. Result:=RawData[-3];
  262. end;
  263. procedure TOmfRawRecord.SetRecordType(AValue: Byte);
  264. begin
  265. RawData[-3]:=AValue;
  266. end;
  267. function TOmfRawRecord.GetRecordLength: Word;
  268. begin
  269. Result:=RawData[-2] or (RawData[-1] shl 8);
  270. end;
  271. procedure TOmfRawRecord.SetRecordLength(AValue: Word);
  272. begin
  273. RawData[-2]:=Byte(AValue);
  274. RawData[-1]:=Byte(AValue shr 8);
  275. end;
  276. function TOmfRawRecord.ReadStringAt(Offset: Integer; out s: string): Integer;
  277. var
  278. len: Byte;
  279. begin
  280. len:=RawData[Offset];
  281. Result:=Offset+len+1;
  282. if result>RecordLength then
  283. internalerror(2015033103);
  284. SetLength(s, len);
  285. UniqueString(s);
  286. Move(RawData[Offset+1],s[1],len);
  287. end;
  288. function TOmfRawRecord.WriteStringAt(Offset: Integer; s: string): Integer;
  289. begin
  290. if Length(s)>255 then
  291. internalerror(2015033101);
  292. result:=Offset+Length(s)+1;
  293. if result>High(RawData) then
  294. internalerror(2015033102);
  295. RawData[Offset]:=Length(s);
  296. Move(s[1], RawData[Offset+1], Length(s));
  297. end;
  298. function TOmfRawRecord.ReadIndexedRef(Offset: Integer; out IndexedRef: Integer): Integer;
  299. begin
  300. Result:=Offset+1;
  301. if result>RecordLength then
  302. internalerror(2015033103);
  303. IndexedRef:=RawData[Offset];
  304. if IndexedRef<=$7f then
  305. exit;
  306. Result:=Offset+2;
  307. if result>RecordLength then
  308. internalerror(2015033103);
  309. IndexedRef:=((IndexedRef and $7f) shl 8)+RawData[Offset+1];
  310. end;
  311. function TOmfRawRecord.WriteIndexedRef(Offset: Integer; IndexedRef: Integer): Integer;
  312. begin
  313. if (IndexedRef<0) or (IndexedRef>$7FFF) then
  314. internalerror(2015040303);
  315. if IndexedRef<=$7f then
  316. begin
  317. Result:=Offset+1;
  318. if Result>High(RawData) then
  319. internalerror(2015033102);
  320. RawData[Offset]:=IndexedRef;
  321. end
  322. else
  323. begin
  324. Result:=Offset+2;
  325. if Result>High(RawData) then
  326. internalerror(2015033102);
  327. RawData[Offset]:=$80+(IndexedRef shr 8);
  328. RawData[Offset+1]:=Byte(IndexedRef);
  329. end;
  330. end;
  331. function TOmfRawRecord.GetChecksumByte: Byte;
  332. begin
  333. if RecordLength>0 then
  334. Result:=RawData[RecordLength-1]
  335. else
  336. Result:=0;
  337. end;
  338. procedure TOmfRawRecord.SetChecksumByte(AValue: Byte);
  339. begin
  340. if RecordLength>0 then
  341. RawData[RecordLength-1]:=AValue;
  342. end;
  343. procedure TOmfRawRecord.CalculateChecksumByte;
  344. var
  345. I: Integer;
  346. b: Byte;
  347. begin
  348. b:=0;
  349. for I:=-3 to RecordLength-2 do
  350. b:=byte(b+RawData[I]);
  351. SetChecksumByte($100-b);
  352. end;
  353. function TOmfRawRecord.VerifyChecksumByte: boolean;
  354. var
  355. I: Integer;
  356. b: Byte;
  357. begin
  358. { according to the OMF spec, some tools always write a 0 rather than
  359. computing the checksum, so it should also be accepted as correct }
  360. if ChecksumByte=0 then
  361. exit(true);
  362. b:=0;
  363. for I:=-3 to RecordLength-1 do
  364. b:=byte(b+RawData[I]);
  365. Result:=(b=0);
  366. end;
  367. procedure TOmfRawRecord.ReadFrom(aReader: TObjectReader);
  368. begin
  369. aReader.read(RawData, 3);
  370. aReader.read(RawData[0], RecordLength);
  371. end;
  372. procedure TOmfRawRecord.WriteTo(aWriter: TObjectWriter);
  373. begin
  374. aWriter.write(RawData, RecordLength+3);
  375. end;
  376. { TOmfRecord_THEADR }
  377. procedure TOmfRecord_THEADR.DecodeFrom(RawRecord: TOmfRawRecord);
  378. begin
  379. RawRecord.ReadStringAt(0,FModuleName);
  380. end;
  381. procedure TOmfRecord_THEADR.EncodeTo(RawRecord: TOmfRawRecord);
  382. var
  383. NextOfs: Integer;
  384. begin
  385. RawRecord.RecordType:=RT_THEADR;
  386. NextOfs:=RawRecord.WriteStringAt(0,ModuleName);
  387. RawRecord.RecordLength:=NextOfs+1;
  388. RawRecord.CalculateChecksumByte;
  389. end;
  390. { TOmfRecord_COMENT }
  391. function TOmfRecord_COMENT.GetNoList: Boolean;
  392. begin
  393. Result:=(CommentType and $40)<>0;
  394. end;
  395. function TOmfRecord_COMENT.GetNoPurge: Boolean;
  396. begin
  397. Result:=(CommentType and $80)<>0;
  398. end;
  399. procedure TOmfRecord_COMENT.SetNoList(AValue: Boolean);
  400. begin
  401. if AValue then
  402. CommentType:=CommentType or $40
  403. else
  404. CommentType:=CommentType and $BF;
  405. end;
  406. procedure TOmfRecord_COMENT.SetNoPurge(AValue: Boolean);
  407. begin
  408. if AValue then
  409. CommentType:=CommentType or $80
  410. else
  411. CommentType:=CommentType and $7F;
  412. end;
  413. procedure TOmfRecord_COMENT.DecodeFrom(RawRecord: TOmfRawRecord);
  414. begin
  415. if RawRecord.RecordLength<3 then
  416. internalerror(2015033104);
  417. CommentType:=RawRecord.RawData[0];
  418. CommentClass:=RawRecord.RawData[1];
  419. SetLength(FCommentString,RawRecord.RecordLength-3);
  420. UniqueString(FCommentString);
  421. Move(RawRecord.RawData[2],FCommentString[1],Length(FCommentString));
  422. end;
  423. procedure TOmfRecord_COMENT.EncodeTo(RawRecord: TOmfRawRecord);
  424. begin
  425. RawRecord.RecordType:=RT_COMENT;
  426. if (Length(FCommentString)+3)>High(RawRecord.RawData) then
  427. internalerror(2015033105);
  428. RawRecord.RecordLength:=Length(FCommentString)+3;
  429. RawRecord.RawData[0]:=CommentType;
  430. RawRecord.RawData[1]:=CommentClass;
  431. Move(FCommentString[1],RawRecord.RawData[2],Length(FCommentString));
  432. RawRecord.CalculateChecksumByte;
  433. end;
  434. { TOmfRecord_LNAMES }
  435. constructor TOmfRecord_LNAMES.Create;
  436. begin
  437. FNextIndex:=1;
  438. end;
  439. procedure TOmfRecord_LNAMES.DecodeFrom(RawRecord: TOmfRawRecord);
  440. begin
  441. {TODO: implement}
  442. internalerror(2015040101);
  443. end;
  444. procedure TOmfRecord_LNAMES.EncodeTo(RawRecord: TOmfRawRecord);
  445. const
  446. RecordLengthLimit = 1024;
  447. var
  448. Len,LastIncludedIndex,NextOfs,I: Integer;
  449. begin
  450. RawRecord.RecordType:=RT_LNAMES;
  451. { find out how many strings can we include until we reach the length limit }
  452. Len:=1;
  453. LastIncludedIndex:=NextIndex-1;
  454. repeat
  455. Inc(LastIncludedIndex);
  456. Inc(Len,Length(Names[LastIncludedIndex])+1);
  457. until (LastIncludedIndex>=Names.Count) or ((Len+Length(Names[LastIncludedIndex+1])+1)>=RecordLengthLimit);
  458. { write the strings... }
  459. NextOfs:=0;
  460. for I:=NextIndex to LastIncludedIndex do
  461. NextOfs:=RawRecord.WriteStringAt(NextOfs,Names[I]);
  462. RawRecord.RecordLength:=Len;
  463. RawRecord.CalculateChecksumByte;
  464. { update NextIndex }
  465. NextIndex:=LastIncludedIndex+1;
  466. end;
  467. { TOmfRecord_SEGDEF }
  468. procedure TOmfRecord_SEGDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  469. var
  470. B: Byte;
  471. Big: Boolean;
  472. NextOfs: Integer;
  473. MinLen: Integer;
  474. begin
  475. if not (RawRecord.RecordType in [RT_SEGDEF,RT_SEGDEF32]) then
  476. internalerror(2015040301);
  477. Is32Bit:=RawRecord.RecordType=RT_SEGDEF32;
  478. MinLen:=7; { b(1)+seglength(2..4)+segnameindex(1..2)+classnameindex(1..2)+overlaynameindex(1..2)+checksum }
  479. if Is32Bit then
  480. inc(MinLen,2);
  481. if RawRecord.RecordLength<MinLen then
  482. internalerror(2015040305);
  483. B:=RawRecord.RawData[0];
  484. Alignment:=TOmfSegmentAlignment(B shr 5);
  485. Combination:=TOmfSegmentCombination((B shr 2) and 7);
  486. Big:=(B and 2)<>0;
  487. Use:=TOmfSegmentUse(B and 1);
  488. NextOfs:=1;
  489. if Alignment=saAbsolute then
  490. begin
  491. inc(MinLen,3);
  492. if RawRecord.RecordLength<MinLen then
  493. internalerror(2015040305);
  494. FrameNumber:=RawRecord.RawData[1]+(RawRecord.RawData[2] shl 8);
  495. Offset:=RawRecord.RawData[3];
  496. NextOfs:=4;
  497. end
  498. else
  499. begin
  500. FrameNumber:=0;
  501. Offset:=0;
  502. end;
  503. if Is32Bit then
  504. begin
  505. SegmentLength:=RawRecord.RawData[NextOfs]+
  506. (RawRecord.RawData[NextOfs+1] shl 8)+
  507. (RawRecord.RawData[NextOfs+2] shl 16)+
  508. (RawRecord.RawData[NextOfs+3] shl 24);
  509. if Big then
  510. if SegmentLength=0 then
  511. SegmentLength:=4294967296
  512. else
  513. internalerror(2015040306);
  514. Inc(NextOfs,4);
  515. end
  516. else
  517. begin
  518. SegmentLength:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  519. if Big then
  520. if SegmentLength=0 then
  521. SegmentLength:=65536
  522. else
  523. internalerror(2015040306);
  524. Inc(NextOfs,2);
  525. end;
  526. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FSegmentNameIndex);
  527. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FClassNameIndex);
  528. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FOverlayNameIndex);
  529. end;
  530. procedure TOmfRecord_SEGDEF.EncodeTo(RawRecord: TOmfRawRecord);
  531. var
  532. Big: Boolean;
  533. NextOfs: Integer;
  534. begin
  535. if Is32Bit then
  536. begin
  537. RawRecord.RecordType:=RT_SEGDEF32;
  538. if SegmentLength>4294967296 then
  539. internalerror(2015040302);
  540. Big:=SegmentLength=4294967296;
  541. end
  542. else
  543. begin
  544. RawRecord.RecordType:=RT_SEGDEF;
  545. if SegmentLength>65536 then
  546. internalerror(2015040302);
  547. Big:=SegmentLength=65536;
  548. end;
  549. RawRecord.RawData[0]:=(Ord(Alignment) shl 5) or (Ord(Combination) shl 2) or (Ord(Big) shl 1) or Ord(Use);
  550. NextOfs:=1;
  551. if Alignment=saAbsolute then
  552. begin
  553. RawRecord.RawData[1]:=Byte(FrameNumber);
  554. RawRecord.RawData[2]:=Byte(FrameNumber shr 8);
  555. RawRecord.RawData[3]:=Offset;
  556. NextOfs:=4;
  557. end;
  558. if Is32Bit then
  559. begin
  560. RawRecord.RawData[NextOfs]:=Byte(SegmentLength);
  561. RawRecord.RawData[NextOfs+1]:=Byte(SegmentLength shr 8);
  562. RawRecord.RawData[NextOfs+2]:=Byte(SegmentLength shr 16);
  563. RawRecord.RawData[NextOfs+3]:=Byte(SegmentLength shr 24);
  564. Inc(NextOfs,4);
  565. end
  566. else
  567. begin
  568. RawRecord.RawData[NextOfs]:=Byte(SegmentLength);
  569. RawRecord.RawData[NextOfs+1]:=Byte(SegmentLength shr 8);
  570. Inc(NextOfs,2);
  571. end;
  572. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,SegmentNameIndex);
  573. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,ClassNameIndex);
  574. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,OverlayNameIndex);
  575. RawRecord.RecordLength:=NextOfs+1;
  576. RawRecord.CalculateChecksumByte;
  577. end;
  578. { TOmfRecord_GRPDEF }
  579. procedure TOmfRecord_GRPDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  580. begin
  581. {TODO: implement}
  582. internalerror(2015040101);
  583. end;
  584. procedure TOmfRecord_GRPDEF.EncodeTo(RawRecord: TOmfRawRecord);
  585. var
  586. NextOfs: Integer;
  587. Segment: Integer;
  588. begin
  589. RawRecord.RecordType:=RT_GRPDEF;
  590. NextOfs:=RawRecord.WriteIndexedRef(0,GroupNameIndex);
  591. for Segment in SegmentList do
  592. begin
  593. if NextOfs>High(RawRecord.RawData) then
  594. internalerror(2015040401);
  595. RawRecord.RawData[NextOfs]:=$ff;
  596. NextOfs:=RawRecord.WriteIndexedRef(NextOfs+1,Segment);
  597. end;
  598. RawRecord.RecordLength:=NextOfs+1;
  599. RawRecord.CalculateChecksumByte;
  600. end;
  601. end.