/*****************************************************************************/ /* Copyright (c) 1987 - 1988, Future Soft Engineering, Inc. */ /* Houston, Texas */ /*****************************************************************************/ #define NOLSTRING TRUE /* jtf win3 mod */ #include #include "port1632.h" #include "dcrc.h" #include "dynacomm.h" /*---------------------------------------------------------------------------*/ #define XM_ABORT 0x8000 #define XM_COMPLETE 0x4000 #define XM_BLKREPEAT 0x2000 #define XM_CRC 0x0800 #define YM_1KBLK 0x0400 #define YM_GOPTION 0x0200 #define XM_RETRYMASK 0x001F /* mbbx 1.04: relax 15 -> 31 */ #define XM_RETRIES 0x0014 /* mbbx 1.04: relax 10 -> 20 */ #define XM_RETRYINITCRC 4 #define XM_RETRYINITCKS 10 #define XM_WAITRCVINIT 50 /* mbbx 1.04: relax... */ #define XM_WAITNEXTBLK 100 #define XM_WAITNEXTCHAR 50 //sdj: was 20 to get rid of xmodem //sdj: retries when moused moved..move to 50 #define XM_WAITSNDINIT 600 BOOL YM_RcvBatch(WORD); BOOL NEAR YM_RcvFileInfo(WORD *, WORD *); BOOL XM_RcvFile(WORD); BOOL NEAR XM_RcvInit(WORD *, WORD *); BOOL NEAR XM_RcvData(WORD *, WORD *); BOOL NEAR XM_RcvBlockHeader(WORD *, WORD *); BOOL NEAR XM_RcvBlockData(WORD *blockNumber, WORD blockSize,WORD *rcvStatus); VOID NEAR XM_RcvBlockAbort(WORD *); BOOL NEAR XM_RcvEnd(); VOID NEAR XM_RcvAbort(); BOOL YM_SndBatch(WORD); BOOL NEAR YM_SndFileInfo(WORD *, BOOL); BOOL XM_SndFile(WORD sndStatus); BOOL NEAR XM_SndInit(WORD *); BOOL NEAR XM_SndData(WORD *); BOOL NEAR XM_SndBlockData(WORD *, WORD *, WORD *); BOOL NEAR XM_SndEnd(); VOID NEAR XM_SndAbort(); BYTE XM_CheckSum(BYTE *dataBlock, WORD blockSize); /* mbbx 2.00: NEAR -> FAR */ WORD XM_CalcCRC(BYTE *, INT); /* mbbx 2.00: NEAR -> FAR */ /*---------------------------------------------------------------------------*/ /* UTILITIES --> RCVBFILE.C */ BOOL initXfrBuffer(WORD wBufSize); VOID fillXfrBuffer(BYTE *, WORD); WORD readXfrBuffer(BYTE *dataBlock,WORD blockSize,BOOL bBlkRepeat); BOOL writeXfrBuffer(BYTE *dataBlock, WORD blockSize,BOOL bBlkRepeat); VOID grabXfrBuffer(BYTE *, WORD); BOOL clearXfrBuffer(); VOID freeXfrBuffer(); /*---------------------------------------------------------------------------*/ /* XM_RcvFile() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL XM_RcvFile(WORD rcvStatus) { WORD blockSize; if(XM_RcvInit(&blockSize, &rcvStatus)) if(XM_RcvData(&blockSize, &rcvStatus)) if(XM_RcvEnd()) return(TRUE); XM_RcvAbort(); return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_RcvInit() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_RcvInit(WORD *blockSize, WORD *rcvStatus) { BYTE work[3]; WORD retry; LoadString(hInst, STR_RI, (LPSTR) work, 4); /* mbbx 1.04: REZ... */ bSetup(work); *blockSize = 128; *rcvStatus |= XM_RETRIES; if(*rcvStatus & (YM_1KBLK | YM_GOPTION)) *rcvStatus |= XM_CRC; while(*rcvStatus & XM_CRC) { for(retry = XM_RETRYINITCRC; retry > 0; retry -= 1) { modemWr('C'); if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); if(waitRcvChar(work, XM_WAITRCVINIT, 0, CHSTX, CHSOH, CHEOT, CHCAN, NULL)) { switch(work[0]) { case CHSTX: *blockSize = 1024; /* then fall thru... */ case CHSOH: return(TRUE); case CHEOT: *rcvStatus |= XM_COMPLETE; return(TRUE); case CHCAN: return(FALSE); } } if(xferStopped) return(FALSE); } *rcvStatus &= ((*rcvStatus & YM_GOPTION) ? ~YM_GOPTION : ~XM_CRC); } for(retry = XM_RETRYINITCKS; retry > 0; retry -= 1) /* mbbx 1.04: relax */ { modemWr(CHNAK); if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); if(waitRcvChar(work, XM_WAITRCVINIT, 0, CHSTX, CHSOH, CHEOT, CHCAN, NULL)) { switch(work[0]) { case CHSTX: *blockSize = 1024; /* then fall thru... */ case CHSOH: return(TRUE); case CHEOT: *rcvStatus |= XM_COMPLETE; return(TRUE); case CHCAN: return(FALSE); } } if(xferStopped) break; showBErrors(++xferErrors); } return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_RcvData() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_RcvData(WORD *blockSize, WORD *rcvStatus) { BYTE work[3]; WORD blockNumber = 1; if(*rcvStatus & XM_COMPLETE) return(TRUE); LoadString(hInst, STR_DF, (LPSTR) work, 4); /* mbbx 1.04: REZ... */ bSetup(work); if(initXfrBuffer(12 * 1024)) { XM_RcvBlockData(&blockNumber, *blockSize, rcvStatus); while(!(*rcvStatus & (XM_COMPLETE | XM_ABORT))) { if(XM_RcvBlockHeader(blockSize, rcvStatus)) XM_RcvBlockData(&blockNumber, *blockSize, rcvStatus); } if(!(*rcvStatus & XM_ABORT)) if(!clearXfrBuffer()) *rcvStatus |= XM_ABORT; freeXfrBuffer(); } return(!(*rcvStatus & XM_ABORT)); } /*---------------------------------------------------------------------------*/ /* XM_RcvBlockHeader() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_RcvBlockHeader(WORD *blockSize, WORD *rcvStatus) { BYTE work[1]; if(waitRcvChar(work, XM_WAITNEXTBLK, 0, CHSTX, CHSOH, CHEOT, CHCAN, NULL)) { switch(work[0]) { case CHSTX: *blockSize = 1024; return(TRUE); case CHSOH: *blockSize = 128; return(TRUE); case CHEOT: *rcvStatus |= XM_COMPLETE; return(FALSE); case CHCAN: xferStopped = TRUE; break; } } XM_RcvBlockAbort(rcvStatus); return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_RcvBlockData() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_RcvBlockData(WORD *blockNumber, WORD blockSize,WORD *rcvStatus) { BYTE work[2]; BOOL bBlkRepeat; WORD ndx; BYTE dataBlock[1024]; signed char i,j; while(waitRcvChar(work, XM_WAITNEXTCHAR, 0, 0) && waitRcvChar(work+1, XM_WAITNEXTCHAR, 0, 0) && ( (j=(signed char)work[0]) == ~(i = (signed char)work[1]) ) ) //sdj: on mips xmodem rcv was broken due to (BYTE)~work[1] { if(bBlkRepeat = (work[0] != (BYTE) *blockNumber)) if(work[0] != (BYTE) (*blockNumber-1)) break; for(ndx = 0; ndx < blockSize; ndx += 1) if(!waitRcvChar(dataBlock+ndx, XM_WAITNEXTCHAR, 0, 0)) break; if(ndx < blockSize) break; if(!waitRcvChar(work, XM_WAITNEXTCHAR, 0, 0)) break; if(!(*rcvStatus & XM_CRC)) { if(XM_CheckSum(dataBlock, blockSize) != work[0]) break; } else { if(!waitRcvChar(work+1, XM_WAITNEXTCHAR, 0, 0) || (XM_CalcCRC(dataBlock, blockSize) != ((work[0] << 8) | work[1]))) break; } if(!writeXfrBuffer(dataBlock, blockSize, bBlkRepeat)) { xferStopped = TRUE; break; } if(!bBlkRepeat) /* mbb: reset retry counter */ { *blockNumber += 1; *rcvStatus = (*rcvStatus & ~XM_RETRYMASK) | XM_RETRIES; if(*blockNumber > 1) /* mbb: skip block 0 */ { if(xferOrig > 0) { xferBytes -= blockSize; updateProgress(FALSE); } else showBBytes(xferLength += blockSize, FALSE); /* mbbx 2.00: xfer ctrls */ } } if(!(*rcvStatus & YM_GOPTION)) { modemWr(CHACK); if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); } return(TRUE); } XM_RcvBlockAbort(rcvStatus); return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_RcvBlockAbort() - [mbb] */ /*---------------------------------------------------------------------------*/ VOID NEAR XM_RcvBlockAbort(WORD *rcvStatus) { BYTE work[1]; if(xferStopped || (((*rcvStatus -= 1) & XM_RETRYMASK) == 0)) *rcvStatus |= XM_ABORT; else { while(waitRcvChar(work, XM_WAITNEXTCHAR, 0, 0)); modemWr(CHNAK); if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); } if(!xferStopped) showBErrors(++xferErrors); } /*---------------------------------------------------------------------------*/ /* XM_RcvEnd() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_RcvEnd() { BYTE work[3]; WORD retry; LoadString(hInst, STR_RE, (LPSTR) work, 4); /* mbbx 1.04: REZ... */ bSetup(work); modemWr(CHACK); if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); for(retry = XM_RETRIES; retry > 0; retry -= 1) /* mbbx 1.04: relax */ { if(waitRcvChar(work, XM_WAITNEXTBLK / 2, 0, CHEOT, CHCAN, NULL)) { switch(work[0]) { case CHEOT: modemWr(CHACK); if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); showBErrors(++xferErrors); continue; case CHCAN: xferStopped = TRUE; break; } } if(xferStopped) break; return(TRUE); } return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_RcvAbort() - [mbb] */ /*---------------------------------------------------------------------------*/ VOID NEAR XM_RcvAbort() { BYTE work[1]; rcvAbort(); while(waitRcvChar(work, XM_WAITNEXTCHAR, 0, 0)); modemWr(CHCAN); modemWr(CHCAN); modemWr(CHCAN); modemWr(CHCAN); modemWr(CHCAN); modemWr(BS); modemWr(BS); modemWr(BS); modemWr(BS); modemWr(BS); if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); } /*---------------------------------------------------------------------------*/ /* XM_SndFile() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL XM_SndFile(WORD sndStatus) { if(XM_SndInit(&sndStatus)) if(XM_SndData(&sndStatus)) if(XM_SndEnd()) return(TRUE); XM_SndAbort(); return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_SndInit() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_SndInit(WORD *sndStatus) { BYTE work[3]; LoadString(hInst, STR_SI, (LPSTR) work, 4); /* mbbx 1.04: REZ... */ bSetup(work); *sndStatus |= XM_RETRIES; if(waitRcvChar(work, XM_WAITSNDINIT, 0, 'C', CHNAK, CHCAN, 0)) { switch(work[0]) { case 'C': *sndStatus |= XM_CRC; if(!(*sndStatus & YM_1KBLK) && waitRcvChar(work, XM_WAITNEXTCHAR / 2, 0, 'K', 0)) *sndStatus |= YM_1KBLK; return(TRUE); case CHNAK: *sndStatus &= ~(XM_CRC | YM_1KBLK); return(TRUE); case CHCAN: break; } } return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_SndData() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_SndData(WORD *sndStatus) { BYTE work[3]; WORD blockNumber = 1; WORD blockSize; LoadString(hInst, STR_DF, (LPSTR) work, 4); /* mbbx 1.04: REZ... */ bSetup(work); if(initXfrBuffer(12 * 1024)) { blockSize = (!(*sndStatus & YM_1KBLK) ? 128 : 1024); while(!(*sndStatus & (XM_COMPLETE | XM_ABORT))) XM_SndBlockData(&blockNumber, &blockSize, sndStatus); freeXfrBuffer(); } return(!(*sndStatus & XM_ABORT)); } /*---------------------------------------------------------------------------*/ /* XM_SndBlockData() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_SndBlockData(WORD *blockNumber, WORD *blockSize, WORD *sndStatus) { BYTE dataBlock[1024]; WORD dataBytes; WORD wCRC; BYTE work[1]; BOOL writeGood; switch(dataBytes = readXfrBuffer(dataBlock, *blockSize, (*sndStatus & XM_BLKREPEAT))) { case (WORD)-1: xferStopped = TRUE; break; case 0: *sndStatus |= XM_COMPLETE; return(TRUE); default: if((*blockSize == 1024) && (dataBytes <= (5 * 128)) && !(*sndStatus & XM_BLKREPEAT)) readXfrBuffer(dataBlock, *blockSize = 128, TRUE); modemWr((*blockSize == 128) ? CHSOH : CHSTX); modemWr((BYTE) *blockNumber); modemWr((BYTE) ~*blockNumber); writeGood = modemWrite((LPSTR) dataBlock, (INT)(*blockSize)); if(!writeGood) { wCRC = 0; break; } if(!(*sndStatus & XM_CRC)) modemWr(XM_CheckSum(dataBlock, *blockSize)); else { wCRC = XM_CalcCRC(dataBlock, *blockSize); modemWr(HIBYTE(wCRC)); modemWr(LOBYTE(wCRC)); } if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); if(!waitRcvChar(work, XM_WAITSNDINIT, 0, CHACK, CHNAK, CHCAN, (*blockNumber <= 1) ? 'C' : 0, 0)) { xferStopped = TRUE; break; } switch(work[0]) { case CHACK: *blockNumber += 1; *sndStatus = (*sndStatus & ~(XM_BLKREPEAT | XM_RETRYMASK)) | XM_RETRIES; if(*blockNumber > 1) { xferBytes -= *blockSize; updateProgress(FALSE); } return(TRUE); case CHNAK: break; case CHCAN: xferStopped = TRUE; break; } break; } if(xferStopped || (((*sndStatus -= 1) & XM_RETRYMASK) == 0)) *sndStatus |= XM_ABORT; else *sndStatus |= XM_BLKREPEAT; if(!xferStopped) showBErrors(++xferErrors); return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_SndEnd() - [mbb] */ /*---------------------------------------------------------------------------*/ BOOL NEAR XM_SndEnd() { BYTE work[3]; WORD retry; LoadString(hInst, STR_SE, (LPSTR) work, 4); /* mbbx 1.04: REZ... */ bSetup(work); for(retry = XM_RETRIES; retry > 0; retry -= 1) /* mbbx 1.04: relax */ { modemWr(CHEOT); if(xferPSChar) /* mbbx 1.02: packet switching... */ modemWr(xferPSChar); if(waitRcvChar(work, XM_WAITNEXTBLK, 0, CHACK, CHCAN, 0)) /* mbbx 1.04: relax 15 -> 60 */ { switch(work[0]) { case CHACK: return(TRUE); case CHCAN: xferStopped = TRUE; break; } } if(xferStopped) break; showBErrors(++xferErrors); } return(FALSE); } /*---------------------------------------------------------------------------*/ /* XM_SndAbort() - [mbb] */ /*---------------------------------------------------------------------------*/ VOID NEAR XM_SndAbort() { BYTE work[1]; sndAbort(); modemWr(CHCAN); modemWr(CHCAN); modemWr(CHCAN); modemWr(CHCAN); modemWr(CHCAN); modemWr(BS); modemWr(BS); modemWr(BS); modemWr(BS); modemWr(BS); if(xferPSChar) /* mbbx 1.02: packet switching */ modemWr(xferPSChar); } /*---------------------------------------------------------------------------*/ /* XM_CheckSum() - [mbb] */ /*---------------------------------------------------------------------------*/ BYTE XM_CheckSum(BYTE *dataBlock, WORD blockSize) /* mbbx 2.00: NEAR -> FAR */ { BYTE XM_CheckSum = 0; while(blockSize > 0) XM_CheckSum += dataBlock[--blockSize]; return(XM_CheckSum); } /*---------------------------------------------------------------------------*/ /* XM_CalcCRC() - [mbb] */ /*---------------------------------------------------------------------------*/ WORD XM_CalcCRC(BYTE *dataBlock, INT blockSize) { WORD XM_CalcCRC = 0; INT ndx; while(--blockSize >= 0) { XM_CalcCRC = XM_CalcCRC ^ (((WORD) *dataBlock++) << 8); for(ndx = 0; ndx < 8; ndx += 1) { if(XM_CalcCRC & 0x8000) XM_CalcCRC = (XM_CalcCRC << 1) ^ 0x1021; else XM_CalcCRC = (XM_CalcCRC << 1); } } return(XM_CalcCRC & 0xFFFF); } /*---------------------------------------------------------------------------*/ /* UTILITIES --> file buffering to be used by all RCV protocols !!! [mbb] */ /*---------------------------------------------------------------------------*/ HANDLE hXfrBuf; LPSTR lpXfrBuf; WORD wXfrBufSize; WORD wXfrBufBytes; WORD wXfrBufIndex; WORD wXfrBufExtend; BOOL initXfrBuffer(WORD wBufSize) { wXfrBufSize = wBufSize; if((hXfrBuf = GlobalAlloc(GMEM_MOVEABLE, (DWORD) wXfrBufSize)) != NULL) { #ifdef ORGCODE if((lpXfrBuf = GlobalWire(hXfrBuf)) != NULL) #else if((lpXfrBuf = GlobalLock(hXfrBuf)) != NULL) #endif { wXfrBufBytes = 0; wXfrBufIndex = 0; wXfrBufExtend = 0; return(TRUE); } GlobalFree(hXfrBuf); } rcvFileErr(); return(FALSE); } WORD readXfrBuffer(BYTE *dataBlock, WORD blockSize, BOOL bBlkRepeat) { if(!bBlkRepeat) wXfrBufIndex += wXfrBufExtend; if((wXfrBufIndex+blockSize) > wXfrBufBytes) { if((wXfrBufBytes -= wXfrBufIndex) > 0) lmovmem(lpXfrBuf+wXfrBufIndex, lpXfrBuf, wXfrBufBytes); if((wXfrBufIndex = (WORD)_lread(xferRefNo, lpXfrBuf, wXfrBufSize-wXfrBufBytes)) == (WORD)-1) { return((WORD)-1); } wXfrBufBytes += wXfrBufIndex; wXfrBufIndex = 0; } if((wXfrBufExtend = (wXfrBufBytes-wXfrBufIndex)) > 0) { if(wXfrBufExtend > blockSize) wXfrBufExtend = blockSize; lmovmem(lpXfrBuf+wXfrBufIndex, (LPSTR) dataBlock, wXfrBufExtend); if(wXfrBufExtend < blockSize) memset(dataBlock+wXfrBufExtend, CNTRLZ, blockSize-wXfrBufExtend); } return(wXfrBufExtend); } BOOL writeXfrBuffer(BYTE *dataBlock, WORD blockSize,BOOL bBlkRepeat) { if(!bBlkRepeat) wXfrBufBytes += wXfrBufExtend; if((wXfrBufBytes+blockSize) > wXfrBufSize) { if(_lwrite(xferRefNo, lpXfrBuf, wXfrBufBytes) != wXfrBufBytes) { rcvFileErr(); return(FALSE); } wXfrBufBytes = 0; } lmovmem((LPSTR) dataBlock, lpXfrBuf+wXfrBufBytes, wXfrBufExtend = blockSize); return(TRUE); } BOOL clearXfrBuffer() { if(wXfrBufExtend > 0) { while(wXfrBufExtend > 0) /* mbbx 1.04 ... */ { if(*(lpXfrBuf+(wXfrBufBytes+wXfrBufExtend-1)) != CNTRLZ) break; wXfrBufExtend -= 1; } wXfrBufBytes += wXfrBufExtend; wXfrBufExtend = 0; } if(wXfrBufBytes > 0) { if(_lwrite(xferRefNo, lpXfrBuf, wXfrBufBytes) != wXfrBufBytes) { rcvFileErr(); return(FALSE); } wXfrBufBytes = 0; } return(TRUE); } VOID freeXfrBuffer() { #ifdef ORGCODE GlobalUnWire(hXfrBuf); #else GlobalUnlock(hXfrBuf); #endif GlobalFree(hXfrBuf); }