diff --git a/src/sbbs3/sexyz.c b/src/sbbs3/sexyz.c
index 67ecc0a454d86ae9abaae4b3a915ed88937d3a89..173b41bd5c5d5d85d45a177c516b87c4f0423662 100644
--- a/src/sbbs3/sexyz.c
+++ b/src/sbbs3/sexyz.c
@@ -844,9 +844,9 @@ static int send_files(char** fname, uint fnames)
 			success=FALSE;
 			startfile=time(NULL);
 
-			lprintf(LOG_INFO,"Sending %s (%lu KB) via %s"
+			lprintf(LOG_INFO,"Sending %s (%lu KB) via %cMODEM"
 				,path,fsize/1024
-				,mode&XMODEM ? "Xmodem" : mode&YMODEM ? "Ymodem" : "Zmodem");
+				,mode&XMODEM ? 'X' : mode&YMODEM ? 'Y' : 'Z');
 
 			if(mode&ZMODEM)
 					success=zmodem_send_file(&zm, path, fp, /* ZRQINIT? */fnum==0, &startfile, &sent_bytes);
@@ -924,11 +924,11 @@ static int send_files(char** fname, uint fnames)
 
 		if(xmodem_get_mode(&xm)) {
 
-			lprintf(LOG_INFO,"Sending Ymodem termination block");
+			lprintf(LOG_INFO,"Sending YMODEM termination block");
 
 			memset(block,0,XMODEM_MIN_BLOCK_SIZE);	/* send short block for terminator */
 			xmodem_put_block(&xm, block, XMODEM_MIN_BLOCK_SIZE /* block_size */, 0 /* block_num */);
-			if(!xmodem_get_ack(&xm,6,0)) {
+			if(xmodem_get_ack(&xm, /* tries: */6, /* block_num: */0) != ACK) {
 				lprintf(LOG_WARNING,"Failed to receive ACK after terminating block"); 
 			} 
 		}
@@ -977,23 +977,25 @@ static int receive_files(char** fname_list, int fnames)
 
 		else {
 			if(mode&YMODEM) {
-				lprintf(LOG_INFO,"Fetching Ymodem header block");
+				lprintf(LOG_INFO,"Fetching YMODEM header block");
 				for(errors=0;errors<=xm.max_errors && !xm.cancelled;errors++) {
-					if(errors>(xm.max_errors/2) && mode&CRC && !(mode&GMODE))
-						mode&=~CRC;
 					xmodem_put_nak(&xm, /* expected_block: */ 0);
-					if(xmodem_get_block(&xm, block, /* expected_block: */ 0) == 0) {
+					if(xmodem_get_block(&xm, block, /* expected_block: */ 0) == SUCCESS) {
 						send_byte(NULL,ACK,10);
 						break; 
 					} 
+					if(errors+1>xm.max_errors/3 && mode&CRC && !(mode&GMODE)) {
+						lprintf(LOG_NOTICE,"Falling back to 8-bit Checksum mode");
+						mode&=~CRC;
+					}
 				}
-				if(errors>=xm.max_errors || xm.cancelled) {
-					lprintf(LOG_ERR,"Error fetching Ymodem header block");
+				if(errors>xm.max_errors || xm.cancelled) {
+					lprintf(LOG_ERR,"Error fetching YMODEM header block");
 					xmodem_cancel(&xm);
 					return(1); 
 				}
 				if(!block[0]) {
-					lprintf(LOG_INFO,"Received Ymodem termination block");
+					lprintf(LOG_INFO,"Received YMODEM termination block");
 					return(0); 
 				}
 				file_bytes=ftime=total_files=total_bytes=0;
@@ -1005,11 +1007,11 @@ static int receive_files(char** fname_list, int fnames)
 					,&total_files			/* remaining files to be sent */
 					,&total_bytes			/* remaining bytes to be sent */
 					);
-				lprintf(LOG_DEBUG,"Ymodem header (%u fields): %s", i, block+strlen(block)+1);
+				lprintf(LOG_DEBUG,"YMODEM header (%u fields): %s", i, block+strlen(block)+1);
 				SAFECOPY(fname,block);
 
 			} else {	/* Zmodem */
-				lprintf(LOG_INFO,"Waiting for Zmodem sender...");
+				lprintf(LOG_INFO,"Waiting for ZMODEM sender...");
 
 				i=zmodem_recv_init(&zm);
 
@@ -1105,14 +1107,15 @@ static int receive_files(char** fname_list, int fnames)
 		}
 
 		if(mode&XMODEM)
-			lprintf(LOG_INFO,"Receiving %s via Xmodem %s"
+			lprintf(LOG_INFO,"Receiving %s via XMODEM%s %s"
 				,str
+				,mode&GMODE ? "-G" : ""
 				,mode&CRC ? "CRC-16":"Checksum");
 		else
 			lprintf(LOG_INFO,"Receiving %s (%lu KB) via %s %s"
 				,str
 				,file_bytes/1024
-				,mode&YMODEM ? mode&GMODE ? "Ymodem-G" : "Ymodem" :"Zmodem"
+				,mode&YMODEM ? mode&GMODE ? "YMODEM-G" : "YMODEM" :"ZMODEM"
 				,mode&ZMODEM ? "" : (mode&CRC ? "CRC-16" : "Checksum"));
 
 		startfile=time(NULL);
@@ -1138,7 +1141,7 @@ static int receive_files(char** fname_list, int fnames)
 				xmodem_progress(NULL,block_num,ftell(fp),file_bytes,startfile);
 				i=xmodem_get_block(&xm, block, block_num); 	
 
-				if(i!=0) {
+				if(i!=SUCCESS) {
 					if(i==EOT)	{		/* end of transfer */
 						success=TRUE;
 						xmodem_put_ack(&xm);
@@ -1152,20 +1155,23 @@ static int receive_files(char** fname_list, int fnames)
 					if(mode&GMODE)
 						return(-1);
 
-					if(++errors>=xm.max_errors) {
+					if(++errors>xm.max_errors) {
 						lprintf(LOG_ERR,"Too many errors (%u)",errors);
 						xmodem_cancel(&xm);
 						break;
 					}
-					if(block_num==1 && errors>(xm.max_errors/2) && mode&CRC && !(mode&GMODE))
+					if(i!=NOT_XMODEM 
+						&& block_num==1 && errors>xm.max_errors/3 && mode&CRC && !(mode&GMODE)) {
+						lprintf(LOG_NOTICE,"Falling back to 8-bit Checksum mode (error=%d)", i);
 						mode&=~CRC;
+					}
 					xmodem_put_nak(&xm, block_num);
 					continue;
 				}
 				if(!(mode&GMODE))
 					send_byte(NULL,ACK,10);
-				if(file_bytes_left<=0L)  { /* No more bytes to send */
-					lprintf(LOG_WARNING,"Attempt to send more byte specified in header");
+				if(file_bytes_left<=0L)  { /* No more bytes to receive */
+					lprintf(LOG_WARNING,"Sender attempted to send more bytes than were specified in header");
 					break; 
 				}
 				wr=xm.block_size;
@@ -1264,9 +1270,12 @@ static const char* usage=
 	"socket = TCP socket descriptor\n"
 #endif
 	"\n"
-	"opts   = -y  to overwrite files when receiving\n"
+	"opts   = -y  allow overwriting of existing files when receiving\n"
 	"         -o  disable Zmodem CRC-32 mode (use CRC-16)\n"
 	"         -s  disable Zmodem streaming (Slow Zmodem)\n"
+	"         -k  enable X/Ymodem-1K send mode\n"
+    "         -c  enable Xmodem-CRC receive mode\n"
+	"         -g  enable X/Ymodem-G receive mode (no error recovery)\n"
 	"         -2  set maximum Zmodem block size to 2K\n"
 	"         -4  set maximum Zmodem block size to 4K\n"
 	"         -8  set maximum Zmodem block size to 8K (ZedZap)\n"
@@ -1275,11 +1284,11 @@ static const char* usage=
 	"         -rlogin or -ssh or -raw to disable Telnet mode\n"
 	"\n"
 	"cmd    = v  to display detailed version information\n"
-	"         sx to send Xmodem     rx to recv Xmodem\n"
-	"         sX to send Xmodem-1K  rc to recv Xmodem-CRC\n"
-	"         sy to send Ymodem     ry to recv Ymodem\n"
-	"         sY to send Ymodem-1K  rg to recv Ymodem-G\n"
-	"         sz to send Zmodem     rz to recv Zmodem\n"
+	"         sx to send Xmodem     rx to receive Xmodem\n"
+	"         sX to send Xmodem-1K  rc to receive Xmodem-CRC\n"
+	"         sy to send Ymodem     ry to receive Ymodem\n"
+	"         sY to send Ymodem-1K  rg to receive Ymodem-G\n"
+	"         sz to send Zmodem     rz to receive Zmodem\n"
 	"\n"
 	"file   = filename to send or receive\n"
 	"path   = directory to receive files into\n"
@@ -1316,7 +1325,7 @@ int main(int argc, char **argv)
 
 	sscanf("$Revision$", "%*s %s", revision);
 
-	fprintf(statfp,"\nSynchronet External X/Y/Zmodem  v%s-%s"
+	fprintf(statfp,"\nSynchronet External X/Y/ZMODEM  v%s-%s"
 		"  Copyright %s Rob Swindell\n\n"
 		,revision
 		,PLATFORM_DESC
@@ -1364,9 +1373,14 @@ int main(int argc, char **argv)
 	xm.recv_timeout			=iniReadInteger(fp,"Xmodem","RecvTimeout",xm.recv_timeout);	/* seconds */
 	xm.byte_timeout			=iniReadInteger(fp,"Xmodem","ByteTimeout",xm.byte_timeout);	/* seconds */
 	xm.ack_timeout			=iniReadInteger(fp,"Xmodem","AckTimeout",xm.ack_timeout);	/* seconds */
-	xm.block_size			=iniReadInteger(fp,"Xmodem","BlockSize",xm.block_size);		/* 128 or 1024 */
+	xm.block_size			=iniReadInteger(fp,"Xmodem","BlockSize",xm.block_size);			/* 128 or 1024 */
+	xm.max_block_size		=iniReadInteger(fp,"Xmodem","MaxBlockSize",xm.max_block_size);	/* 128 or 1024 */
 	xm.max_errors			=iniReadInteger(fp,"Xmodem","MaxErrors",xm.max_errors);
 	xm.g_delay				=iniReadInteger(fp,"Xmodem","G_Delay",xm.g_delay);
+	xm.crc_mode_supported	=iniReadBool(fp,"Xmodem","SendCRC",xm.crc_mode_supported);
+	xm.g_mode_supported		=iniReadBool(fp,"Xmodem","SendG",xm.g_mode_supported);
+
+	xm.fallback_to_xmodem	=iniReadInteger(fp,"Ymodem","FallbackToXmodem", xm.fallback_to_xmodem);
 
 	zm.init_timeout			=iniReadInteger(fp,"Zmodem","InitTimeout",zm.init_timeout);	/* seconds */
 	zm.send_timeout			=iniReadInteger(fp,"Zmodem","SendTimeout",zm.send_timeout);	/* seconds */
@@ -1445,6 +1459,9 @@ int main(int argc, char **argv)
 					case 'Y':
 						mode|=(YMODEM|CRC);
 						break;
+					case 'k':	/* Ymodem-Checksum for debug/test purposes only */
+						mode|=YMODEM;
+						break;
 					case 'g':
 					case 'G':
 						mode|=(YMODEM|CRC|GMODE);
@@ -1516,8 +1533,8 @@ int main(int argc, char **argv)
 					case 'S':	/* disable Zmodem streaming */
 						zm.no_streaming=TRUE;
 						break;
-					case 'G':	/* Ymodem-G */
-						mode|=GMODE;
+					case 'G':	/* Ymodem-G or Xmodem-G (a.k.a. Qmodem-G) */
+						mode|=(GMODE|CRC);
 						break;
 					case 'Y':
 						mode|=OVERWRITE;
diff --git a/src/sbbs3/sexyz.h b/src/sbbs3/sexyz.h
index 143f78e04ad7b451104cd51511691c70488fdbe8..2bf63ebe32363a03fd4bd1c8ad88b4936ecf7026 100644
--- a/src/sbbs3/sexyz.h
+++ b/src/sbbs3/sexyz.h
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2008 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -46,7 +46,7 @@
 #define YMODEM			(1<<3)	/* Use Ymodem								*/
 #define ZMODEM			(1<<4)	/* Use Zmodem								*/
 #define CRC 			(1<<5)	/* Use CRC error correction 				*/
-#define GMODE			(1<<6)	/* For Qmodem-G and Ymodem-G				*/
+#define GMODE			(1<<6)	/* For Xmodem-G and Ymodem-G				*/
 #define RECVDIR 		(1<<7)	/* Directory specified to download to		*/
 #define OVERWRITE		(1<<9)	/* Overwrite receiving files				*/
 
@@ -54,5 +54,8 @@
 #define CTRL_ESC	(1<<0)	/* Escape all control chars 				*/
 #define VAR_HDRS	(1<<1)	/* Use variable headers 					*/
 
-#define NOINP -1     			/* input buffer empty (incom only) */
-#define NOT_YMODEM -3			/* Expected block zero, got block one */
+#define SUCCESS		0
+#define NOINP		-1			/* input buffer empty (incom only) */
+#define FAILURE		-2			/* xmodem_get_block() failure */
+#define NOT_YMODEM	-3			/* Expected block zero, got block one */
+#define NOT_XMODEM	-4			/* Expected block one, got block zero */
diff --git a/src/sbbs3/xmodem.c b/src/sbbs3/xmodem.c
index 3a8cce81db263aa8e58fa3ea91d5496bdfd97ab1..9c83fd5dd9a27922c12d59cd93c32d5c57fb2256 100644
--- a/src/sbbs3/xmodem.c
+++ b/src/sbbs3/xmodem.c
@@ -116,7 +116,7 @@ int xmodem_put_nak(xmodem_t* xm, unsigned block_num)
 		;				/* wait for any trailing data */
 
 	if(block_num<=1) {
-		if(*(xm->mode)&GMODE) {		/* G for Ymodem-G */
+		if(*(xm->mode)&GMODE) {		/* G for X/Ymodem-G */
 			lprintf(xm,LOG_INFO,"Requesting mode: Streaming, 16-bit CRC");
 			return putcom('G');
 		} else if(*(xm->mode)&CRC) {	/* C for CRC */
@@ -145,7 +145,7 @@ int xmodem_cancel(xmodem_t* xm)
 		xm->cancelled=TRUE;
 	}
 
-	return 0;
+	return SUCCESS;
 }
 
 /****************************************************************************/
@@ -162,7 +162,7 @@ int xmodem_get_block(xmodem_t* xm, uchar* block, unsigned expected_block_num)
 
 	for(errors=0;errors<=xm->max_errors && is_connected(xm);errors++) {
 
-		i=getcom(expected_block_num<=1 ? 5 : 10);
+		i=getcom(expected_block_num<=1 ? 3 : 10);
 		if(eot && i!=EOT && i!=NOINP)
 			eot=0;
 		if(can && i!=CAN)
@@ -172,10 +172,12 @@ int xmodem_get_block(xmodem_t* xm, uchar* block, unsigned expected_block_num)
 				xm->block_size=XMODEM_MIN_BLOCK_SIZE;
 				break;
 			case STX: /* 1024 byte blocks */
+				if(xm->max_block_size < XMODEM_MAX_BLOCK_SIZE)
+					return FAILURE;
 				xm->block_size=XMODEM_MAX_BLOCK_SIZE;
 				break;
 			case EOT:
-				lprintf(xm,LOG_DEBUG,"EOT");
+				lprintf(xm,LOG_DEBUG,"Block %u: EOT received", expected_block_num);
 				if(/*((*xm->mode)&(YMODEM|GMODE))==YMODEM &&*/ !eot) {
 					lprintf(xm,LOG_INFO,"NAKing first EOT");
 					eot=1;	
@@ -186,13 +188,15 @@ int xmodem_get_block(xmodem_t* xm, uchar* block, unsigned expected_block_num)
 			case CAN:
 				if(!can) {			/* must get two CANs in a row */
 					can=1;
-					lprintf(xm,LOG_WARNING,"Received CAN  Expected SOH, STX, or EOT");
+					lprintf(xm,LOG_WARNING,"Block %u: Received CAN  Expected SOH, STX, or EOT"
+						,expected_block_num);
 					continue; 
 				}
-				lprintf(xm,LOG_WARNING,"Cancelled remotely");
+				lprintf(xm,LOG_WARNING,"Block %u: Cancelled remotely", expected_block_num);
 				return(CAN);
 			default:
-				lprintf(xm,LOG_WARNING,"Received %s  Expected SOH, STX, or EOT",chr((uchar)i));
+				lprintf(xm,LOG_WARNING,"Block %u: Received %s  Expected SOH, STX, or EOT"
+					,expected_block_num, chr((uchar)i));
 			case NOINP: 	/* Nothing came in */
 				if(eot)
 					return(EOT);
@@ -226,8 +230,8 @@ int xmodem_get_block(xmodem_t* xm, uchar* block, unsigned expected_block_num)
 			chksum=getcom(xm->byte_timeout);
 
 		if(block_num!=(uchar)~block_inv) {
-			lprintf(xm,LOG_WARNING,"Block number bit error (0x%02X vs 0x%02x)"
-				,block_num,(uchar)~block_inv);
+			lprintf(xm,LOG_WARNING,"Block %u: Block number bit error (0x%02X vs 0x%02x)"
+				,expected_block_num, block_num,(uchar)~block_inv);
 			break; 
 		}
 
@@ -248,6 +252,8 @@ int xmodem_get_block(xmodem_t* xm, uchar* block, unsigned expected_block_num)
 		if(block_num!=(uchar)(expected_block_num&0xff)) {
 			lprintf(xm,LOG_WARNING,"Block number error (%u received, expected %u)"
 				,block_num,expected_block_num&0xff);
+			if((*xm->mode)&XMODEM && expected_block_num==1 && block_num==0)
+				return(NOT_XMODEM);
 			if(expected_block_num==0 && block_num==1)
 				return(NOT_YMODEM);
 			if(expected_block_num && block_num==(uchar)((expected_block_num-1)&0xff))
@@ -255,10 +261,10 @@ int xmodem_get_block(xmodem_t* xm, uchar* block, unsigned expected_block_num)
 			break; 
 		}
 
-		return(0);	/* Success */
+		return SUCCESS;	/* Success */
 	}
 
-	return(-2);		/* Failure */
+	return FAILURE;		/* Failure */
 }
 
 /*****************/
@@ -303,35 +309,35 @@ int xmodem_put_block(xmodem_t* xm, uchar* block, unsigned block_size, unsigned b
 
 /************************************************************/
 /* Gets an acknowledgement - usually after sending a block	*/
-/* Returns 1 if ack received, 0 otherwise.					*/
+/* Returns ACK if ack received								*/
 /************************************************************/
-BOOL xmodem_get_ack(xmodem_t* xm, unsigned tries, unsigned block_num)
+int xmodem_get_ack(xmodem_t* xm, unsigned tries, unsigned block_num)
 {
-	int i,can=0;
+	int i=NOINP,can=0;
 	unsigned errors;
 
-	for(errors=0;errors<tries && is_connected(xm);errors++) {
+	for(errors=0;errors<tries && is_connected(xm);) {
 
-		if((*xm->mode)&GMODE) {		/* Don't wait for ACK on Ymodem-G */
+		if((*xm->mode)&GMODE) {		/* Don't wait for ACK on X/Ymodem-G */
 			SLEEP(xm->g_delay);
 			if(getcom(0)==CAN) {
 				lprintf(xm,LOG_WARNING,"Block %u: !Cancelled remotely", block_num);
 				xmodem_cancel(xm);
-				return(FALSE); 
+				return(CAN); 
 			}
-			return(TRUE); 
+			return(ACK); 
 		}
 
 		i=getcom(xm->ack_timeout);
 		if(can && i!=CAN)
 			can=0;
 		if(i==ACK)
-			return(TRUE);
+			break;
 		if(i==CAN) {
-			if(can) {
+			if(can) {	/* 2 CANs in a row */
 				lprintf(xm,LOG_WARNING,"Block %u: !Cancelled remotely", block_num);
 				xmodem_cancel(xm);
-				return(FALSE); 
+				return(CAN); 
 			}
 			can=1; 
 		}
@@ -339,11 +345,13 @@ BOOL xmodem_get_ack(xmodem_t* xm, unsigned tries, unsigned block_num)
 			lprintf(xm,LOG_WARNING,"Block %u: !Received %s  Expected ACK"
 				,block_num, chr((uchar)i));
 			if(i!=CAN)
-				return(FALSE); 
-		} 
+				return(i); 
+		}
+		if(i!=CAN)
+			errors++;
 	}
 
-	return(FALSE);
+	return(i);
 }
 
 BOOL xmodem_get_mode(xmodem_t* xm)
@@ -365,10 +373,14 @@ BOOL xmodem_get_mode(xmodem_t* xm)
 				return(TRUE); 
 			case 'C':
 				lprintf(xm,LOG_INFO,"Receiver requested mode: 16-bit CRC");
+				if(!xm->crc_mode_supported)
+					continue;
 				*(xm->mode)|=CRC;
 				return(TRUE); 
 			case 'G':
 				lprintf(xm,LOG_INFO,"Receiver requested mode: Streaming, 16-bit CRC");
+				if(!xm->crc_mode_supported || !xm->g_mode_supported)
+					continue;
 				*(xm->mode)|=(GMODE|CRC);
 				return(TRUE); 
 			case CAN:
@@ -462,17 +474,24 @@ BOOL xmodem_send_file(xmodem_t* xm, const char* fname, FILE* fp, time_t* start,
 				,xm->total_files-xm->sent_files
 				,xm->total_bytes-xm->sent_bytes);
 			
-			lprintf(xm,LOG_INFO,"Sending Ymodem header block: '%s'",block+strlen(block)+1);
+			lprintf(xm,LOG_INFO,"Sending YMODEM header block: '%s'",block+strlen(block)+1);
 			
 			block_len=strlen(block)+1+i;
 			for(xm->errors=0;xm->errors<=xm->max_errors && !is_cancelled(xm) && is_connected(xm);xm->errors++) {
 				xmodem_put_block(xm, block, block_len <=XMODEM_MIN_BLOCK_SIZE ? XMODEM_MIN_BLOCK_SIZE:XMODEM_MAX_BLOCK_SIZE, 0  /* block_num */);
-				if(xmodem_get_ack(xm,1,0)) {
+				if((i=xmodem_get_ack(xm,/* tries: */1, /* block_num: */0)) == ACK) {
 					sent_header=TRUE;
 					break; 
 				}
+				if((i==NAK || i=='C' || i=='G')
+					&& xm->fallback_to_xmodem && xm->errors+1 == xm->fallback_to_xmodem) {
+					lprintf(xm,LOG_NOTICE,"Falling back to XMODEM mode after %u attempts"
+						,xm->fallback_to_xmodem);
+					*(xm->mode)&=~YMODEM;
+					break;
+				}
 			}
-			if(xm->errors>=xm->max_errors || is_cancelled(xm)) {
+			if(xm->errors>xm->max_errors || is_cancelled(xm)) {
 				lprintf(xm,LOG_ERR,"Failed to send header block");
 				break;
 			}
@@ -511,7 +530,7 @@ BOOL xmodem_send_file(xmodem_t* xm, const char* fname, FILE* fp, time_t* start,
 			if(xm->progress!=NULL)
 				xm->progress(xm->cbdata,block_num,ftell(fp),st.st_size,startfile);
 			xmodem_put_block(xm, block, xm->block_size, block_num);
-			if(!xmodem_get_ack(xm,5,block_num)) {
+			if(xmodem_get_ack(xm, /* tries: */5,block_num) != ACK) {
 				xm->errors++;
 				lprintf(xm,LOG_WARNING,"Error #%d at offset %ld"
 					,xm->errors,ftell(fp)-xm->block_size);
@@ -576,11 +595,14 @@ void xmodem_init(xmodem_t* xm, void* cbdata, long* mode
 	xm->ack_timeout=10;			/* seconds */
 
 	xm->block_size=XMODEM_MAX_BLOCK_SIZE;
+	xm->max_block_size=XMODEM_MAX_BLOCK_SIZE;
 	xm->max_errors=9;
 	xm->g_delay=1;
 
 	xm->cbdata=cbdata;
 	xm->mode=mode;
+	xm->g_mode_supported=TRUE;
+	xm->crc_mode_supported=TRUE;
 	xm->lputs=lputs;
 	xm->progress=progress;
 	xm->send_byte=send_byte;
diff --git a/src/sbbs3/xmodem.h b/src/sbbs3/xmodem.h
index 951031214649bf76a89bd460997c87acea12208a..aa9fa87e793783f253dadaf351d1ea12c24c5eea 100644
--- a/src/sbbs3/xmodem.h
+++ b/src/sbbs3/xmodem.h
@@ -49,13 +49,17 @@ typedef struct {
 	void*		cbdata;
 	long*		mode;
 	BOOL		cancelled;
+	BOOL		crc_mode_supported;	/* for send */
+	BOOL		g_mode_supported;	/* for send */
 	unsigned	block_size;
+	unsigned	max_block_size;		/* for recv */
 	unsigned	ack_timeout;
 	unsigned	byte_timeout;
 	unsigned	send_timeout;
 	unsigned	recv_timeout;
 	unsigned	errors;
 	unsigned	max_errors;
+	unsigned	fallback_to_xmodem; /* fallback to Xmodem after this many Ymodem send attempts */
 	unsigned	g_delay;
 	unsigned	total_files;
 	unsigned	total_bytes;
@@ -82,7 +86,7 @@ void		xmodem_init(xmodem_t*, void* cbdata, long* mode
 char*		xmodem_ver(char *buf);
 const char* xmodem_source(void);
 int			xmodem_cancel(xmodem_t*);
-BOOL		xmodem_get_ack(xmodem_t*, unsigned tries, unsigned block_num);
+int			xmodem_get_ack(xmodem_t*, unsigned tries, unsigned block_num);
 BOOL		xmodem_get_mode(xmodem_t*);
 BOOL		xmodem_put_eot(xmodem_t*);
 int			xmodem_put_ack(xmodem_t*);