| ; |
| ; 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 |