title HMem ;HMem.asm - huge memory functions HMemCpy, etc include gpfix.inc include kernel.inc externFP Int21Handler DataBegin externW WinFlags ifdef WOW externD pFileTable externW cur_dos_PDB externW Win_PDB endif DataEnd ifdef WOW externFP WOWFileRead externFP WOWFileWrite endif sBegin CODE assumes cs,CODE ifdef WOW externD prevInt21proc endif externA __AHINCR cProc hMemCpy,, parmD dest ; to ES:DI parmD src ; to DS:SI parmD cnt ; to DX:AX localW flags cBegin SetKernelDS mov bx, WinFlags mov flags, bx mov dx, seg_cnt ; DX:AX is 32 bit length mov ax, off_cnt xor cx, cx ; 0 if fault loading operands beg_fault_trap hmc_trap lds si, src les di, dest cld hmc_loop: mov cx, 8000h ; try to copy 32K cmp cx, si ; space left in source? jae @F mov cx, si @@: cmp cx, di ; space left in dest? jae @F mov cx, di @@: neg cx ; convert bytes left to positive or dx, dx ; >64K left to copy? jnz @F cmp cx, ax ; At least this much left? jbe @F mov cx, ax @@: sub ax, cx ; Decrement count while we're here sbb dx, 0 test flags, WF_CPU386 + WF_CPU486 + WF_ENHANCED jnz hmc_do32 shr cx, 1 ; Copy 32KB rep movsw adc cx, 0 rep movsb jmps hmc_copied hmc_do32: .386p push cx shr cx, 2 rep movsd pop cx and cx, 3 rep movsb .286p hmc_copied: mov cx, ax ; At end of copy? or cx, dx jz hmc_done or si, si ; Source wrap-around? jnz @F mov bx, ds add bx, __AHINCR mov ds, bx @@: or di, di ; Dest wrap-around? jnz @F mov bx, es add bx, __AHINCR mov es, bx end_fault_trap @@: jmps hmc_loop hmc_trap: fault_fix_stack ; DX:AX = bytes left if failure krDebugOut DEB_ERROR, "hMemCopy: Copy past end of segment" add ax, cx adc dx, 0 hmc_done: ; DX:AX = 0 if success cEnd ifdef W_Q21 cProc _HREAD, , parmW h parmD lpData parmD dwCnt cBegin SetKernelDS ds push bx mov bx, Win_PDB cmp bx, cur_dos_PDB je HR_PDB_ok push ax mov cur_dos_PDB,bx mov ah,50h pushf call cs:prevInt21Proc ; JUMP THROUGH CS VARIABLE pop ax HR_PDB_OK: pop bx cCall WowFileRead, ; DX:AX = Number Bytes Read ; DX = FFFF, AX = Error Code inc dx jnz @f xor dx,dx or ax, -1 @@: dec dx cEnd cProc _HWRITE, , parmW h parmD lpData parmD dwCnt cBegin SetKernelDS ds push bx ; Setting the DOS PDB can probably mov bx, Win_PDB ; be removed just pass Win_PDB to cmp bx, cur_dos_PDB ; the WOW thunk je HW_PDB_ok push ax mov cur_dos_PDB,bx mov ah,50h pushf call cs:prevInt21Proc ; JUMP THROUGH CS VARIABLE pop ax HW_PDB_OK: pop bx cCall WowFileWrite, ; DX:AX = Number Bytes Read ; DX = FFFF, AX = Error Code inc dx jnz @f xor dx,dx or ax, -1 @@: dec dx cEnd else public _HREAD, _HWRITE _HREAD: mov bx, 3f00h jmps hugeIO _HWRITE: mov bx, 4000h cProc hugeIO, , parmW h parmD lpData parmD dwCnt localD dwTot localW func cBegin mov func, bx ; read from a file mov bx, h xor cx, cx mov seg_dwTot, cx mov off_dwTot, cx beg_fault_trap hr_fault lds dx, lpData mov si, seg_dwCnt mov di, off_dwCnt hr_loop: mov cx, 8000h ; try to do 32KB cmp cx, dx ; space left in data buffer jae @F mov cx, dx neg cx @@: or si, si ; at least 64K left jnz @F cmp cx, di jbe @F mov cx, di @@: mov ax, func ; talk to DOS DOSCALL jc hr_oops add off_dwTot, ax ; update transfer count adc seg_dwTot, 0 cmp ax, cx ; end of file? jnz hr_done sub di, ax ; decrement count sbb si, 0 mov cx, si ; end of count or cx, di jz hr_done add dx, ax ; update pointer to data jnz @F ; wrapped to next segment mov ax, ds add ax, __AHINCR mov ds, ax end_fault_trap @@: jmps hr_loop hr_fault: pop dx pop ax ; krDebugOut DEB_ERROR, "File I/O past end of memory block" krDebugOut DEB_ERROR, "GP fault in _hread/_hwrite at #DX #AX" ; fault_fix_stack hr_oops: or dx, -1 mov seg_dwTot, dx mov off_dwTot, dx hr_done: mov dx, seg_dwTot mov ax, off_dwTot cEnd endif ; WOW sEnd end