⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 softmodem.cpp

📁 DOSBox emulates a full x86 pc with sound and dos. Its main use is to run old dosgames on platforms w
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2002-2007  The DOSBox Team * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* $Id: softmodem.cpp,v 1.7 2007/01/13 08:35:49 qbix79 Exp $ */#include "dosbox.h"#if C_MODEM#include <string.h>#include <stdlib.h>#include <ctype.h>#include "support.h"#include "serialport.h"#include "softmodem.h"#include "misc_util.h"//#include "mixer.h"CSerialModem::CSerialModem(Bitu id, CommandLine* cmd):CSerial(id, cmd) {	InstallationSuccessful=false;	connected=false;	rqueue=new CFifo(MODEM_BUFFER_QUEUE_SIZE);	tqueue=new CFifo(MODEM_BUFFER_QUEUE_SIZE);		// Default to direct null modem connection.  Telnet mode interprets IAC codes	telnetmode = false;	// Initialize the sockets and setup the listening port	listenport = 23;	waitingclientsocket=0;	clientsocket = 0;	serversocket = 0;	getBituSubstring("listenport:", &listenport, cmd);		// TODO: Fix dialtones if requested	//mhd.chan=MIXER_AddChannel((MIXER_MixHandler)this->MODEM_CallBack,8000,"MODEM");	//MIXER_Enable(mhd.chan,false);	//MIXER_SetMode(mhd.chan,MIXER_16MONO);			CSerial::Init_Registers();	Reset(); // reset calls EnterIdleState			setEvent(SERIAL_POLLING_EVENT,1);	InstallationSuccessful=true;}CSerialModem::~CSerialModem() {	if(serversocket) delete serversocket;	if(clientsocket) delete clientsocket;	if(waitingclientsocket) delete waitingclientsocket;	delete rqueue;	delete tqueue;	// remove events	for(Bitu i = SERIAL_BASE_EVENT_COUNT+1;	i <= SERIAL_MODEM_EVENT_COUNT; i++)		removeEvent(i);}void CSerialModem::handleUpperEvent(Bit16u type) {	switch(type)	{	case SERIAL_RX_EVENT:		{			break;		}	case MODEM_TX_EVENT:		{			if(tqueue->left()) {				tqueue->addb(waiting_tx_character);				if(tqueue->left() < 2) {					CSerial::setCTS(false);				}			} else LOG_MSG("MODEM: TX Buffer overflow!");			ByteTransmitted();						break;		}	case SERIAL_POLLING_EVENT:		{			Timer2();			setEvent(SERIAL_POLLING_EVENT,1);			break;		}	case MODEM_RING_EVENT:		{			break;		}	}}void CSerialModem::SendLine(const char *line) {	rqueue->addb(0xd);	rqueue->addb(0xa);	rqueue->adds((Bit8u *)line,strlen(line));	rqueue->addb(0xd);	rqueue->addb(0xa);}// only for numbers < 1000...void CSerialModem::SendNumber(Bitu val) {	rqueue->addb(0xd);	rqueue->addb(0xa);		rqueue->addb(val/100+'0');	val = val%100;	rqueue->addb(val/10+'0');	val = val%10;	rqueue->addb(val+'0');	rqueue->addb(0xd);	rqueue->addb(0xa);}void CSerialModem::SendRes(ResTypes response) {	char * string;Bitu code;	switch (response)	{		case ResNONE:		return;		case ResOK:			string="OK"; code=0; break;		case ResERROR:		string="ERROR"; code=4; break;		case ResRING:		string="RING"; code=2; break;		case ResNODIALTONE: string="NO DIALTONE"; code=6; break;		case ResNOCARRIER:	string="NO CARRIER" ;code=3; break;		case ResCONNECT:	string="CONNECT 57600"; code=1; break;	}		if(doresponse!=1) {		if(doresponse==2 && (response==ResRING || 			response == ResCONNECT || response==ResNOCARRIER)) return;		if(numericresponse) SendNumber(code);		else SendLine(string);		//if(CSerial::CanReceiveByte())	// very fast response		//	if(rqueue->inuse() && CSerial::getRTS())		//	{ Bit8u rbyte =rqueue->getb();		//		CSerial::receiveByte(rbyte);		//	LOG_MSG("Modem: sending byte %2x back to UART2",rbyte);		//	}		LOG_MSG("Modem response: %s", string);	}}bool CSerialModem::Dial(char * host) {	// Scan host for port	Bit16u port;	char * hasport=strrchr(host,':');	if (hasport) {		*hasport++=0;		port=(Bit16u)atoi(hasport);	}	else port=MODEM_DEFAULT_PORT;	// Resolve host we're gonna dial	LOG_MSG("Connecting to host %s port %d",host,port);	clientsocket = new TCPClientSocket(host, port);	if(!clientsocket->isopen) {		delete clientsocket;		clientsocket=0;		LOG_MSG("Failed to connect.");		SendRes(ResNOCARRIER);		EnterIdleState();		return false;	} else {		EnterConnectedState();		return true;	}}void CSerialModem::AcceptIncomingCall(void) {	if(waitingclientsocket) {		clientsocket=waitingclientsocket;		waitingclientsocket=0;		EnterConnectedState();	} else {		EnterIdleState();	}}Bitu CSerialModem::ScanNumber(char * & scan) {	Bitu ret=0;	while (char c=*scan) {		if (c>='0' && c<='9') {			ret*=10;			ret+=c-'0';			scan++;		} else break;	}	return ret;}void CSerialModem::Reset(){	EnterIdleState();	cmdpos = 0;	cmdbuf[0]=0;	oldDTRstate = getDTR();	flowcontrol = 0;	plusinc = 0;	if(clientsocket) {		delete clientsocket;		clientsocket=0;	}	memset(&reg,0,sizeof(reg));	reg[MREG_AUTOANSWER_COUNT]=0;	// no autoanswer	reg[MREG_RING_COUNT] = 1;	reg[MREG_ESCAPE_CHAR]='+';	reg[MREG_CR_CHAR]='\r';	reg[MREG_LF_CHAR]='\n';	reg[MREG_BACKSPACE_CHAR]='\b';	cmdpause = 0;		echo = true;	doresponse = 0;	numericresponse = false;	/* Default to direct null modem connection.  Telnet mode interprets IAC codes */	telnetmode = false;}void CSerialModem::EnterIdleState(void){	connected=false;	ringing=false;		if(clientsocket) {		delete clientsocket;		clientsocket=0;	}	if(waitingclientsocket) {	// clear current incoming socket		delete waitingclientsocket;		waitingclientsocket=0;	}	// get rid of everything	if(serversocket) {		while(waitingclientsocket=serversocket->Accept())			delete waitingclientsocket;	} else if (listenport) {				serversocket=new TCPServerSocket(listenport);			if(!serversocket->isopen) {			LOG_MSG("Serial%d: Modem could not open TCP port %d.",COMNUMBER,listenport);			delete serversocket;			serversocket=0;		} else LOG_MSG("Serial%d: Modem listening on port %d...",COMNUMBER,listenport);	}	waitingclientsocket=0;		commandmode = true;	CSerial::setCD(false);	CSerial::setRI(false);	CSerial::setDSR(true);	CSerial::setCTS(true);	tqueue->clear();}void CSerialModem::EnterConnectedState(void) {	if(serversocket) {		// we don't accept further calls		delete serversocket;		serversocket=0;	}	SendRes(ResCONNECT);	commandmode = false;	memset(&telClient, 0, sizeof(telClient));	connected = true;	ringing = false;	CSerial::setCD(true);	CSerial::setRI(false);}void CSerialModem::DoCommand() {	cmdbuf[cmdpos] = 0;	cmdpos = 0;			//Reset for next command	upcase(cmdbuf);	LOG_MSG("Command sent to modem: ->%s<-\n", cmdbuf);		/* Check for empty line, stops dialing and autoanswer */		if (!cmdbuf[0]) {			reg[0]=0;	// autoanswer off			return;		//	} 		//else {				//MIXER_Enable(mhd.chan,false);		//		dialing = false;		//		SendRes(ResNOCARRIER);		//		goto ret_none;		//	}		}		/* AT command set interpretation */		if ((cmdbuf[0] != 'A') || (cmdbuf[1] != 'T')) {			SendRes(ResERROR);			return;		}				if (strstr(cmdbuf,"NET0")) {			telnetmode = false;			SendRes(ResOK);			return;		}		else if (strstr(cmdbuf,"NET1")) {			telnetmode = true;			SendRes(ResOK);			return;		}				/* Check for dial command */		if(strncmp(cmdbuf,"ATD3",3)==0) {			char * foundstr=&cmdbuf[3];			if (*foundstr=='T' || *foundstr=='P') foundstr++;			/* Small protection against empty line */			if (!foundstr[0]) {				SendRes(ResERROR);				return;			}			char* helper;			// scan for and remove spaces; weird bug: with leading spaces in the string,			// SDLNet_ResolveHost will return no error but not work anyway (win)			while(foundstr[0]==' ') foundstr++;			helper=foundstr;			helper+=strlen(foundstr);			while(helper[0]==' ') {				helper[0]=0;				helper--;			}			if (strlen(foundstr) >= 12) {					// Check if supplied parameter only consists of digits					bool isNum = true;				for (Bitu i=0; i<strlen(foundstr); i++)						if (foundstr[i] < '0' || foundstr[i] > '9')							isNum = false;				if (isNum) {					// Parameter is a number with at least 12 digits => this cannot be a valid IP/name					// Transform by adding dots					char buffer[128];					Bitu j = 0;					for (Bitu i=0; i<strlen(foundstr); i++) {							buffer[j++] = foundstr[i];							// Add a dot after the third, sixth and ninth number							if (i == 2 || i == 5 || i == 8)								buffer[j++] = '.';							// If the string is longer than 12 digits, interpret the rest as port							if (i == 11 && strlen(foundstr)>12)								buffer[j++] = ':';						}						buffer[j] = 0;						foundstr = buffer;					}				}			Dial(foundstr);			return;		}		char * scanbuf;		scanbuf=&cmdbuf[2];		char chr;		Bitu num;		while (chr=*scanbuf++) {			switch (chr) {			case 'I':	//Some strings about firmware				switch (num=ScanNumber(scanbuf)) {				case 3:SendLine("DosBox Emulated Modem Firmware V1.00");break;				case 4:SendLine("Modem compiled for DosBox version " VERSION);break;				};break;			case 'E':	//Echo on/off				switch (num=ScanNumber(scanbuf)) {				case 0:echo = false;break;				case 1:echo = true;break;				};break;			case 'V':				switch (num=ScanNumber(scanbuf)) {				case 0:numericresponse = true;break;				case 1:numericresponse = false;break;				};break;			case 'H':	//Hang up				switch (num=ScanNumber(scanbuf)) {				case 0:					if (connected) {						SendRes(ResNOCARRIER);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -