1;
2; jmemdosa.asm
3;
4; Copyright (C) 1992, Thomas G. Lane.
5; This file is part of the Independent JPEG Group's software.
6; For conditions of distribution and use, see the accompanying README file.
7;
8; This file contains low-level interface routines to support the MS-DOS
9; backing store manager (jmemdos.c).  Routines are provided to access disk
10; files through direct DOS calls, and to access XMS and EMS drivers.
11;
12; This file should assemble with Microsoft's MASM or any compatible
13; assembler (including Borland's Turbo Assembler).  If you haven't got
14; a compatible assembler, better fall back to jmemansi.c or jmemname.c.
15;
16; To minimize dependence on the C compiler's register usage conventions,
17; we save and restore all 8086 registers, even though most compilers only
18; require SI,DI,DS to be preserved.  Also, we use only 16-bit-wide return
19; values, which everybody returns in AX.
20;
21; Based on code contributed by Ge' Weijers.
22;
23
24JMEMDOSA_TXT	segment byte public 'CODE'
25
26		assume	cs:JMEMDOSA_TXT
27
28		public	_jdos_open
29		public	_jdos_close
30		public	_jdos_seek
31		public	_jdos_read
32		public	_jdos_write
33		public	_jxms_getdriver
34		public	_jxms_calldriver
35		public	_jems_available
36		public	_jems_calldriver
37
38;
39; short far jdos_open (short far * handle, char far * filename)
40;
41; Create and open a temporary file
42;
43_jdos_open	proc	far
44		push	bp			; linkage
45		mov 	bp,sp
46		push	si			; save all registers for safety
47		push	di
48		push	bx
49		push	cx
50		push	dx
51		push	es
52		push	ds
53		mov	cx,0			; normal file attributes
54		lds	dx,dword ptr [bp+10]	; get filename pointer
55		mov	ah,3ch			; create file
56		int	21h
57		jc	open_err		; if failed, return error code
58		lds	bx,dword ptr [bp+6]	; get handle pointer
59		mov	word ptr [bx],ax	; save the handle
60		xor	ax,ax			; return zero for OK
61open_err:	pop	ds			; restore registers and exit
62		pop	es
63		pop	dx
64		pop	cx
65		pop	bx
66		pop	di
67		pop	si
68		pop 	bp
69		ret
70_jdos_open	endp
71
72
73;
74; short far jdos_close (short handle)
75;
76; Close the file handle
77;
78_jdos_close	proc	far
79		push	bp			; linkage
80		mov 	bp,sp
81		push	si			; save all registers for safety
82		push	di
83		push	bx
84		push	cx
85		push	dx
86		push	es
87		push	ds
88		mov	bx,word ptr [bp+6]	; file handle
89		mov	ah,3eh			; close file
90		int	21h
91		jc	close_err		; if failed, return error code
92		xor	ax,ax			; return zero for OK
93close_err:	pop	ds			; restore registers and exit
94		pop	es
95		pop	dx
96		pop	cx
97		pop	bx
98		pop	di
99		pop	si
100		pop 	bp
101		ret
102_jdos_close	endp
103
104
105;
106; short far jdos_seek (short handle, long offset)
107;
108; Set file position
109;
110_jdos_seek	proc	far
111		push	bp			; linkage
112		mov 	bp,sp
113		push	si			; save all registers for safety
114		push	di
115		push	bx
116		push	cx
117		push	dx
118		push	es
119		push	ds
120		mov	bx,word ptr [bp+6]	; file handle
121		mov	dx,word ptr [bp+8]	; LS offset
122		mov	cx,word ptr [bp+10]	; MS offset
123		mov	ax,4200h		; absolute seek
124		int	21h
125		jc	seek_err		; if failed, return error code
126		xor	ax,ax			; return zero for OK
127seek_err:	pop	ds			; restore registers and exit
128		pop	es
129		pop	dx
130		pop	cx
131		pop	bx
132		pop	di
133		pop	si
134		pop 	bp
135		ret
136_jdos_seek	endp
137
138
139;
140; short far jdos_read (short handle, void far * buffer, unsigned short count)
141;
142; Read from file
143;
144_jdos_read	proc	far
145		push	bp			; linkage
146		mov 	bp,sp
147		push	si			; save all registers for safety
148		push	di
149		push	bx
150		push	cx
151		push	dx
152		push	es
153		push	ds
154		mov	bx,word ptr [bp+6]	; file handle
155		lds	dx,dword ptr [bp+8]	; buffer address
156		mov	cx,word ptr [bp+12]	; number of bytes
157		mov	ah,3fh			; read file
158		int	21h
159		jc	read_err		; if failed, return error code
160		cmp	ax,word ptr [bp+12]	; make sure all bytes were read
161		je	read_ok
162		mov	ax,1			; else return 1 for not OK
163		jmp	short read_err
164read_ok:	xor	ax,ax			; return zero for OK
165read_err:	pop	ds			; restore registers and exit
166		pop	es
167		pop	dx
168		pop	cx
169		pop	bx
170		pop	di
171		pop	si
172		pop 	bp
173		ret
174_jdos_read	endp
175
176
177;
178; short far jdos_write (short handle, void far * buffer, unsigned short count)
179;
180; Write to file
181;
182_jdos_write	proc	far
183		push	bp			; linkage
184		mov 	bp,sp
185		push	si			; save all registers for safety
186		push	di
187		push	bx
188		push	cx
189		push	dx
190		push	es
191		push	ds
192		mov	bx,word ptr [bp+6]	; file handle
193		lds	dx,dword ptr [bp+8]	; buffer address
194		mov	cx,word ptr [bp+12]	; number of bytes
195		mov	ah,40h			; write file
196		int	21h
197		jc	write_err		; if failed, return error code
198		cmp	ax,word ptr [bp+12]	; make sure all bytes written
199		je	write_ok
200		mov	ax,1			; else return 1 for not OK
201		jmp	short write_err
202write_ok:	xor	ax,ax			; return zero for OK
203write_err:	pop	ds			; restore registers and exit
204		pop	es
205		pop	dx
206		pop	cx
207		pop	bx
208		pop	di
209		pop	si
210		pop 	bp
211		ret
212_jdos_write	endp
213
214
215;
216; void far jxms_getdriver (XMSDRIVER far *)
217;
218; Get the address of the XMS driver, or NULL if not available
219;
220_jxms_getdriver	proc	far
221		push	bp			; linkage
222		mov 	bp,sp
223		push	si			; save all registers for safety
224		push	di
225		push	bx
226		push	cx
227		push	dx
228		push	es
229		push	ds
230		mov 	ax,4300h		; call multiplex interrupt with
231		int	2fh			; a magic cookie, hex 4300
232		cmp 	al,80h			; AL should contain hex 80
233		je	xmsavail
234		xor 	dx,dx			; no XMS driver available
235		xor 	ax,ax			; return a nil pointer
236		jmp	short xmsavail_done
237xmsavail:	mov 	ax,4310h		; fetch driver address with
238		int	2fh			; another magic cookie
239		mov 	dx,es			; copy address to dx:ax
240		mov 	ax,bx
241xmsavail_done:	les 	bx,dword ptr [bp+6]	; get pointer to return value
242		mov	word ptr es:[bx],ax
243		mov	word ptr es:[bx+2],dx
244		pop	ds			; restore registers and exit
245		pop	es
246		pop	dx
247		pop	cx
248		pop	bx
249		pop	di
250		pop	si
251		pop	bp
252		ret
253_jxms_getdriver	endp
254
255
256;
257; void far jxms_calldriver (XMSDRIVER, XMScontext far *)
258;
259; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers.
260; These are loaded, the XMS call is performed, and the new values of the
261; AX,DX,BX registers are written back to the context structure.
262;
263_jxms_calldriver 	proc	far
264		push	bp			; linkage
265		mov 	bp,sp
266		push	si			; save all registers for safety
267		push	di
268		push	bx
269		push	cx
270		push	dx
271		push	es
272		push	ds
273		les 	bx,dword ptr [bp+10]	; get XMScontext pointer
274		mov 	ax,word ptr es:[bx]	; load registers
275		mov 	dx,word ptr es:[bx+2]
276		mov 	si,word ptr es:[bx+6]
277		mov 	ds,word ptr es:[bx+8]
278		mov 	bx,word ptr es:[bx+4]
279		call	dword ptr [bp+6]	; call the driver
280		mov	cx,bx			; save returned BX for a sec
281		les 	bx,dword ptr [bp+10]	; get XMScontext pointer
282		mov 	word ptr es:[bx],ax	; put back ax,dx,bx
283		mov 	word ptr es:[bx+2],dx
284		mov 	word ptr es:[bx+4],cx
285		pop	ds			; restore registers and exit
286		pop	es
287		pop	dx
288		pop	cx
289		pop	bx
290		pop	di
291		pop	si
292		pop 	bp
293		ret
294_jxms_calldriver 	endp
295
296
297;
298; short far jems_available (void)
299;
300; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)
301;
302_jems_available	proc	far
303		push	si			; save all registers for safety
304		push	di
305		push	bx
306		push	cx
307		push	dx
308		push	es
309		push	ds
310		mov	ax,3567h		; get interrupt vector 67h
311		int	21h
312		push	cs
313		pop	ds
314		mov	di,000ah		; check offs 10 in returned seg
315		lea	si,ASCII_device_name	; against literal string
316		mov	cx,8
317		cld
318		repe cmpsb
319		jne	no_ems
320		mov	ax,1			; match, it's there
321		jmp	short avail_done
322no_ems:		xor	ax,ax			; it's not there
323avail_done:	pop	ds			; restore registers and exit
324		pop	es
325		pop	dx
326		pop	cx
327		pop	bx
328		pop	di
329		pop	si
330		ret
331
332ASCII_device_name	db	"EMMXXXX0"
333
334_jems_available	endp
335
336
337;
338; void far jems_calldriver (EMScontext far *)
339;
340; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers.
341; These are loaded, the EMS trap is performed, and the new values of the
342; AX,DX,BX registers are written back to the context structure.
343;
344_jems_calldriver	proc far
345		push	bp			; linkage
346		mov 	bp,sp
347		push	si			; save all registers for safety
348		push	di
349		push	bx
350		push	cx
351		push	dx
352		push	es
353		push	ds
354		les 	bx,dword ptr [bp+6]	; get EMScontext pointer
355		mov 	ax,word ptr es:[bx]	; load registers
356		mov 	dx,word ptr es:[bx+2]
357		mov 	si,word ptr es:[bx+6]
358		mov 	ds,word ptr es:[bx+8]
359		mov 	bx,word ptr es:[bx+4]
360		int	67h			; call the EMS driver
361		mov	cx,bx			; save returned BX for a sec
362		les 	bx,dword ptr [bp+6]	; get EMScontext pointer
363		mov 	word ptr es:[bx],ax	; put back ax,dx,bx
364		mov 	word ptr es:[bx+2],dx
365		mov 	word ptr es:[bx+4],cx
366		pop	ds			; restore registers and exit
367		pop	es
368		pop	dx
369		pop	cx
370		pop	bx
371		pop	di
372		pop	si
373		pop 	bp
374		ret
375_jems_calldriver	endp
376
377JMEMDOSA_TXT	ends
378
379		end
380