bool CNullModem::ServerConnect() { // check if a connection is available. clientsocket=serversocket->Accept(); if (!clientsocket) return false; Bit8u peeripbuf[16]; clientsocket->GetRemoteAddressString(peeripbuf); LOG_MSG("Serial%d: A client (%s) has connected.",(int)COMNUMBER,peeripbuf); #if SERIAL_DEBUG log_ser(dbg_aux,"Nullmodem: A client (%s) has connected.", peeripbuf); #endif /* FIXME: It would be nice if the SDL net library had a bind() call to bind only to a specific interface. * Or maybe it does... what am I missing? */ if (!nonlocal && strcmp((char*)peeripbuf,"127.0.0.1") != 0) { LOG_MSG("Serial%d: Non-localhost client (%s) dropped by nonlocal:0 policy. To accept connections from network, set nonlocal:1",(int)COMNUMBER,peeripbuf); delete clientsocket; clientsocket = NULL; return false; } clientsocket->SetSendBufferSize(256); rx_state=N_RX_IDLE; setEvent(SERIAL_POLLING_EVENT, 1); // we don't accept further connections delete serversocket; serversocket=0; // transmit the line status setRTSDTR(getRTS(), getDTR()); if (transparent) setCD(true); return true; }
void CSerialDummy::setDTR(bool val) { #ifdef CHECKIT_TESTPLUG setDSR(val); setRI(val); setCD(val); #endif }
void CDirectSerial::updateMSR () { int new_status = SERIAL_getmodemstatus(comport); setCTS(new_status&SERIAL_CTS? true:false); setDSR(new_status&SERIAL_DSR? true:false); setRI(new_status&SERIAL_RI? true:false); setCD(new_status&SERIAL_CD? true:false); }
CSerialDummy::CSerialDummy(Bitu id, CommandLine* cmd):CSerial(id, cmd) { CSerial::Init_Registers(); setRI(false); setDSR(false); setCD(false); setCTS(false); InstallationSuccessful=true; }
CSerialLog::CSerialLog(Bitu id, CommandLine* cmd):CSerial(id, cmd) { CSerial::Init_Registers(); // DSR+CTS on to make sure the DOS COM device will not get stuck waiting for them setRI(false); setCD(false); setDSR(true); setCTS(true); InstallationSuccessful=true; }
bool CNullModem::ServerListen() { // Start the server listen port. serversocket = new TCPServerSocket(serverport); if (!serversocket->isopen) return false; LOG_MSG("Serial%d: Nullmodem server waiting for connection on port %d...", COMNUMBER,serverport); setEvent(SERIAL_SERVER_POLLING_EVENT, 50); setCD(false); return true; }
bool CNullModem::ClientConnect(TCPClientSocket* newsocket) { Bit8u peernamebuf[16]; clientsocket = newsocket; if (!clientsocket->isopen) { LOG_MSG("Serial%d: Connection failed.",COMNUMBER); delete clientsocket; clientsocket=0; setCD(false); return false; } clientsocket->SetSendBufferSize(256); clientsocket->GetRemoteAddressString(peernamebuf); // transmit the line status if (!transparent) setRTSDTR(getRTS(), getDTR()); rx_state=N_RX_IDLE; LOG_MSG("Serial%d: Connected to %s",COMNUMBER,peernamebuf); setEvent(SERIAL_POLLING_EVENT, 1); setCD(true); return true; }
void CDirectSerial::updateMSR () { DWORD dptr = 0; if (!GetCommModemStatus (hCom, &dptr)) { #ifdef SERIALPORT_DEBUGMSG // LOG_MSG ("Serial port at %x: GetCommModemStatus failed!", base); #endif //return; } setCTS((dptr & MS_CTS_ON)!=0); setDSR((dptr & MS_DSR_ON)!=0); setRI ((dptr & MS_RING_ON)!=0); setCD((dptr & MS_RLSD_ON)!=0); }
void CNullModem::Disconnect() { removeEvent(SERIAL_POLLING_EVENT); removeEvent(SERIAL_RX_EVENT); // it was disconnected; free the socket and restart the server socket LOG_MSG("Serial%d: Disconnected.",COMNUMBER); delete clientsocket; clientsocket=0; setDSR(false); setCTS(false); setCD(false); if (serverport) { serversocket = new TCPServerSocket(serverport); if (serversocket->isopen) setEvent(SERIAL_SERVER_POLLING_EVENT, 50); else delete serversocket; } else if (dtrrespect) { setEvent(SERIAL_NULLMODEM_DTR_EVENT,50); DTR_delta = getDTR(); // try to reconnect the next time DTR is set } }
bool CNullModem::ServerConnect() { // check if a connection is available. clientsocket=serversocket->Accept(); if (!clientsocket) return false; Bit8u peeripbuf[16]; clientsocket->GetRemoteAddressString(peeripbuf); LOG_MSG("Serial%d: A client (%s) has connected.",COMNUMBER,peeripbuf); #if SERIAL_DEBUG log_ser(dbg_aux,"Nullmodem: A client (%s) has connected.", peeripbuf); #endif clientsocket->SetSendBufferSize(256); rx_state=N_RX_IDLE; setEvent(SERIAL_POLLING_EVENT, 1); // we don't accept further connections delete serversocket; serversocket=0; // transmit the line status setRTSDTR(getRTS(), getDTR()); if (transparent) setCD(true); return true; }
bool ResourceManager::init() { uint32 i, j; // Until proven differently, assume we're on CD 1. This is so the start // dialog will be able to play any music at all. setCD(1); // We read in the resource info which tells us the names of the // resource cluster files ultimately, although there might be groups // within the clusters at this point it makes no difference. We only // wish to know what resource files there are and what is in each Common::File file; if (!file.open("resource.inf")) { GUIErrorMessage("Broken Sword II: Cannot open resource.inf"); return false; } // The resource.inf file is a simple text file containing the names of // all the resource files. while (1) { char *buf = _resFiles[_totalClusters].fileName; uint len = sizeof(_resFiles[_totalClusters].fileName); if (!file.readLine(buf, len)) break; int pos = strlen(buf); if (buf[pos - 1] == 0x0A) buf[pos - 1] = 0; _resFiles[_totalClusters].numEntries = -1; _resFiles[_totalClusters].entryTab = NULL; if (++_totalClusters >= MAX_res_files) { GUIErrorMessage("Broken Sword II: Too many entries in resource.inf"); return false; } } file.close(); // Now load in the binary id to res conversion table if (!file.open("resource.tab")) { GUIErrorMessage("Broken Sword II: Cannot open resource.tab"); return false; } // Find how many resources uint32 size = file.size(); _totalResFiles = size / 4; // Table seems ok so malloc some space _resConvTable = (uint16 *)malloc(size); for (i = 0; i < size / 2; i++) _resConvTable[i] = file.readUint16LE(); if (file.eos() || file.err()) { file.close(); GUIErrorMessage("Broken Sword II: Cannot read resource.tab"); return false; } file.close(); // Check that we have cd.inf file, unless we are running PSX // version, which has all files on one disc. if (!file.open("cd.inf") && !Sword2Engine::isPsx()) { GUIErrorMessage("Broken Sword II: Cannot open cd.inf"); return false; } CdInf *cdInf = new CdInf[_totalClusters]; for (i = 0; i < _totalClusters; i++) { if (Sword2Engine::isPsx()) { // We are running PSX version, artificially fill CdInf structure cdInf[i].cd = CD1; } else { // We are running PC version, read cd.inf file file.read(cdInf[i].clusterName, sizeof(cdInf[i].clusterName)); cdInf[i].cd = file.readByte(); if (file.eos() || file.err()) { delete[] cdInf; file.close(); GUIErrorMessage("Broken Sword II: Cannot read cd.inf"); return false; } } // It has been reported that there are two different versions // of the cd.inf file: One where all clusters on CD also have // the LOCAL_CACHE bit set. This bit is no longer used. To // avoid future problems, let's normalize the flag once and for // all here. if (cdInf[i].cd & LOCAL_PERM) cdInf[i].cd = 0; else if (cdInf[i].cd & CD1) cdInf[i].cd = 1; else if (cdInf[i].cd & CD2) cdInf[i].cd = 2; else cdInf[i].cd = 0; // Any file on "CD 0" may be needed at all times. Verify that // it exists. Any other missing cluster will be requested with // an "insert CD" message. Of course, the file may still vanish // during game-play (oh, that wascally wabbit!) in which case // the resource manager will print a fatal error. if (cdInf[i].cd == 0 && !Common::File::exists((char *)cdInf[i].clusterName)) { GUIErrorMessage("Broken Sword II: Cannot find " + Common::String((char *)cdInf[i].clusterName)); delete[] cdInf; return false; } } file.close(); // We check the presence of resource files in cd.inf // This is ok in PC version, but in PSX version we don't // have cd.inf so we'll have to skip this. if (!Sword2Engine::isPsx()) { for (i = 0; i < _totalClusters; i++) { for (j = 0; j < _totalClusters; j++) { if (scumm_stricmp((char *)cdInf[j].clusterName, _resFiles[i].fileName) == 0) break; } if (j == _totalClusters) { delete[] cdInf; GUIErrorMessage(Common::String(_resFiles[i].fileName) + " is not in cd.inf"); return false; } _resFiles[i].cd = cdInf[j].cd; } } delete[] cdInf; debug(1, "%d resources in %d cluster files", _totalResFiles, _totalClusters); for (i = 0; i < _totalClusters; i++) debug(2, "filename of cluster %d: -%s (%d)", i, _resFiles[i].fileName, _resFiles[i].cd); _resList = (Resource *)malloc(_totalResFiles * sizeof(Resource)); for (i = 0; i < _totalResFiles; i++) { _resList[i].ptr = NULL; _resList[i].size = 0; _resList[i].refCount = 0; _resList[i].prev = _resList[i].next = NULL; } return true; }
/** * Returns the address of a resource. Loads if not in memory. Retains a count. */ byte *ResourceManager::openResource(uint32 res, bool dump) { assert(res < _totalResFiles); // FIXME: In PSX edition, not all top menu icons are present (TOP menu is not used). // Though, at present state, the engine still ask for the resources. if (Sword2Engine::isPsx()) { // We need to "rewire" missing icons if (res == 342) res = 364; // Rewire RESTORE ICON to SAVE ICON } // Is the resource in memory already? If not, load it. if (!_resList[res].ptr) { // Fetch the correct file and read in the correct portion. uint16 cluFileNum = _resConvTable[res * 2]; // points to the number of the ascii filename assert(cluFileNum != 0xffff); // Relative resource within the file // First we have to find the file via the _resConvTable uint16 actual_res = _resConvTable[(res * 2) + 1]; debug(5, "openResource %s res %d", _resFiles[cluFileNum].fileName, res); // If we're loading a cluster that's only available from one // of the CDs, remember which one so that we can play the // correct speech and music. if (Sword2Engine::isPsx()) // We have only one disk in PSX version setCD(CD1); else setCD(_resFiles[cluFileNum].cd); // Actually, as long as the file can be found we don't really // care which CD it's on. But if we can't find it, keep asking // for the CD until we do. Common::File *file = openCluFile(cluFileNum); if (_resFiles[cluFileNum].entryTab == NULL) { // we didn't read from this file before, get its index table readCluIndex(cluFileNum, file); } assert(_resFiles[cluFileNum].entryTab); uint32 pos = _resFiles[cluFileNum].entryTab[actual_res * 2 + 0]; uint32 len = _resFiles[cluFileNum].entryTab[actual_res * 2 + 1]; file->seek(pos, SEEK_SET); debug(6, "res len %d", len); // Ok, we know the length so try and allocate the memory. _resList[res].ptr = _vm->_memory->memAlloc(len, res); _resList[res].size = len; _resList[res].refCount = 0; file->read(_resList[res].ptr, len); debug(3, "Loaded resource '%s' (%d) from '%s' on CD %d (%d)", fetchName(_resList[res].ptr), res, _resFiles[cluFileNum].fileName, getCD(), _resFiles[cluFileNum].cd); if (dump) { char buf[256]; const char *tag; switch (fetchType(_resList[res].ptr)) { case ANIMATION_FILE: tag = "anim"; break; case SCREEN_FILE: tag = "layer"; break; case GAME_OBJECT: tag = "object"; break; case WALK_GRID_FILE: tag = "walkgrid"; break; case GLOBAL_VAR_FILE: tag = "globals"; break; case PARALLAX_FILE_null: tag = "parallax"; // Not used! break; case RUN_LIST: tag = "runlist"; break; case TEXT_FILE: tag = "text"; break; case SCREEN_MANAGER: tag = "screen"; break; case MOUSE_FILE: tag = "mouse"; break; case WAV_FILE: tag = "wav"; break; case ICON_FILE: tag = "icon"; break; case PALETTE_FILE: tag = "palette"; break; default: tag = "unknown"; break; } sprintf(buf, "dumps/%s-%d.dmp", tag, res); if (!Common::File::exists(buf)) { Common::DumpFile out; if (out.open(buf)) out.write(_resList[res].ptr, len); } } // close the cluster file->close(); delete file; _usedMem += len; checkMemUsage(); } else if (_resList[res].refCount == 0) removeFromCacheList(_resList + res); _resList[res].refCount++; return _resList[res].ptr; }
void CSerialLog::setDTR(bool val) { setDSR(val); setRI(val); setCD(val); }
CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) { Bitu temptcpport=23; memset(&telClient, 0, sizeof(telClient)); InstallationSuccessful = false; serversocket = 0; clientsocket = 0; serverport = 0; clientport = 0; rx_retry = 0; rx_retry_max = 20; rx_state=N_RX_DISC; tx_gather = 12; dtrrespect=false; tx_block=false; receiveblock=false; transparent=false; telnet=false; Bitu bool_temp=0; // usedtr: The nullmodem will // 1) when it is client connect to the server not immediately but // as soon as a modem-aware application is started (DTR is switched on). // 2) only receive data when DTR is on. if (getBituSubstring("usedtr:", &bool_temp, cmd)) { if (bool_temp==1) { dtrrespect=true; transparent=true; DTR_delta=false; // connect immediately when DTR is already 1 } } // transparent: don't add additional handshake control. if (getBituSubstring("transparent:", &bool_temp, cmd)) { if (bool_temp==1) transparent=true; else transparent=false; } // telnet: interpret telnet commands. if (getBituSubstring("telnet:", &bool_temp, cmd)) { if (bool_temp==1) { transparent=true; telnet=true; } } // rxdelay: How many milliseconds to wait before causing an // overflow when the application is unresponsive. if (getBituSubstring("rxdelay:", &rx_retry_max, cmd)) { if (!(rx_retry_max<=10000)) { rx_retry_max=50; } } // txdelay: How many milliseconds to wait before sending data. // This reduces network overhead quite a lot. if (getBituSubstring("txdelay:", &tx_gather, cmd)) { if (!(tx_gather<=500)) { tx_gather=12; } } // port is for both server and client if (getBituSubstring("port:", &temptcpport, cmd)) { if (!(temptcpport>0&&temptcpport<65536)) { temptcpport=23; } } // socket inheritance (client-alike) if (getBituSubstring("inhsocket:", &bool_temp, cmd)) { #ifdef NATIVESOCKETS if (Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) { if (bool_temp==1) { int sock; if (control->cmdline->FindInt("-socket",sock,true)) { dtrrespect=false; transparent=true; LOG_MSG("Inheritance socket handle: %d",sock); if (!ClientConnect(new TCPClientSocket(sock))) return; } else { LOG_MSG("Serial%d: -socket parameter missing.",COMNUMBER); return; } } } else { LOG_MSG("Serial%d: socket inheritance not supported on this platform.", COMNUMBER); return; } #else LOG_MSG("Serial%d: socket inheritance not available.", COMNUMBER); #endif } else { // normal server/client std::string tmpstring; if (cmd->FindStringBegin("server:",tmpstring,false)) { // we are a client const char* hostnamechar=tmpstring.c_str(); size_t hostlen=strlen(hostnamechar)+1; if (hostlen>sizeof(hostnamebuffer)) { hostlen=sizeof(hostnamebuffer); hostnamebuffer[sizeof(hostnamebuffer)-1]=0; } memcpy(hostnamebuffer,hostnamechar,hostlen); clientport=(Bit16u)temptcpport; if (dtrrespect) { // we connect as soon as DTR is switched on setEvent(SERIAL_NULLMODEM_DTR_EVENT, 50); LOG_MSG("Serial%d: Waiting for DTR...",COMNUMBER); } else if (!ClientConnect( new TCPClientSocket((char*)hostnamebuffer,(Bit16u)clientport))) return; } else { // we are a server serverport = (Bit16u)temptcpport; if (!ServerListen()) return; } } CSerial::Init_Registers(); InstallationSuccessful = true; setCTS(dtrrespect||transparent); setDSR(dtrrespect||transparent); setRI(false); setCD(clientsocket > 0); // CD on if connection established }