; ; jmemdosa.asm ; ; Copyright (C) 1992, Thomas G. Lane. ; This file is part of the Independent JPEG Group's software. ; For conditions of distribution and use, see the accompanying README file. ; ; 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. ; ; This file should assemble with Microsoft's MASM or any compatible ; assembler (including Borland's Turbo Assembler). If you haven't got ; a compatible assembler, better fall back to jmemansi.c or jmemname.c. ; ; To minimize dependence on the C compiler's register usage conventions, ; we save and restore all 8086 registers, even though most compilers only ; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return ; values, which everybody returns in AX. ; ; Based on code contributed by Ge' Weijers. ; JMEMDOSA_TXT segment byte public 'CODE' assume cs:JMEMDOSA_TXT public _jdos_open public _jdos_close public _jdos_seek public _jdos_read public _jdos_write public _jxms_getdriver public _jxms_calldriver public _jems_available public _jems_calldriver ; ; short far jdos_open (short far * handle, char far * filename) ; ; Create and open a temporary file ; _jdos_open proc far push bp ; linkage mov bp,sp 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,dword ptr [bp+10] ; get filename pointer mov ah,3ch ; create file int 21h jc open_err ; if failed, return error code lds bx,dword ptr [bp+6] ; 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 pop bp ret _jdos_open endp ; ; short far jdos_close (short handle) ; ; Close the file handle ; _jdos_close proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; 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 pop bp ret _jdos_close endp ; ; short far jdos_seek (short handle, long offset) ; ; Set file position ; _jdos_seek proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle mov dx,word ptr [bp+8] ; LS offset mov cx,word ptr [bp+10] ; 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 pop bp ret _jdos_seek endp ; ; short far jdos_read (short handle, void far * buffer, unsigned short count) ; ; Read from file ; _jdos_read proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle lds dx,dword ptr [bp+8] ; buffer address mov cx,word ptr [bp+12] ; number of bytes mov ah,3fh ; read file int 21h jc read_err ; if failed, return error code cmp ax,word ptr [bp+12] ; make sure all bytes were read je read_ok mov ax,1 ; else return 1 for not OK jmp short 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 pop bp ret _jdos_read endp ; ; short far jdos_write (short handle, void far * buffer, unsigned short count) ; ; Write to file ; _jdos_write proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle lds dx,dword ptr [bp+8] ; buffer address mov cx,word ptr [bp+12] ; number of bytes mov ah,40h ; write file int 21h jc write_err ; if failed, return error code cmp ax,word ptr [bp+12] ; make sure all bytes written je write_ok mov ax,1 ; else return 1 for not OK jmp short 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 pop bp ret _jdos_write endp ; ; void far jxms_getdriver (XMSDRIVER far *) ; ; Get the address of the XMS driver, or NULL if not available ; _jxms_getdriver proc far push bp ; linkage mov bp,sp 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 short 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 pop bp ret _jxms_getdriver endp ; ; void far jxms_calldriver (XMSDRIVER, XMScontext far *) ; ; 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. ; _jxms_calldriver proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds les bx,dword ptr [bp+10] ; 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 [bp+6] ; call the driver mov cx,bx ; save returned BX for a sec les bx,dword ptr [bp+10] ; 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 pop bp ret _jxms_calldriver endp ; ; short far jems_available (void) ; ; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs) ; _jems_available proc far 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 short 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 ret ASCII_device_name db "EMMXXXX0" _jems_available endp ; ; void far jems_calldriver (EMScontext far *) ; ; 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. ; _jems_calldriver proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds les bx,dword ptr [bp+6] ; get EMScontext 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] int 67h ; call the EMS driver mov cx,bx ; save returned BX for a sec les bx,dword ptr [bp+6] ; get EMScontext 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 pop bp ret _jems_calldriver endp JMEMDOSA_TXT ends end