pmode.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. {
  2. This file is part of the Free Sockets Interface
  3. Copyright (c) 1999 by Berczi Gabor
  4. Support routines for DPMI programs
  5. See the file COPYING.FCL, 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. {$ifdef VER70}{$define TP}{$endif}
  12. unit PMode;
  13. interface
  14. uses Dos;
  15. type
  16. MemPtr = object
  17. Ofs,Seg: word;
  18. Size : word;
  19. {$ifdef DPMI}
  20. Sel : word;
  21. {$endif}
  22. function DosPtr: pointer;
  23. function DataPtr: pointer;
  24. function DosSeg: word;
  25. function DosOfs: word;
  26. procedure MoveDataTo(var Src; DSize: word);
  27. procedure MoveDataFrom(DSize: word; var Dest);
  28. procedure Clear;
  29. private
  30. function DataSeg: word;
  31. function DataOfs: word;
  32. end;
  33. PtrRec = packed record
  34. Ofs,Seg: word;
  35. end;
  36. registers32 = packed record { DPMI call structure }
  37. EDI : LongInt;
  38. ESI : LongInt;
  39. EBP : LongInt;
  40. Reserved: LongInt;
  41. EBX : LongInt;
  42. EDX : LongInt;
  43. ECX : LongInt;
  44. EAX : LongInt;
  45. Flags : Word;
  46. ES : Word;
  47. DS : Word;
  48. FS : Word;
  49. GS : Word;
  50. IP : Word;
  51. CS : Word;
  52. SP : Word;
  53. SS : Word;
  54. end;
  55. pregisters = ^registers;
  56. function GetDosMem(var M: MemPtr; Size: word): boolean;
  57. procedure FreeDosMem(var M: MemPtr);
  58. procedure realintr(IntNo: byte; var r: registers);
  59. {procedure realintr32(IntNo: byte; var r: registers32);}
  60. procedure realcall(Proc: pointer; var r: registers);
  61. function MoveDosToPM(DosPtr: pointer; PMPtr: pointer; Size: word): boolean;
  62. function MovePMToDos(PMPtr: pointer; DosPtr: pointer; Size: word): boolean;
  63. procedure realGetIntVec(IntNo: byte; var P: pointer);
  64. function allocrmcallback(PMAddr: pointer; RealRegs: pregisters): pointer;
  65. procedure freermcallback(RealCallAddr: pointer);
  66. function MakePtr(ASeg,AOfs: word): pointer;
  67. implementation
  68. {$ifdef TP}
  69. {$ifdef DPMI}uses WinAPI;{$endif}
  70. {$IFDEF DPMI}
  71. const
  72. DPMI_INTR = $31;
  73. type
  74. TDPMIRegisters = {$ifdef TP}Registers32{$else}TRegisters32{$endif};
  75. var
  76. DPMIRegs: TDPMIRegisters;
  77. {$ENDIF DPMI}
  78. procedure realintr(IntNo: byte; var r: registers);
  79. {$ifdef DPMI}
  80. var Regs: Registers;
  81. begin
  82. FillChar(DPMIRegs, SizeOf(TDPMIRegisters), 0);
  83. DPMIRegs.EAX := r.ax;
  84. DPMIRegs.EBX := r.bx;
  85. DPMIRegs.ECX := r.cx;
  86. DPMIRegs.EDX := r.dx;
  87. DPMIRegs.EDI := r.di;
  88. DPMIRegs.ESI := r.si;
  89. DPMIRegs.EBP := r.bp;
  90. DPMIRegs.DS := r.ds;
  91. DPMIRegs.ES := r.es;
  92. DPMIRegs.Flags := r.flags;
  93. Regs.AX := $0300;
  94. Regs.BL := IntNo;
  95. Regs.BH := 0;
  96. Regs.CX := 0;
  97. Regs.ES := Seg(DPMIRegs);
  98. Regs.DI := Ofs(DPMIRegs);
  99. Intr(DPMI_INTR, Regs);
  100. r.ax := DPMIRegs.EAX;
  101. r.bx := DPMIRegs.EBX;
  102. r.cx := DPMIRegs.ECX;
  103. r.dx := DPMIRegs.EDX;
  104. r.di := DPMIRegs.EDI;
  105. r.si := DPMIRegs.ESI;
  106. r.bp := DPMIRegs.EBP;
  107. r.ds := DPMIRegs.DS;
  108. r.es := DPMIRegs.ES;
  109. r.Flags := DPMIRegs.Flags;
  110. end;
  111. {$else}
  112. begin
  113. intr(IntNo,r);
  114. end;
  115. {$endif}
  116. (*procedure realintr32(IntNo: byte; var r: registers32);
  117. {$ifdef DPMI}
  118. var Regs: Registers;
  119. begin
  120. FillChar(DPMIRegs, SizeOf(TDPMIRegisters), 0);
  121. DPMIRegs:=r;
  122. Regs.AX := $0300;
  123. Regs.BL := IntNo;
  124. Regs.BH := 0;
  125. Regs.CX := 0;
  126. Regs.ES := Seg(DPMIRegs);
  127. Regs.DI := Ofs(DPMIRegs);
  128. Intr(DPMI_INTR, Regs);
  129. r:=DPMIRegs;
  130. end;
  131. {$else}
  132. begin
  133. { not implemented }
  134. Halt(99);
  135. end;
  136. {$endif}
  137. *)
  138. {$ifndef DPMI}
  139. const DummyIntRedir: boolean = false;
  140. CallAddr: pointer = nil;
  141. DummyInt = $ef;
  142. procedure CallInt; assembler;
  143. asm
  144. push ax
  145. push ds
  146. mov ax, seg CallAddr
  147. mov ds, ax
  148. mov ax, ds:CallAddr.word[0]
  149. mov cs:@JmpAddr.word[0], ax
  150. mov ax, ds:CallAddr.word[2]
  151. mov cs:@JmpAddr.word[2], ax
  152. pop ds
  153. pop ax
  154. sti
  155. db $9a
  156. @JmpAddr:
  157. dw 0,0
  158. jmp @over
  159. @regax: dw 0
  160. @over:
  161. mov word ptr cs:@regax, ax
  162. push bx
  163. pushf
  164. pop ax
  165. mov bx, sp
  166. mov word ptr ss:[bx+6], ax
  167. pop bx
  168. mov ax, word ptr cs:@regax
  169. iret
  170. end;
  171. {$endif}
  172. procedure realcall(Proc: pointer; var r: registers);
  173. {$ifdef DPMI}
  174. var Regs: Registers;
  175. begin
  176. FillChar(DPMIRegs, SizeOf(TDPMIRegisters), 0);
  177. DPMIRegs.EAX := r.ax;
  178. DPMIRegs.EBX := r.bx;
  179. DPMIRegs.ECX := r.cx;
  180. DPMIRegs.EDX := r.dx;
  181. DPMIRegs.EDI := r.di;
  182. DPMIRegs.ESI := r.si;
  183. DPMIRegs.EBP := r.bp;
  184. DPMIRegs.DS := r.ds;
  185. DPMIRegs.ES := r.es;
  186. DPMIRegs.Flags := r.flags;
  187. DPMIRegs.CS := PtrRec(Proc).Seg;
  188. DPMIRegs.IP := PtrRec(Proc).Ofs;
  189. DPMIRegs.SS :=0; DPMIRegs.SP:=0;
  190. Regs.AX := $0301;
  191. Regs.BH := 0;
  192. Regs.CX := 0;
  193. Regs.ES := Seg(DPMIRegs);
  194. Regs.DI := Ofs(DPMIRegs);
  195. Intr(DPMI_INTR, Regs);
  196. r.ax := DPMIRegs.EAX and $ffff;
  197. r.bx := DPMIRegs.EBX and $ffff;
  198. r.cx := DPMIRegs.ECX and $ffff;
  199. r.dx := DPMIRegs.EDX and $ffff;
  200. r.di := DPMIRegs.EDI and $ffff;
  201. r.si := DPMIRegs.ESI and $ffff;
  202. r.bp := DPMIRegs.EBP and $ffff;
  203. r.ds := DPMIRegs.DS;
  204. r.es := DPMIRegs.ES;
  205. r.Flags := DPMIRegs.Flags and $ffff;
  206. end;
  207. {$else}
  208. (*begin
  209. asm
  210. push ds
  211. push bp
  212. mov ax, Proc.word[2]
  213. mov bx, Proc.word[0]
  214. mov cs:@Call+1.word, bx
  215. mov cs:@Call+3.word, ax
  216. lds si, r
  217. mov @rptr.word[2], ds
  218. mov @rptr.word[0], si
  219. lodsw
  220. push ax { -> ax }
  221. lodsw
  222. mov bx, ax
  223. lodsw
  224. mov cx, ax
  225. lodsw
  226. mov dx, ax
  227. lodsw
  228. mov bp, ax
  229. lodsw
  230. push ax { -> si }
  231. lodsw
  232. mov di, ax
  233. lodsw
  234. push ax { -> ds }
  235. lodsw
  236. mov es, ax
  237. lodsw
  238. push ax { -> flags }
  239. popf
  240. pop si
  241. pop ds
  242. pop ax
  243. @Call:
  244. db 9ah
  245. dd 0
  246. jmp @skipover
  247. @rptr: dd 0
  248. @skipover:
  249. pushf
  250. push es
  251. push di
  252. mov es, @rptr.word[2]
  253. mov di, @rptr.word[0]
  254. stosw
  255. mov ax, bx
  256. stosw
  257. mov ax, cx
  258. stosw
  259. mov ax, dx
  260. stosw
  261. mov ax, bp
  262. stosw
  263. mov ax, si
  264. stosw
  265. pop ax { <- di }
  266. stosw
  267. mov ax, ds
  268. stosw
  269. pop ax { <- es }
  270. stosw
  271. pop ax { <- flags }
  272. stosw
  273. pop bp
  274. pop ds
  275. end;
  276. end;
  277. *)
  278. begin
  279. if DummyIntRedir=false then
  280. begin
  281. SetIntVec(DummyInt,@CallInt);
  282. DummyIntRedir:=true;
  283. end;
  284. CallAddr:=Proc;
  285. dos.intr(DummyInt,r);
  286. end;
  287. {$endif}
  288. (*const ActiveBlocks: word = 0;*)
  289. function GetDosMem(var M: MemPtr; Size: word): boolean;
  290. var P: pointer;
  291. L: longint;
  292. begin
  293. M.Size:=Size;
  294. {$ifndef DPMI}
  295. GetMem(P,Size);
  296. M.Seg:=PtrRec(P).Seg; M.Ofs:=PtrRec(P).Ofs;
  297. {$else}
  298. L:=GlobalDosAlloc(Size);
  299. M.Seg:=(L shr 16); M.Ofs:=0;
  300. M.Sel:=(L and $ffff);
  301. {$endif}
  302. if M.Seg<>0 then M.Clear;
  303. GetDosMem:=M.Seg<>0;
  304. (* Inc(ActiveBlocks);
  305. write('|DMC:',ActiveBlocks,'-S:',M.Sel,'-S:',M.Seg);*)
  306. end;
  307. procedure FreeDosMem(var M: MemPtr);
  308. begin
  309. if M.Size=0 then Exit;
  310. {$ifndef DPMI}
  311. if M.Seg<>0 then
  312. FreeMem(Ptr(M.Seg,M.Ofs),M.Size);
  313. {$else}
  314. if M.Sel<>0 then
  315. if GlobalDosFree(M.Sel)<>0 then
  316. writeln('!!!Failed to deallocate Dos block!!!');
  317. {$endif}
  318. FillChar(M,SizeOf(M),0);
  319. end;
  320. {$ifdef DPMI}
  321. function GetSelectorForSeg(Seg: word): word;
  322. var Sel: word;
  323. r: registers;
  324. begin
  325. r.ax:=$0002; r.bx:=Seg;
  326. intr(DPMI_Intr,r);
  327. if (r.flags and fCarry)=0 then
  328. Sel:=r.ax
  329. else
  330. Sel:=0;
  331. GetSelectorForSeg:=Sel;
  332. end;
  333. {$endif}
  334. function MoveDosToPM(DosPtr: pointer; PMPtr: pointer; Size: word): boolean;
  335. {$ifndef DPMI}
  336. begin
  337. Move(DosPtr^,PMPtr^,Size);
  338. MoveDosToPM:=true;
  339. end;
  340. {$else}
  341. var Sel: word;
  342. OK,DisposeSel: boolean;
  343. begin
  344. Sel:=GetSelectorForSeg(PtrRec(DosPtr).Seg);
  345. OK:=Sel<>0; DisposeSel:=false;
  346. if OK=false then
  347. begin
  348. Sel:=AllocSelector(0);
  349. OK:=Sel<>0;
  350. if OK then
  351. begin
  352. SetSelectorLimit(Sel,PtrRec(DosPtr).Ofs+Size);
  353. OK:=SetSelectorBase(Sel,PtrRec(DosPtr).Seg shl 4)=Sel;
  354. end;
  355. if OK then DisposeSel:=true;
  356. end;
  357. if OK then
  358. begin
  359. Move(ptr(Sel,PtrRec(DosPtr).Ofs)^,PMPtr^,Size);
  360. if DisposeSel then FreeSelector(Sel);
  361. end;
  362. MoveDosToPM:=OK;
  363. end;
  364. {$endif}
  365. function MovePMToDos(PMPtr: pointer; DosPtr: pointer; Size: word): boolean;
  366. {$ifndef DPMI}
  367. begin
  368. Move(PMPtr^,DosPtr^,Size);
  369. MovePMToDos:=true;
  370. end;
  371. {$else}
  372. var Sel: word;
  373. OK,DisposeSel: boolean;
  374. begin
  375. Sel:=GetSelectorForSeg(PtrRec(DosPtr).Seg);
  376. OK:=Sel<>0; DisposeSel:=false;
  377. if OK=false then
  378. begin
  379. Sel:=AllocSelector(0);
  380. OK:=Sel<>0;
  381. if OK then
  382. begin
  383. SetSelectorLimit(Sel,PtrRec(DosPtr).Ofs+Size);
  384. OK:=SetSelectorBase(Sel,PtrRec(DosPtr).Seg shl 4)=Sel;
  385. end;
  386. if OK then DisposeSel:=true;
  387. end;
  388. if OK then
  389. begin
  390. Move(PMPtr^,ptr(Sel,PtrRec(DosPtr).Ofs)^,Size);
  391. if DisposeSel then FreeSelector(Sel);
  392. end;
  393. MovePMToDos:=OK;
  394. end;
  395. {$endif}
  396. procedure realGetIntVec(IntNo: byte; var P: pointer);
  397. {$ifndef DPMI}
  398. begin
  399. GetIntVec(IntNo,P);
  400. end;
  401. {$else}
  402. var r: registers;
  403. begin
  404. r.ax:=$200; r.bl:=IntNo;
  405. intr(DPMI_Intr,r);
  406. P:=Ptr(r.cx,r.dx);
  407. end;
  408. {$endif}
  409. procedure MemPtr.MoveDataTo(const Src; DSize: word);
  410. begin
  411. if DSize>Size then
  412. RunError(216);
  413. Move(Src,Ptr(DataSeg,DataOfs)^,DSize);
  414. end;
  415. procedure MemPtr.MoveDataFrom(DSize: word; var Dest);
  416. begin
  417. if DSize>Size then
  418. RunError(216);
  419. Move(Ptr(DataSeg,DataOfs)^,Dest,DSize);
  420. end;
  421. procedure MemPtr.Clear;
  422. begin
  423. FillChar(Ptr(DataSeg,DataOfs)^,Size,0);
  424. end;
  425. procedure RealAbstract;
  426. begin
  427. writeln('Abstract call in real mode...');
  428. RunError(255);
  429. end;
  430. function allocrmcallback(PMAddr: pointer; RealRegs: pregisters): pointer;
  431. {$ifdef DPMI}
  432. var r: registers;
  433. P: pointer;
  434. begin
  435. r.ax:=$0303;
  436. r.ds:=PtrRec(PMAddr).Seg; r.si:=PtrRec(PMAddr).Ofs;
  437. r.es:=PtrRec(RealRegs).Seg; r.di:=PtrRec(RealRegs).Ofs;
  438. intr(DPMI_Intr,r);
  439. if (r.flags and fCarry)=0 then
  440. P:=MakePtr(r.cx,r.dx)
  441. else
  442. P:=nil;
  443. allocrmcallback:=P;
  444. end;
  445. {$else}
  446. begin
  447. RealAbstract;
  448. end;
  449. {$endif}
  450. procedure freermcallback(RealCallAddr: pointer);
  451. {$ifdef DPMI}
  452. var r: registers;
  453. begin
  454. r.ax:=$0304;
  455. r.cx:=PtrRec(RealCallAddr).Seg; r.dx:=PtrRec(RealCallAddr).Seg;
  456. intr(DPMI_Intr,r);
  457. end;
  458. {$else}
  459. begin
  460. RealAbstract;
  461. end;
  462. {$endif}
  463. {$endif TP}
  464. {$ifdef GO32V2}
  465. { --------------------- GO32 --------------------- }
  466. uses go32;
  467. function GetDosMem(var M: MemPtr; Size: word): boolean;
  468. var L: longint;
  469. begin
  470. M.Size:=Size;
  471. L:=global_dos_alloc(Size);
  472. M.Seg:=(L shr 16); M.Ofs:=0;
  473. M.Sel:=(L and $ffff);
  474. GetDosMem:=M.Seg<>0;
  475. end;
  476. procedure FreeDosMem(var M: MemPtr);
  477. begin
  478. if M.Size=0 then Exit;
  479. if M.Sel<>0 then
  480. if global_dos_free(M.Sel)=false then
  481. writeln('!!!Failed to deallocate Dos block!!!');
  482. FillChar(M,SizeOf(M),0);
  483. end;
  484. procedure realintr(IntNo: byte; var r: registers);
  485. var rr: trealregs;
  486. begin
  487. rr.realeax:=r.ax;
  488. rr.realebx:=r.bx;
  489. rr.realecx:=r.cx;
  490. rr.realedx:=r.dx;
  491. rr.realesi:=r.si;
  492. rr.realedi:=r.di;
  493. rr.reales:=r.es;
  494. rr.realds:=r.ds;
  495. go32.realintr(IntNo,rr);
  496. r.ax:=rr.realeax and $ffff;
  497. r.bx:=rr.realebx and $ffff;
  498. r.cx:=rr.realecx and $ffff;
  499. r.dx:=rr.realedx and $ffff;
  500. r.si:=rr.realesi and $ffff;
  501. r.di:=rr.realedi and $ffff;
  502. r.es:=rr.reales and $ffff;
  503. r.ds:=rr.realds and $ffff;
  504. end;
  505. function dorealcall(var regs : trealregs) : boolean;
  506. begin
  507. regs.realsp:=0;
  508. regs.realss:=0;
  509. asm
  510. movw $0x0,%bx
  511. xorl %ecx,%ecx
  512. movl regs,%edi
  513. { es is always equal ds }
  514. movl $0x301,%eax
  515. int $0x31
  516. setnc %al
  517. movb %al,__RESULT
  518. end;
  519. end;
  520. procedure realcall(Proc: pointer; var r: registers);
  521. var rr: trealregs;
  522. begin
  523. rr.realeax:=r.ax;
  524. rr.realebx:=r.bx;
  525. rr.realecx:=r.cx;
  526. rr.realedx:=r.dx;
  527. rr.realesi:=r.si;
  528. rr.realedi:=r.di;
  529. rr.reales:=r.es;
  530. rr.realds:=r.ds;
  531. rr.flags:=r.flags;
  532. rr.CS:=PtrRec(Proc).Seg;
  533. rr.IP:=PtrRec(Proc).Ofs;
  534. rr.realss:=0; rr.realsp:=0;
  535. dorealcall(rr);
  536. r.ax:=rr.realeax and $ffff;
  537. r.bx:=rr.realebx and $ffff;
  538. r.cx:=rr.realecx and $ffff;
  539. r.dx:=rr.realedx and $ffff;
  540. r.si:=rr.realesi and $ffff;
  541. r.di:=rr.realedi and $ffff;
  542. r.es:=rr.reales and $ffff;
  543. r.ds:=rr.realds and $ffff;
  544. r.flags:=rr.Flags and $ffff;
  545. end;
  546. function MoveDosToPM(DosPtr: pointer; PMPtr: pointer; Size: word): boolean;
  547. begin
  548. dosmemget(PtrRec(DosPtr).Seg,PtrRec(DosPtr).Ofs,PMPtr^,Size);
  549. MoveDosToPM:=true;
  550. end;
  551. function MovePMToDos(PMPtr, DosPtr: pointer; Size: word): boolean;
  552. begin
  553. dosmemput(PtrRec(DosPtr).Seg,PtrRec(DosPtr).Ofs,PMPtr^,Size);
  554. MovePMToDos:=true;
  555. end;
  556. procedure realGetIntVec(IntNo: byte; var P: pointer);
  557. var si: tseginfo;
  558. begin
  559. get_rm_interrupt(IntNo,si);
  560. PtrRec(P).Seg:=si.segment; PtrRec(P).Ofs:=longint(si.offset);
  561. end;
  562. procedure MemPtr.MoveDataTo(var Src; DSize: word);
  563. begin
  564. dpmi_dosmemput(DosSeg,DosOfs,Src,DSize);
  565. end;
  566. procedure MemPtr.MoveDataFrom(DSize: word; var Dest);
  567. begin
  568. dpmi_dosmemget(DosSeg,DosOfs,Dest,DSize);
  569. end;
  570. procedure MemPtr.Clear;
  571. begin
  572. dpmi_dosmemfillchar(DosSeg,DosOfs,Size,#0);
  573. end;
  574. function allocrmcallback(PMAddr: pointer; RealRegs: pregisters): pointer;
  575. var s: tseginfo;
  576. P: pointer;
  577. begin
  578. if get_rm_callback(PMAddr,RealRegs^,s) then
  579. P:=MakePtr(s.segment,longint(s.offset))
  580. else
  581. P:=nil;
  582. allocrmcallback:=P;
  583. end;
  584. procedure freermcallback(RealCallAddr: pointer);
  585. var s: tseginfo;
  586. begin
  587. s.segment:=PtrRec(RealCallAddr).seg;
  588. s.offset:=pointer(longint(PtrRec(RealCallAddr).ofs));
  589. free_rm_callback(s);
  590. end;
  591. {$endif GO32V2}
  592. { ---------------------- COMMON ---------------------- }
  593. function MemPtr.DosPtr: pointer;
  594. begin
  595. DosPtr:=MakePtr(Seg,Ofs);
  596. end;
  597. function MemPtr.DataPtr: pointer;
  598. begin
  599. DataPtr:=MakePtr(DataSeg,DataOfs);
  600. end;
  601. function MemPtr.DataSeg: word;
  602. begin
  603. {$ifndef DPMI}
  604. DataSeg:=Seg;
  605. {$else}
  606. DataSeg:=Sel;
  607. {$endif}
  608. end;
  609. function MemPtr.DataOfs: word;
  610. begin
  611. {$ifndef DPMI}
  612. DataOfs:=Ofs;
  613. {$else}
  614. DataOfs:=0;
  615. {$endif}
  616. end;
  617. function MemPtr.DosSeg: word;
  618. begin
  619. DosSeg:=Seg;
  620. end;
  621. function MemPtr.DosOfs: word;
  622. begin
  623. DosOfs:=Ofs;
  624. end;
  625. function MakePtr(ASeg, AOfs: word): pointer;
  626. var P: pointer;
  627. begin
  628. with PtrRec(P) do
  629. begin
  630. Seg:=ASeg; Ofs:=AOfs;
  631. end;
  632. MakePtr:=P;
  633. end;
  634. END.