summaryrefslogtreecommitdiff
path: root/packages/base/pasjpeg/jmemdosa.pas
blob: 593d409cc3070e889bb3713ddca174495c580019 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
Unit jmemdosa;

{$G+} {enable 286/287 instructions }

{ Original: jmemdosa.asm ; Copyright (C) 1992, Thomas G. Lane.
            Based on code contributed by Ge' Weijers.  }

{ This file contains low-level interface routines to support the MS-DOS
  backing store manager (jmemdos.c).  Routines are provided to access disk
  files through direct DOS calls, and to access XMS and EMS drivers. }

interface

uses
  jmorecfg;

type
  XMSDRIVER = pointer; {far}    { actually a pointer to code }
type
  XMScontext = packed record    { registers for calling XMS driver }
    ax, dx, bx : ushort;
    ds_si : pointer; {far}
  end;
type
  EMScontext = packed record    { registers for calling EMS driver }
    ax, dx, bx : ushort;
    ds_si : pointer; {far}
  end;
{ offset is a reserved word in BASM }

function jdos_open (var handle : short {far}; const filename {: PChar}) : short;

function jdos_close (handle : short) : short;

function jdos_seek (handle : short; offs : long) : short;

function jdos_read (handle : short; buffer : pointer; {FAR}
                                count : ushort) : short;
function jdos_write (handle : short; buffer : pointer; {FAR}
                     count : ushort) : short;

procedure jxms_getdriver (var driver : XMSDRIVER);

procedure jxms_calldriver (driver : XMSDRIVER;
                           var ctx : XMScontext);
function jems_available : short;

procedure jems_calldriver (var ctx : EMScontext);


implementation


function jdos_open (var handle : short {far};
                    const filename {: PChar}) : short; assembler;
{ Create and open a temporary file }
label
  open_err;
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds
        mov     cx,0                    { normal file attributes }
        lds     dx, filename            { get filename pointer }
        mov     ah,3ch                  { create file }
        int     21h
        jc      open_err                { if failed, return error code }
        lds     bx, handle              { get handle pointer }
        mov     word ptr [bx],ax        { save the handle }
        xor     ax,ax                   { return zero for OK }
open_err:
        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jdos_open }


function jdos_close (handle : short) : short; assembler;
{ Close the file handle }
label
  close_err;
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds
        mov     bx, handle              { file handle }
        mov     ah,3eh                  { close file }
        int     21h
        jc      close_err               { if failed, return error code }
        xor     ax,ax                   { return zero for OK }
close_err:
        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jdos_close }



function jdos_seek (handle : short; offs : long) : short; assembler;
{ Set file position }
label
  seek_err;
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds
        mov     bx, handle              { file handle }
        mov     dx, offs.word           { LS offset }
        mov     cx, offs.word[2]        { MS offset }
        mov     ax,4200h                { absolute seek }
        int     21h
        jc      seek_err                { if failed, return error code }
        xor     ax,ax                   { return zero for OK }
seek_err:
        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jdos_seek }


function jdos_read (handle : short; buffer : pointer; {FAR}
                                    count : ushort) : short; assembler;
{ Read from file }
label
  read_ok, read_err;
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds
        mov     bx, handle              { file handle }
        lds     dx, buffer              { buffer address }
        mov     cx, count               { number of bytes }
        mov     ah,3fh                  { read file }
        int     21h
        jc      read_err                { if failed, return error code }
        cmp     ax, count               { make sure all bytes were read }
        je      read_ok
        mov     ax,1                    { else return 1 for not OK }
        jmp     read_err
read_ok:
        xor     ax,ax                   { return zero for OK }
read_err:
        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jdos_read }



function jdos_write (handle : short; buffer : pointer; {FAR}
                                     count : ushort) : short;  assembler;
{ Write to file }
label
  write_ok, write_err;
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds
        mov     bx, handle              { file handle }
        lds     dx, buffer              { buffer address }
        mov     cx, count               { number of bytes }
        mov     ah,40h                  { write file }
        int     21h
        jc      write_err               { if failed, return error code }
        cmp     ax, count               { make sure all bytes written }
        je      write_ok
        mov     ax,1                    { else return 1 for not OK }
        jmp     write_err
write_ok:
        xor     ax,ax                   { return zero for OK }
write_err:
        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jdos_write }



procedure jxms_getdriver (var driver : XMSDRIVER); assembler;
{ Get the address of the XMS driver, or NIL if not available }
label
  xmsavail, xmsavail_done;
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds
        mov     ax,4300h                { call multiplex interrupt with }
        int     2fh                     { a magic cookie, hex 4300 }
        cmp     al,80h                  { AL should contain hex 80 }
        je      xmsavail
        xor     dx,dx                   { no XMS driver available }
        xor     ax,ax                   { return a nil pointer }
        jmp     xmsavail_done
xmsavail:
        mov     ax,4310h                { fetch driver address with }
        int     2fh                     { another magic cookie }
        mov     dx,es                   { copy address to dx:ax }
        mov     ax,bx
xmsavail_done:
        les     bx,dword ptr [bp+6]     { get pointer to return value }
        mov     word ptr es:[bx],ax
        mov     word ptr es:[bx+2],dx
        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jxms_getdriver }

procedure jxms_calldriver (driver : XMSDRIVER;
                           var ctx : XMScontext); assembler;
{ The XMScontext structure contains values for the AX,DX,BX,SI,DS registers.}
{ These are loaded, the XMS call is performed, and the new values of the }
{ AX,DX,BX registers are written back to the context structure. }
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds
        les     bx, ctx                 { get XMScontext pointer }
        mov     ax,word ptr es:[bx]     { load registers }
        mov     dx,word ptr es:[bx+2]
        mov     si,word ptr es:[bx+6]
        mov     ds,word ptr es:[bx+8]
        mov     bx,word ptr es:[bx+4]
        call    dword ptr driver        { call the driver }
        mov     cx,bx                   { save returned BX for a sec }
        les     bx, ctx                 { get XMScontext pointer }
        mov     word ptr es:[bx],ax     { put back ax,dx,bx }
        mov     word ptr es:[bx+2],dx
        mov     word ptr es:[bx+4],cx
        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jxms_calldriver }



function jems_available : short; assembler;
{ Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)}
label
  no_ems, avail_done;
const
  ASCII_device_name : packed array[0..7] of char  = 'EMMXXXX0';
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds
        mov     ax,3567h                { get interrupt vector 67h }
        int     21h
        push    cs
        pop     ds
        mov     di,000ah                { check offs 10 in returned seg }
        lea     si, ASCII_device_name   { against literal string }
        mov     cx,8
        cld
        repe cmpsb
        jne     no_ems
        mov     ax,1                    { match, it's there }
        jmp     avail_done
no_ems: xor     ax,ax                   { it's not there }
avail_done:
        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jems_available }


procedure jems_calldriver (var ctx : EMScontext); assembler;
{ The EMScontext structure contains values for the AX,DX,BX,SI,DS registers. }
{ These are loaded, the EMS trap is performed, and the new values of the }
{ AX,DX,BX registers are written back to the context structure. }
asm
        push    si                      { save all registers for safety }
        push    di
        push    bx
        push    cx
        push    dx
        push    es
        push    ds

        les     bx, ctx                 { get EMScontext pointer }
        mov     ax, es:[bx].EMScontext.&ax      { load registers }
        mov     dx, es:[bx].EMScontext.&dx
        mov     si, es:[bx].EMScontext.&ds_si.word
        mov     ds, es:[bx].EMScontext.&ds_si.word[2]
        mov     bx, es:[bx].EMScontext.&bx
        int     67h                     { call the EMS driver }
        mov     cx,bx                   { save returned BX for a sec }
        les     bx, ctx                 { get EMScontext pointer }
        mov     es:[bx].EMScontext.&ax, ax     { put back ax,dx,bx }
        mov     es:[bx].EMScontext.&dx, dx
        mov     es:[bx].EMScontext.&bx, cx

        pop     ds                      { restore registers and exit }
        pop     es
        pop     dx
        pop     cx
        pop     bx
        pop     di
        pop     si
end; { jems_calldriver }

end.