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(); }
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; }
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)); }
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; }
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) }
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); } }
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; }
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]; } }
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); } }