;------------------------------------------------ ; ems.asm ; ; Copyright (c) 1989-93 by c.mos ;------------------------------------------------ include vz.inc ;----- Equations ----- ;BMP: Bit Mapped Pages ;XMEM: eXtended MEMory (EMS,XMS,TMP) EOALLOC equ -1 HALF_PAGE equ 2 MAX_PAGE equ 4 EM_INIT equ 40h EM_FRAME equ 41h EM_PAGELEFT equ 42h EM_ALLOC equ 43h EM_MAP equ 44h EM_FREE equ 45h EM_SAVE equ 47h EM_RESTORE equ 48h EM_REALLOC equ 51h XM_EMBSIZE equ 08h XM_EMBALLOC equ 09h XM_EMBFREE equ 0Ah XM_EMBMOVE equ 0Bh XM_EMBREALLOC equ 0Fh RM_EMS equ 1 RM_XMS equ 2 ;----- BMP work ----- ; BMP handle: ; b0..b9=entry(0..1023), b10,b11=page count _bmprec struc bm_base dw ? bm_offset dw ? bm_max dw ? bm_w1 dw ? _bmprec ends _embrec struc emb_size dw ? dw ? emb_src_h dw ? emb_src_off dd ? emb_dst_h dw ? emb_dst_off dd ? _embrec ends ;----- XMS function call ----- xmm macro cmd mov ah,cmd call cs:xmsfunc endm ;----- External symbols ----- wseg extrn nm_vz :byte extrn invz :byte extrn reallocf :byte extrn emsfree :word extrn emspages :word extrn xmssize :word extrn save_ds :word extrn retval :word endws extrn tmppath :near extrn memmove :near wseg ;----- Local work ----- GDATA frame, dw, 0 ; ##152.22 ;GDATA mappages,dw, 0 ; ##153.58 r_ems _bmprec <> r_xms _bmprec <> r_tmp _bmprec <> pmap dw MAX_PAGE dup(0) ; Page map table pmap_bak dw MAX_PAGE dup(0) embwork _embrec <> truncf dw 0 endws bseg h_ems dw 0 h_xms dw 0 h_tmp dw 0 xmsfunc _farptr <> bmptbl db BMPSIZE dup(0) ; EMS/XMS free bit field table endbs iseg assume ds:cgroup ;----- Open EMS ----- ;<-- ; AX :EMS page count ; CY :EMS not ready emsid db 'EMMXXXX0' public ems_open ems_open proc push es tstw emspages jz eopen_x msdos F_GETVCT,INT_EMS mov si,offset cgroup:emsid push ds movseg ds,cs mov di,000Ah mov cx,8 repe cmpsb pop ds jnz eopen_x emm EM_INIT tst ah jnz eopen_x emm EM_PAGELEFT cmp bx,4 ; ##156.130 jb eopen_x mov ax,emspages cmp ax,1 je eopen1 cmp ax,PAGEMAX _if a eopen1: mov ax,PAGEMAX _endif cmp ax,bx _if b mov bx,ax _endif emm EM_ALLOC tst ah jnz eopen_x tst bx jz eopen_x mov emspages,bx mov emsfree,bx push bx emm EM_FRAME mov frame,bx mov cs:h_ems,dx mov si,offset cgroup:nm_vz mov ax,5301h ; set EMS handle name int INT_EMS pop ax clc jmps eopen9 eopen_x: stc eopen9: pop es VZ_RET ems_open endp ;----- Open XMS ----- ;<-- ; AX :XMS size ; CY :XMS not ready public xms_open xms_open proc push es tstw xmssize jz xopen_x msdos F_VERSION cmp al,3 jb xopen_x mov ax,4300h int 2Fh cmp al,80h jne xopen_x mov ax,4310h int 2Fh mov cs:xmsfunc.@off,bx mov cs:xmsfunc.@seg,es clr dx xmm XM_EMBSIZE tst dx jz xopen_x mov cx,PAGEMAX call ems_check _ifn z mov dx,emspages add dx,7 and dx,not 7 sub cx,dx _endif shlm cx,4 mov dx,xmssize cmp dx,1 je xopen1 cmp dx,cx _if a xopen1: mov dx,cx _endif cmp ax,dx _if b mov dx,ax _endif and dx,0FFF0h jz xopen_x mov xmssize,dx xmm XM_EMBALLOC tst ax jz xopen_x mov cs:h_xms,dx mov ax,xmssize clc jmps xopen9 xopen_x: stc xopen9: pop es VZ_RET xms_open endp endis eseg ;----- Close XMEM handles ----- ;--> DS: terget segment public xmem_close xmem_close proc mov dx,h_ems tst dx _ifn z emm EM_FREE _endif mov dx,h_xms tst dx _ifn z mov ah,XM_EMBFREE call xmsfunc _endif tstw h_tmp _ifn z mov dx,offset cgroup:tmppath msdos F_DELETE _endif VZ_RET xmem_close endp ;----- Allocate EMS pages ----- ;--> ; AL :page count ; AX :size (ems_salloc) ;<-- ; NC,AX :BMP handle ; CY,AX :EMS not ready (AX=0), ; or not enough page (AX:max. page count) public ems_alloc, ems_salloc ems_salloc proc call size2pc ems_alloc: pushm movseg ds,ss mov cl,al clr ch call ems_alloc1 popm ealc9: VZ_RET ems_alloc1 proc call ems_check mov ax,0 stc _ifn z mov si,offset cgroup:r_ems call bmp_alloc _ifn c sub emsfree,cx clc _endif _endif VZ_RET ems_alloc1 endp ems_salloc endp size2pc proc tst ax _if z inc sp inc sp VZ_RET _endif dec ax rolm ax,2 and ax,3 inc ax VZ_RET size2pc endp ;----- Allocate XMEM pages ----- ;--> AX :size ;<-- AX :BMP handle public xmem_alloc xmem_alloc proc call size2pc pushm movseg ds,ss tstw truncf _ifn z push ax call xmem_extend pop ax _endif mov cx,ax call xms_check _ifn z mov si,offset cgroup:r_xms call bmp_alloc jnc xmalc8 _endif call ems_alloc1 _if c mov si,offset cgroup:r_tmp call bmp_alloc _endif xmalc8: popm VZ_RET xmem_alloc endp ;----- Free XMEM pages ----- ;--> ; AX :BMP handle public xmem_free xmem_free proc tst ax _ifn z pushm movseg ds,ss call ishandle call bmp_free cmp si,offset cgroup:r_ems _if e add emsfree,cx _endif popm _endif VZ_RET xmem_free endp ;----- &Ea &Em macro ----- public ex_emsalloc ex_emsalloc proc call ems_alloc jmps exmap9 ex_emsalloc endp public ex_emsmap ex_emsmap proc tst dx _if z call ems_map _else call ems_map2 _endif exmap9: mov retval,ax VZ_RET ex_emsmap endp endes bseg ;----- Save/Restore EMS ----- public ems_save,ems_restore ems_save proc call get_h_ems _ifn z tstb cs:invz ; ##153.49 _if z emm EM_SAVE _endif _endif VZ_RET ems_save endp ems_restore proc call get_h_ems _ifn z tstb cs:invz ; ##153.49 _if z emm EM_RESTORE _endif _endif VZ_RET ems_restore endp ;----- Get handle ----- get_h_ems proc mov dx,cs:h_ems tst dx VZ_RET get_h_ems endp get_h_tmp proc mov bx,cs:h_tmp tst bx VZ_RET get_h_tmp endp ;----- Map EMS pages ----- ;--> ; AX :BMP handle(0xxxh) or segment ;<-- ; ZR :no pages ; AX :entry segment ems_premap: call ems_savemap push ax mov ax,es cmp ax,frame pop ax je ems_map2 public ems_map,ems_map2 ems_map proc push dx clr dx jmps emap0 ems_map2: push dx mov dx,HALF_PAGE emap0: test ah,EMSMASK jnz emap9 pushm mov ds,cs:save_ds mov di,offset cgroup:pmap add di,dx add di,dx ;; push dx call bmp_unpack _repeat tstb cs:invz ; ##153.49 jz emap1 cmp [di],ax je emap2 mov [di],ax emap1: pushm mov bx,ax dec bx mov al,dl call get_h_ems emm EM_MAP tst ah popm _break nz emap2: inc dx cmp dl,MAX_PAGE _break e inc di inc di inc ax _loop pop ax push cx mov cl,10 shl ax,cl add ax,frame pop cx tst cx popm emap9: pop dx VZ_RET ems_map endp ;----- Reset EMS page map ----- public ems_resetmap ems_resetmap proc pushm mov es,cs:save_ds mov cx,MAX_PAGE * 2 mov di,offset cgroup:pmap clr ax rep stosw popm VZ_RET ems_resetmap endp ;----- Check EMS/XMS ----- ;<-- ZR :EMS not ready public ems_check ems_check proc tstw cs:h_ems VZ_RET ems_check endp public xms_check xms_check proc tstw cs:h_xms VZ_RET xms_check endp ;----- Save map ----- public ems_savemap ems_savemap proc pushm mov ds,cs:save_ds mov cx,MAX_PAGE mov si,offset cgroup:pmap _repeat lodsw mov [si+MAX_PAGE*2-2],ax _loop popm VZ_RET ems_savemap endp ;----- Load map ----- public ems_loadmap ems_loadmap proc pushm mov ds,cs:save_ds call get_h_ems _ifn z clr al mov si,offset cgroup:pmap _repeat mov bx,[si+MAX_PAGE*2] tst bx _break z cmp bx,[si] _ifn e mov [si],bx push ax dec bx emm EM_MAP pop ax _endif inc si inc si inc al cmp al,MAX_PAGE _until e _endif popm VZ_RET ems_loadmap endp endbs eseg ;----- Truncate/Extend XMEM resources ----- public xmem_trunc, xmem_extend xmem_trunc proc mov di,TRUE skip2 xmem_extend: clr di push ds movseg ds,ss cmp di,truncf je trunc8 mov truncf,di test reallocf,RM_EMS _if z call ems_check _ifn z mov si,offset cgroup:r_ems call bmp_trunc mov bx,ax call get_h_ems _repeat emm EM_REALLOC tst ah _break z dec bx mov [si].bm_max,bx _until z _endif _endif test reallocf,RM_XMS _if z call xms_check _ifn z mov si,offset cgroup:r_xms call bmp_trunc _repeat push ax mov cl,4 shl ax,cl mov bx,ax mov dx,cs:h_xms xmm XM_EMBREALLOC tst ax pop ax _break nz dec ax mov [si].bm_max,ax _until z _endif _endif call get_h_tmp _ifn z tst di _ifn z mov si,offset cgroup:r_tmp call bmp_trunc inc ax clr cx call tmp_write _endif _endif trunc8: call tmp_close pop ds VZ_RET xmem_trunc endp ;------------------------------------------------ ; BMP manager ;------------------------------------------------ ; ;----- Allocate BMP pages ----- ;--> ; SI :BMP work ptr ; CX :request page count (1..4) ;<-- ; NC,AX :BMP handle ; CY,AX :not enough page (AX:max. page count) bmp_alloc proc pushm mov bx,[si].bm_offset clr dx ; page number clr ah mov [si].bm_w1,dx ; max. pages bmaloc1: clr di ; page count _repeat call scanbmp _until z _repeat inc di cmp di,cx je bmaloc2 call scanbmp _while z cmp di,[si].bm_w1 _if a mov [si].bm_w1,di _endif jmp bmaloc1 bmaloc2: mov ax,dx sub ax,cx inc ax dec cx shlm cl,2 or ah,cl call bmp_set add ax,[si].bm_base clc jmps bmaloc9 scanbmp: inc dx cmp dx,[si].bm_max ja scanend shl ah,1 _if z mov al,cs:[bx] inc bx mov ah,1 _endif test al,ah scbmp9: VZ_RET scanend: tst di jnz scbmp9 add sp,2 mov ax,[si].bm_w1 stc bmaloc9: popm VZ_RET bmp_alloc endp ;----- Truncate BMP ----- ;--> ; SI :BMP work ptr ; DI :trunc=TRUE, extend=FALSE ;<-- ; AX :page count bmp_trunc proc mov ax,[si].bm_max tst di jz bmptr9 mov bx,[si].bm_offset tst ax jz bmptr9 dec ax mov dx,ax and dx,not 7 add dx,8 shrm ax,3 add bx,ax _repeat mov al,cs:[bx] dec bx tst al _if z sub dx,8 jmps bmptr7 _endif mov cx,8 _repeat shl al,1 jc bmptr8 dec dx _loop bmptr7: tst dx _until z bmptr8: mov ax,dx bmptr9: VZ_RET bmp_trunc endp endes bseg ;----- Free BMP pages ----- ;--> ; SI :BMP work ptr ; AX :BMP handle ;<-- ; CX :free page count bmp_free proc mov dl,FALSE skip2 bmp_set: mov dl,TRUE pushm call bmp_unpack dec ax push cx mov cx,ax and cl,7 shrm ax,3 mov bx,[si].bm_offset add bx,ax mov al,1 shl al,cl pop cx push cx _repeat tst dl _if z not al and cs:[bx],al not al _else or cs:[bx],al _endif rol al,1 cmp al,1 _if e inc bx _endif _loop pop cx popm VZ_RET bmp_free endp ;----- Unpack BMP handle ----- ;--> ; AX :BMP handle ;<-- ; AX :BMP entry ; CX :page count bmp_unpack proc mov cl,ah shrm cx,2 and cx,3 inc cx and ah,00000011b VZ_RET bmp_unpack endp endbs iseg ;----- Init BMP table ----- public init_bmp init_bmp proc mov si,offset cgroup:r_ems mov bx,offset cgroup:bmptbl clr dx call ems_check _ifn z mov [si].bm_offset,bx mov ax,emspages call initbmp1 _endif mov si,offset cgroup:r_xms mov [si].bm_base,dx call xms_check _ifn z mov [si].bm_offset,bx mov ax,xmssize mov cl,4 shr ax,cl call initbmp1 _endif mov si,offset cgroup:r_tmp mov [si].bm_base,dx mov [si].bm_offset,bx mov ax,PAGEMAX sub ax,dx mov [si].bm_max,ax VZ_RET initbmp1 proc mov [si].bm_max,ax tst ax _ifn z dec ax and ax,not 7 add ax,8 _endif add dx,ax shrm ax,3 add bx,ax VZ_RET initbmp1 endp init_bmp endp endis bseg ;----- Is handle EMS, XMS or TMP? ----- ;--> ; AX :BMP handle ;<-- ; SI :BMP work ptr ishandle proc push ax and ah,00000011b dec ax call ems_check _ifn z mov si,offset cgroup:r_ems cmp ax,[si + type _bmprec] jb ishdl8 _endif call xms_check _ifn z mov si,offset cgroup:r_xms cmp ax,[si + type _bmprec] jb ishdl8 _endif mov si,offset cgroup:r_tmp ishdl8: pop ax sub ax,[si].bm_base VZ_RET ishandle endp ;----- XMEM block read/write ----- ;--> ; AX :BMP handle ; ES:DI :src/dst ptr ; CX :size public xmem_write, xmem_read xmem_write proc pushm mov ds,cs:save_ds call ishandle cmp si,offset cgroup:r_xms je xms_write cmp si,offset cgroup:r_tmp _if e call tmp_write jmp xmemrw9 _endif call ems_premap movseg ds,es mov es,ax mov si,di clr di jmps ems_rw1 xms_write: clr dx inc cx and cl,not 1 mov bx,00000100b jmps xms_rw1 xmem_write endp xmem_read proc pushm mov ds,cs:save_ds call ishandle cmp si,offset cgroup:r_xms je xms_read cmp si,offset cgroup:r_tmp _if e call tmp_read jmps xmemrw9 _endif call ems_premap mov ds,ax clr si ems_rw1: call memmove call ems_loadmap jmps xmemrw9 xms_read: clr dx test cl,1 _ifn z mov bx,cx inc cx mov dl,es:[di+bx] mov dh,TRUE _endif mov bx,00001010b xms_rw1: mov si,offset cgroup:embwork mov [si],cx mov word ptr [si+bx],0 mov [si+bx+2],di mov [si+bx+4],es xor bl,1110b and ah,00000011b dec ax rorm ax,2 xchg al,ah mov [si+bx+3],ax clr ax mov [si+bx+2],al mov [si+bx+5],al mov ax,cs:h_xms mov [si+bx],ax pushm xmm XM_EMBMOVE popm tst dh _ifn z mov bx,cx dec bx mov es:[di+bx],dl _endif xmemrw9: popm VZ_RET xmem_read endp ;----- TMPfile read/write ----- tmp_write proc push ax call tmp_open _if c cmp ax,ENOFILE jne tmpw_x push cx clr cx msdos F_CREATE pop cx jc tmpw_x mov bx,ax _endif pop dx mov ah,F_WRITE jmps tmp_rw tmpw_x: pop ax stc VZ_RET tmp_write endp tmp_read proc push ax call tmp_open pop dx jc tmpr9 mov ah,F_READ tmp_rw: mov cs:h_tmp,bx push ds pushm and dh,00000011b tst dx _ifn z dec dx _endif rorm dx,2 clr ch mov cl,dl clr dl msdos F_SEEK,0 popm movseg ds,es mov dx,di int 21h _ifn c cmp ax,cx _endif pop ds tmpr9: VZ_RET tmp_read endp tmp_open proc call get_h_tmp _if le mov dx,offset cgroup:tmppath msdos F_OPEN,O_UPDATE jc tmpop9 mov bx,ax _endif tmpop9: VZ_RET tmp_open endp public tmp_close tmp_close proc call get_h_tmp _if g msdos F_CLOSE mov cs:h_tmp,INVALID _endif VZ_RET tmp_close endp endbs end ;------------------------------------------------ ; End of ems.asm ;------------------------------------------------