Ejemplo n.º 1
0
	JOYSTICK(Section* configuration):Module_base(configuration){
		Section_prop * section=static_cast<Section_prop *>(configuration);
		const char * type=section->Get_string("joysticktype");
		if (!strcasecmp(type,"none"))       joytype = JOY_NONE;
		else if (!strcasecmp(type,"false")) joytype = JOY_NONE;
		else if (!strcasecmp(type,"auto"))  joytype = JOY_AUTO;
		else if (!strcasecmp(type,"2axis")) joytype = JOY_2AXIS;
		else if (!strcasecmp(type,"4axis")) joytype = JOY_4AXIS;
		else if (!strcasecmp(type,"4axis_2")) joytype = JOY_4AXIS_2;
		else if (!strcasecmp(type,"fcs"))   joytype = JOY_FCS;
		else if (!strcasecmp(type,"ch"))    joytype = JOY_CH;
		else joytype = JOY_AUTO;

		bool timed = section->Get_bool("timed");
		if(timed) {
			ReadHandler.Install(0x201,read_p201_timed,IO_MB);
			WriteHandler.Install(0x201,write_p201_timed,IO_MB);
		} else {
			ReadHandler.Install(0x201,read_p201,IO_MB);
			WriteHandler.Install(0x201,write_p201,IO_MB);
		}
		autofire = section->Get_bool("autofire");
		swap34 = section->Get_bool("swap34");
		button_wrapping_enabled = section->Get_bool("buttonwrap");
		stick[0].enabled = false;
		stick[1].enabled = false;
		stick[0].xtick = stick[0].ytick = stick[1].xtick =
		                 stick[1].ytick = PIC_FullIndex();
	}
Ejemplo n.º 2
0
Bitu read_herc_status(Bitu port,Bitu iolen) {
	// 3BAh (R):  Status Register
	// bit   0  Horizontal sync
	//       1  Light pen status (only some cards)
	//       3  Video signal
	//     4-6	000: Hercules
	//			001: Hercules Plus
	//			101: Hercules InColor
	//			111: Unknown clone
	//       7  Vertical sync inverted

	double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart;
	Bit8u retval=0x72; // Hercules ident; from a working card (Winbond W86855AF)
					// Another known working card has 0x76 ("KeysoGood", full-length)
	if (timeInFrame < vga.draw.delay.vrstart ||
		timeInFrame > vga.draw.delay.vrend) retval |= 0x80;

	double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal);
	if (timeInLine >= vga.draw.delay.hrstart &&
		timeInLine <= vga.draw.delay.hrend) retval |= 0x1;

	// 688 Attack sub checks bit 3 - as a workaround have the bit enabled
	// if no sync active (corresponds to a completely white screen)
	if ((retval&0x81)==0x80) retval |= 0x8;
	return retval;
}
Ejemplo n.º 3
0
void JOYSTICK_Init() {
	LOG(LOG_MISC,LOG_DEBUG)("Initializing joystick emulation");

	/* NTS: Joystick emulation does not work if we init joystick type AFTER mapper init.
	 *      We cannot wait for poweron/reset signal for determination of joystick type.
	 *      But, I/O port setup can happen later. */
	{
		Section_prop * section=static_cast<Section_prop *>(control->GetSection("joystick"));

		const char * type=section->Get_string("joysticktype");
		if (!strcasecmp(type,"none"))       joytype = JOY_NONE;
		else if (!strcasecmp(type,"false")) joytype = JOY_NONE;
		else if (!strcasecmp(type,"auto"))  joytype = JOY_AUTO;
		else if (!strcasecmp(type,"2axis")) joytype = JOY_2AXIS;
		else if (!strcasecmp(type,"4axis")) joytype = JOY_4AXIS;
		else if (!strcasecmp(type,"4axis_2")) joytype = JOY_4AXIS_2;
		else if (!strcasecmp(type,"fcs"))   joytype = JOY_FCS;
		else if (!strcasecmp(type,"ch"))    joytype = JOY_CH;
		else joytype = JOY_AUTO;

		autofire = section->Get_bool("autofire");
		swap34 = section->Get_bool("swap34");
		button_wrapping_enabled = section->Get_bool("buttonwrap");
		stick[0].enabled = false;
		stick[1].enabled = false;
		stick[0].xtick = stick[0].ytick = stick[1].xtick =
		                 stick[1].ytick = PIC_FullIndex();
	}

	AddExitFunction(AddExitFunctionFuncPair(JOYSTICK_Destroy),true); 
	AddVMEventFunction(VM_EVENT_POWERON,AddVMEventFunctionFuncPair(JOYSTICK_OnPowerOn));
}
Ejemplo n.º 4
0
static Bitu read_p61(Bitu, Bitu) {
	unsigned char dbg;
	dbg = ((port_61_data & 0xF) |
		(TIMER_GetOutput2()? 0x20:0) |
		((fmod(PIC_FullIndex(),0.030) > 0.015)? 0x10:0));
	return dbg;
}
Ejemplo n.º 5
0
static void cmos_checktimer(void) {
	PIC_RemoveEvents(cmos_timerevent);	
	if (cmos.timer.div<=2) cmos.timer.div+=7;
	cmos.timer.delay=(1000.0f/(32768.0f / (1 << (cmos.timer.div - 1))));
	if (!cmos.timer.div || !cmos.timer.enabled) return;
	LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %.2f hz",1000.0/cmos.timer.delay);
//	PIC_AddEvent(cmos_timerevent,cmos.timer.delay);
	/* A rtc is always running */
	double remd=fmod(PIC_FullIndex(),(double)cmos.timer.delay);
	PIC_AddEvent(cmos_timerevent,(float)((double)cmos.timer.delay-remd)); //Should be more like a real pc. Check
//	status reg A reading with this (and with other delays actually)
}
Ejemplo n.º 6
0
static void write_p201_timed(Bitu port,Bitu val,Bitu iolen) {
	// Store writetime index
	// Axes take time = 24.2 microseconds + ( 0.011 microsecons/ohm * resistance )
	// to reset to 0
	// Precalculate the time at which each axis hits 0 here
	double currentTick = PIC_FullIndex();
	if (stick[0].enabled) {
		stick[0].xtick = currentTick + 1000.0*( JOY_S_CONSTANT + S_PER_OHM *
	                         (double)(((stick[0].xpos+1.0)* OHMS)) );
		stick[0].ytick = currentTick + 1000.0*( JOY_S_CONSTANT + S_PER_OHM *
		                 (double)(((stick[0].ypos+1.0)* OHMS)) );
	}
	if (stick[1].enabled) {
		stick[1].xtick = currentTick + 1000.0*( JOY_S_CONSTANT + S_PER_OHM *
		                 (double)((swap34? stick[1].ypos : stick[1].xpos)+1.0) * OHMS);
		stick[1].ytick = currentTick + 1000.0*( JOY_S_CONSTANT + S_PER_OHM *
		                 (double)((swap34? stick[1].xpos : stick[1].ypos)+1.0) * OHMS);
	}
}
Ejemplo n.º 7
0
static Bitu read_p201_timed(Bitu port,Bitu iolen) {
	Bit8u ret=0xff;
	double currentTick = PIC_FullIndex();
	if( stick[0].enabled ){
		if( stick[0].xtick < currentTick ) ret &=~1;
		if( stick[0].ytick < currentTick ) ret &=~2;
	}
	if( stick[1].enabled ){
		if( stick[1].xtick < currentTick ) ret &=~4;
		if( stick[1].ytick < currentTick ) ret &=~8;
	}

	if (stick[0].enabled) {
		if (stick[0].button[0]) ret&=~16;
		if (stick[0].button[1]) ret&=~32;
	}
	if (stick[1].enabled) {
		if (stick[1].button[0]) ret&=~64;
		if (stick[1].button[1]) ret&=~128;
	}
	return ret;
}
Ejemplo n.º 8
0
static Bitu cmos_readreg(Bitu port,Bitu iolen) {
	if (cmos.reg>0x3f) {
		LOG(LOG_BIOS,LOG_ERROR)("CMOS:Read from illegal register %x",cmos.reg);
		return 0xff;
	}
	Bitu drive_a, drive_b;
	Bit8u hdparm;
	time_t curtime;
	struct tm *loctime;
	/* Get the current time. */
	curtime = time (NULL);

	/* Convert it to local time representation. */
	loctime = localtime (&curtime);

	switch (cmos.reg) {
	case 0x00:		/* Seconds */
		return 	MAKE_RETURN(loctime->tm_sec);
	case 0x02:		/* Minutes */
		return 	MAKE_RETURN(loctime->tm_min);
	case 0x04:		/* Hours */
		return 	MAKE_RETURN(loctime->tm_hour);
	case 0x06:		/* Day of week */
		return 	MAKE_RETURN(loctime->tm_wday + 1);
	case 0x07:		/* Date of month */
		return 	MAKE_RETURN(loctime->tm_mday);
	case 0x08:		/* Month */
		return 	MAKE_RETURN(loctime->tm_mon + 1);
	case 0x09:		/* Year */
		return 	MAKE_RETURN(loctime->tm_year % 100);
	case 0x32:		/* Century */
		return 	MAKE_RETURN(loctime->tm_year / 100 + 19);
	case 0x01:		/* Seconds Alarm */
	case 0x03:		/* Minutes Alarm */
	case 0x05:		/* Hours Alarm */
		return cmos.regs[cmos.reg];
	case 0x0a:		/* Status register A */
		if (PIC_TickIndex()<0.002) {
			return (cmos.regs[0x0a]&0x7f) | 0x80;
		} else {
			return (cmos.regs[0x0a]&0x7f);
		}
	case 0x0c:		/* Status register C */
		if (cmos.timer.enabled) {
			/* In periodic interrupt mode only care for those flags */
			Bit8u val=cmos.regs[0xc];
			cmos.regs[0xc]=0;
			return val;
		} else {
			/* Give correct values at certain times */
			Bit8u val=0;
			double index=PIC_FullIndex();
			if (index>=(cmos.last.timer+cmos.timer.delay)) {
				cmos.last.timer=index;
				val|=0x40;
			} 
			if (index>=(cmos.last.ended+1000)) {
				cmos.last.ended=index;
				val|=0x10;
			} 
			return val;
		}
	case 0x10:		/* Floppy size */
		drive_a = 0;
		drive_b = 0;
		if(imageDiskList[0] != NULL) drive_a = imageDiskList[0]->GetBiosType();
		if(imageDiskList[1] != NULL) drive_b = imageDiskList[1]->GetBiosType();
		return ((drive_a << 4) | (drive_b));
	/* First harddrive info */
	case 0x12:
		hdparm = 0;
		if(imageDiskList[2] != NULL) hdparm |= 0xf;
		if(imageDiskList[3] != NULL) hdparm |= 0xf0;
		return hdparm;
	case 0x19:
		if(imageDiskList[2] != NULL) return 47; /* User defined type */
		return 0;
	case 0x1b:
		if(imageDiskList[2] != NULL) return (imageDiskList[2]->cylinders & 0xff);
		return 0;
	case 0x1c:
		if(imageDiskList[2] != NULL) return ((imageDiskList[2]->cylinders & 0xff00)>>8);
		return 0;
	case 0x1d:
		if(imageDiskList[2] != NULL) return (imageDiskList[2]->heads);
		return 0;
	case 0x1e:
		if(imageDiskList[2] != NULL) return 0xff;
		return 0;
	case 0x1f:
		if(imageDiskList[2] != NULL) return 0xff;
		return 0;
	case 0x20:
		if(imageDiskList[2] != NULL) return (0xc0 | (((imageDiskList[2]->heads) > 8) << 3));
		return 0;
	case 0x21:
		if(imageDiskList[2] != NULL) return (imageDiskList[2]->cylinders & 0xff);
		return 0;
	case 0x22:
		if(imageDiskList[2] != NULL) return ((imageDiskList[2]->cylinders & 0xff00)>>8);
		return 0;
	case 0x23:
		if(imageDiskList[2] != NULL) return (imageDiskList[2]->sectors);
		return 0;
	/* Second harddrive info */
	case 0x1a:
		if(imageDiskList[3] != NULL) return 47; /* User defined type */
		return 0;
	case 0x24:
		if(imageDiskList[3] != NULL) return (imageDiskList[3]->cylinders & 0xff);
		return 0;
	case 0x25:
		if(imageDiskList[3] != NULL) return ((imageDiskList[3]->cylinders & 0xff00)>>8);
		return 0;
	case 0x26:
		if(imageDiskList[3] != NULL) return (imageDiskList[3]->heads);
		return 0;
	case 0x27:
		if(imageDiskList[3] != NULL) return 0xff;
		return 0;
	case 0x28:
		if(imageDiskList[3] != NULL) return 0xff;
		return 0;
	case 0x29:
		if(imageDiskList[3] != NULL) return (0xc0 | (((imageDiskList[3]->heads) > 8) << 3));
		return 0;
	case 0x2a:
		if(imageDiskList[3] != NULL) return (imageDiskList[3]->cylinders & 0xff);
		return 0;
	case 0x2b:
		if(imageDiskList[3] != NULL) return ((imageDiskList[3]->cylinders & 0xff00)>>8);
		return 0;
	case 0x2c:
		if(imageDiskList[3] != NULL) return (imageDiskList[3]->sectors);
		return 0;
	case 0x39:
		return 0;
	case 0x3a:
		return 0;


	case 0x0b:		/* Status register B */
	case 0x0d:		/* Status register D */
	case 0x0f:		/* Shutdown status byte */
	case 0x14:		/* Equipment */
	case 0x15:		/* Base Memory KB Low Byte */
	case 0x16:		/* Base Memory KB High Byte */
	case 0x17:		/* Extended memory in KB Low Byte */
	case 0x18:		/* Extended memory in KB High Byte */
	case 0x30:		/* Extended memory in KB Low Byte */
	case 0x31:		/* Extended memory in KB High Byte */
//		LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %X : %04X",cmos.reg,cmos.regs[cmos.reg]);
		return cmos.regs[cmos.reg];
	default:
		LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %X",cmos.reg);
		return cmos.regs[cmos.reg];
	}
}
Ejemplo n.º 9
0
static void DISNEY_analyze(Bitu channel){
	switch(disney.state) {
		case DS_RUNNING: // should not get here
			break;
		case DS_IDLE:
			// initialize channel data
			for(int i = 0; i < 2; i++) {
				disney.da[i].used = 0;
				disney.da[i].speedcheck_sum = 0;
				disney.da[i].speedcheck_failed = false;
				disney.da[i].speedcheck_init = false;
			}
			disney.da[channel].speedcheck_last = PIC_FullIndex();
			disney.da[channel].speedcheck_init = true;
			
			disney.state = DS_ANALYZING;
			break;

		case DS_FINISH: 
		{
			// detect stereo: if we have about the same data amount in both channels
			Bits st_diff = disney.da[0].used - disney.da[1].used;
			
			// find leader channel (the one with higher rate) [this good for the stereo case?]
			if(disney.da[0].used > disney.da[1].used) {
				//disney.monochannel=0;
				disney.leader = &disney.da[0];
			} else {
				//disney.monochannel=1;
				disney.leader = &disney.da[1];
			}
			
			if((st_diff < 5) && (st_diff > -5)) disney.stereo = true;
			else disney.stereo = false;

			// calculate rate for both channels
			Bitu ch_speed[2];

			for(Bitu i = 0; i < 2; i++) {
				ch_speed[i] = (Bitu)(1.0/((disney.da[i].speedcheck_sum/1000.0) /
				(float)(((float)disney.da[i].used)-1.0))); // -1.75
			}
			
			// choose the larger value
			DISNEY_enable(ch_speed[0] > ch_speed[1]?
				ch_speed[0]:ch_speed[1]); // TODO
			break;
		}
		case DS_ANALYZING:
		{
			double current = PIC_FullIndex();
			dac_channel* cch = &disney.da[channel];

			if(!cch->speedcheck_init) {
				cch->speedcheck_init = true;
				cch->speedcheck_last = current;
				break;
			}
			cch->speedcheck_sum += current - cch->speedcheck_last;
			//LOG_MSG("t=%f",current - cch->speedcheck_last);
			
			// sanity checks (printer...)
			if((current - cch-> speedcheck_last) < 0.01 ||
				(current - cch-> speedcheck_last) > 2)
				cch->speedcheck_failed = true;
			
			// if both are failed we are back at start
			if(disney.da[0].speedcheck_failed && disney.da[1].speedcheck_failed) {
				disney.state=DS_IDLE;
				break;
			}

			cch->speedcheck_last = current;
			
			// analyze finish condition
			if(disney.da[0].used > 30 || disney.da[1].used > 30)
				disney.state = DS_FINISH;
			break;
		}
	}
}
CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd)
					:CSerial (id, cmd) {
	InstallationSuccessful = false;
	hCom = INVALID_HANDLE_VALUE; // else destructor may close an invalid handle
	rx_retry = 0;
    rx_retry_max = 0;

	// open the port in NT object space (recommended by Microsoft)
	// allows the user to open COM10+ and custom port names.
	std::string prefix="\\\\.\\";
	std::string tmpstring;
	if(!cmd->FindStringBegin("realport:",tmpstring,false)) return;

#if SERIAL_DEBUG
		if(dbg_modemcontrol)
			fprintf(debugfp,"%12.3f Port type directserial realport %s\r\n",
				PIC_FullIndex(),tmpstring.c_str());
#endif

	prefix.append(tmpstring);

	// 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=0;
		}
	}

	const char* tmpchar=prefix.c_str();

	LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpstring.c_str());
	hCom = CreateFile (tmpchar,
					   GENERIC_READ | GENERIC_WRITE, 0,
									  // must be opened with exclusive-access
	                   NULL,          // no security attributes
	                   OPEN_EXISTING, // must use OPEN_EXISTING
	                   0,             // non overlapped I/O
	                   NULL           // hTemplate must be NULL for comm devices
	                  );

	if (hCom == INVALID_HANDLE_VALUE) {
		int error = GetLastError ();
		LOG_MSG ("Serial%d: Serial Port \"%s\" could not be opened.",
			COMNUMBER, tmpstring.c_str());
		if (error == 2) {
			LOG_MSG ("The specified port does not exist.");
		} else if (error == 5) {
			LOG_MSG ("The specified port is already in use.");
		} else {
			LOG_MSG ("Windows error %d occurred.", error);
		}
		return;
	}

	dcb.DCBlength=sizeof(dcb);
	fSuccess = GetCommState (hCom, &dcb);

	if (!fSuccess) {
		// Handle the error.
		LOG_MSG ("GetCommState failed with error %d.\n", (int)GetLastError ());
		hCom = INVALID_HANDLE_VALUE;
		return;
	}

	// initialize the port
	dcb.BaudRate=CBR_9600;
	dcb.fBinary=true;
	dcb.fParity=true;
	dcb.fOutxCtsFlow=false;
	dcb.fOutxDsrFlow=false;
	dcb.fDtrControl=DTR_CONTROL_DISABLE;
	dcb.fDsrSensitivity=false;
	
	dcb.fOutX=false;
	dcb.fInX=false;
	dcb.fErrorChar=0;
	dcb.fNull=false;
	dcb.fRtsControl=RTS_CONTROL_DISABLE;
	dcb.fAbortOnError=false;

	dcb.ByteSize=8;
	dcb.Parity=NOPARITY;
	dcb.StopBits=ONESTOPBIT;

	fSuccess = SetCommState (hCom, &dcb);

	if (!fSuccess) {
		// Handle the error.
		LOG_MSG ("SetCommState failed with error %d.\n", (int)GetLastError ());
		hCom = INVALID_HANDLE_VALUE;
		return;
	}

	// Configure timeouts to effectively use polling
	COMMTIMEOUTS ct;
	ct.ReadIntervalTimeout = MAXDWORD;
	ct.ReadTotalTimeoutConstant = 0;
	ct.ReadTotalTimeoutMultiplier = 0;
	ct.WriteTotalTimeoutConstant = 0;
	ct.WriteTotalTimeoutMultiplier = 0;
	SetCommTimeouts (hCom, &ct);

	CSerial::Init_Registers();
	InstallationSuccessful = true;
	receiveblock=false;

	ClearCommBreak (hCom);
	setEvent(SERIAL_POLLING_EVENT, 1); // millisecond tick
}
void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) {
	Bit8u parity = 0;
	Bit8u bytelength = 0;

	// baud
	if (divider == 0x1)
		dcb.BaudRate = CBR_115200;
	else if (divider == 0x2)
		dcb.BaudRate = CBR_57600;
	else if (divider == 0x3)
		dcb.BaudRate = CBR_38400;
	else if (divider == 0x6)
		dcb.BaudRate = CBR_19200;
	else if (divider == 0xc)
		dcb.BaudRate = CBR_9600;
	else if (divider == 0x18)
		dcb.BaudRate = CBR_4800;
	else if (divider == 0x30)
		dcb.BaudRate = CBR_2400;
	else if (divider == 0x60)
		dcb.BaudRate = CBR_1200;
	else if (divider == 0xc0)
		dcb.BaudRate = CBR_600;
	else if (divider == 0x180)
		dcb.BaudRate = CBR_300;
	else if (divider == 0x417)
		dcb.BaudRate = CBR_110;

	// I read that windows can handle nonstandard baudrates:
	else
		dcb.BaudRate = 115200 / divider;

	// byte length
	bytelength = lcr & 0x3;
	bytelength += 5;
	dcb.ByteSize = bytelength;

	// parity
	parity = lcr & 0x38;
	parity = parity >> 3;
	switch (parity) {
	case 0x1:
			dcb.Parity = ODDPARITY;
			break;
	case 0x3:
			dcb.Parity = EVENPARITY;
			break;
	case 0x5:
			dcb.Parity = MARKPARITY;
			break;
	case 0x7:
			dcb.Parity = SPACEPARITY;
			break;
	default:
			dcb.Parity = NOPARITY;
			break;
	}

	// stopbits
	if (lcr & 0x4) {
		if (bytelength == 5)
			dcb.StopBits = ONE5STOPBITS;
		else
			dcb.StopBits = TWOSTOPBITS;
	} else {
		dcb.StopBits = ONESTOPBIT;
	}

#ifdef SERIALPORT_DEBUGMSG
	LOG_MSG ("__________________________");
	LOG_MSG ("Serial%d: new baud rate: %d", COMNUMBER, dcb.BaudRate);
	LOG_MSG ("Serial%d: new bytelen: %d", COMNUMBER, dcb.ByteSize);
	LOG_MSG ("Serial%d: new parity: %d", COMNUMBER, dcb.Parity);
	LOG_MSG ("Serial%d: new stopbits: %d", COMNUMBER, dcb.StopBits);
#endif

	if (!SetCommState (hCom, &dcb)) {

#if SERIAL_DEBUG
		if(dbg_modemcontrol)
			fprintf(debugfp,"%12.3f serial mode not supported: rate=%d,LCR=%x.\r\n",
			PIC_FullIndex(),dcb.BaudRate,lcr);
#endif

		LOG_MSG ("Serial%d: Desired serial mode not supported (%d,%d,%d,%d",
			(Bit32u)dcb.BaudRate,(Bit32u)dcb.ByteSize,
			(Bit32u)dcb.Parity,(Bit32u)dcb.StopBits, COMNUMBER);
	}
}