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