コード例 #1
0
ファイル: Sio.c プロジェクト: AlexBu/pcsx
void sioWrite8(unsigned char value) {
#ifdef PAD_LOG
	PAD_LOG("sio write8 %x\n", value);
#endif
	switch (padst) {
		case 1: SIO_INT();
			if ((value&0x40) == 0x40) {
				padst = 2; parp = 1;
				if (!Config.UseNet) {
					switch (CtrlReg&0x2002) {
						case 0x0002:
							buf[parp] = PAD1_poll(value);
							break;
						case 0x2002:
							buf[parp] = PAD2_poll(value);
							break;
					}
				}/* else {
//					SysPrintf("%x: %x, %x, %x, %x\n", CtrlReg&0x2002, buf[2], buf[3], buf[4], buf[5]);
				}*/

				if (!(buf[parp] & 0x0f)) {
					bufcount = 2 + 32;
				} else {
					bufcount = 2 + (buf[parp] & 0x0f) * 2;
				}
				if (buf[parp] == 0x41) {
					switch (value) {
						case 0x43:
							buf[1] = 0x43;
							break;
						case 0x45:
							buf[1] = 0xf3;
							break;
					}
				}
			}
			else padst = 0;
			return;
		case 2:
			parp++;
/*			if (buf[1] == 0x45) {
				buf[parp] = 0;
				SIO_INT();
				return;
			}*/
			if (!Config.UseNet) {
				switch (CtrlReg&0x2002) {
					case 0x0002: buf[parp] = PAD1_poll(value); break;
					case 0x2002: buf[parp] = PAD2_poll(value); break;
				}
			}

			if (parp == bufcount) { padst = 0; return; }
			SIO_INT();
			return;
	}

	switch (mcdst) {
		case 1:
			SIO_INT();
			if (rdwr) { parp++; return; }
			parp = 1;
			switch (value) {
				case 0x52: rdwr = 1; break;
				case 0x57: rdwr = 2; break;
				default: mcdst = 0;
			}
			return;
		case 2: // address H
			SIO_INT();
			adrH = value;
			*buf = 0;
			parp = 0;
			bufcount = 1;
			mcdst = 3;
			return;
		case 3: // address L
			SIO_INT();
			adrL = value;
			*buf = adrH;
			parp = 0;
			bufcount = 1;
			mcdst = 4;
			return;
		case 4:
			SIO_INT();
			parp = 0;
			switch (rdwr) {
				case 1: // read
					buf[0] = 0x5c;
					buf[1] = 0x5d;
					buf[2] = adrH;
					buf[3] = adrL;
					switch (CtrlReg&0x2002) {
						case 0x0002:
							memcpy(&buf[4], Mcd1Data + (adrL | (adrH << 8)) * 128, 128);
							break;
						case 0x2002:
							memcpy(&buf[4], Mcd2Data + (adrL | (adrH << 8)) * 128, 128);
							break;
					}
					{
					char xor = 0;
					int i;
					for (i=2;i<128+4;i++)
						xor^=buf[i];
					buf[132] = xor;
					}
					buf[133] = 0x47;
					bufcount = 133;
					break;
				case 2: // write
					buf[0] = adrL;
					buf[1] = value;
					buf[129] = 0x5c;
					buf[130] = 0x5d;
					buf[131] = 0x47;
					bufcount = 131;
					break;
			}
			mcdst = 5;
			return;
		case 5:	
			parp++;
			if (rdwr == 2) {
				if (parp < 128) buf[parp+1] = value;
			}
			SIO_INT();
			return;
	}

	switch (value) {
		case 0x01: // start pad
			StatReg |= RX_RDY;		// Transfer is Ready

			if (!Config.UseNet) {
				switch (CtrlReg&0x2002) {
					case 0x0002: buf[0] = PAD1_startPoll(1); break;
					case 0x2002: buf[0] = PAD2_startPoll(2); break;
				}
			} else {
				if ((CtrlReg & 0x2002) == 0x0002) {
					int i, j;

					PAD1_startPoll(1);
					buf[0] = 0;
					buf[1] = PAD1_poll(0x42);
					if (!(buf[1] & 0x0f)) {
						bufcount = 32;
					} else {
						bufcount = (buf[1] & 0x0f) * 2;
					}
					buf[2] = PAD1_poll(0);
					i = 3;
					j = bufcount;
					while (j--) {
						buf[i++] = PAD1_poll(0);
					}
					bufcount+= 3;

					if (NET_sendPadData(buf, bufcount) == -1)
						netError();

					if (NET_recvPadData(buf, 1) == -1)
						netError();
					if (NET_recvPadData(buf+128, 2) == -1)
						netError();
				} else {
					memcpy(buf, buf+128, 32);
				}
			}

			bufcount = 2;
			parp = 0;
			padst = 1;
			SIO_INT();
			return;
		case 0x81: // start memcard
			StatReg |= RX_RDY;
			memcpy(buf, cardh, 4);
			parp = 0;
			bufcount = 3;
			mcdst = 1;
			rdwr = 0;
			SIO_INT();
			return;
	}
}
コード例 #2
0
ファイル: sio.cpp プロジェクト: V10lator/emumaster
void sioWrite8(u8 data) {
#ifdef PAD_LOG
	PAD_LOG("sio write8 %x\n", value);
#endif
	switch (padst) {
	case 1: SIO_INT(SIO_CYCLES);
		if ((data & 0x40) == 0x40) {
			padst = 2; parp = 1;
			switch (CtrlReg & 0x2002) {
			case 0x0002:
				buf[parp] = pad1Poll(data);
				break;
			case 0x2002:
				buf[parp] = pad2Poll(data);
				break;
			}

			if (!(buf[parp] & 0x0f)) {
				bufcount = 2 + 32;
			} else {
				bufcount = 2 + (buf[parp] & 0x0f) * 2;
			}
			if (buf[parp] == 0x41) {
				switch (data) {
					case 0x43:
						buf[1] = 0x43;
						break;
					case 0x45:
						buf[1] = 0xf3;
						break;
				}
			}
		}
		else padst = 0;
		return;
	case 2:
		parp++;
/*		if (buf[1] == 0x45) {
		buf[parp] = 0;
		SIO_INT(SIO_CYCLES);
		return;
		}*/
		switch (CtrlReg & 0x2002) {
		case 0x0002: buf[parp] = pad1Poll(data); break;
		case 0x2002: buf[parp] = pad2Poll(data); break;
		}

		if (parp == bufcount) { padst = 0; return; }
		SIO_INT(SIO_CYCLES);
		return;
	}

	switch (mcdst) {
	case 1:
		SIO_INT(SIO_CYCLES);
		if (rdwr) { parp++; return; }
		parp = 1;
		switch (data) {
			case 0x52: rdwr = 1; break;
			case 0x57: rdwr = 2; break;
			default: mcdst = 0;
		}
		return;
	case 2: // address H
		SIO_INT(SIO_CYCLES);
		adrH = data;
		*buf = 0;
		parp = 0;
		bufcount = 1;
		mcdst = 3;
		return;
	case 3: // address L
		SIO_INT(SIO_CYCLES);
		adrL = data;
		*buf = adrH;
		parp = 0;
		bufcount = 1;
		mcdst = 4;
		return;
	case 4:
		SIO_INT(SIO_CYCLES);
		parp = 0;
		switch (rdwr) {
			case 1: // read
				buf[0] = 0x5c;
				buf[1] = 0x5d;
				buf[2] = adrH;
				buf[3] = adrL;
				switch (CtrlReg & 0x2002) {
					case 0x0002:
						memcpy(&buf[4], psxMcd1.memory + (adrL | (adrH << 8)) * 128, 128);
						break;
					case 0x2002:
						memcpy(&buf[4], psxMcd2.memory + (adrL | (adrH << 8)) * 128, 128);
						break;
				}
				{
				char xorVal = 0;
				int i;
				for (i = 2; i < 128 + 4; i++)
					xorVal ^= buf[i];
				buf[132] = xorVal;
				}
				buf[133] = 0x47;
				bufcount = 133;
				break;
			case 2: // write
				buf[0] = adrL;
				buf[1] = data;
				buf[129] = 0x5c;
				buf[130] = 0x5d;
				buf[131] = 0x47;
				bufcount = 131;
				break;
		}
		mcdst = 5;
		return;
	case 5:
		parp++;
		if ((rdwr == 1 && parp == 132) ||
			(rdwr == 2 && parp == 129)) {
			// clear "new card" flags
			if (CtrlReg & 0x2000)
				cardh2[1] &= ~8;
			else
				cardh1[1] &= ~8;
		}
		if (rdwr == 2) {
			if (parp < 128) buf[parp + 1] = data;
		}
		SIO_INT(SIO_CYCLES);
		return;
	}

	switch (data) {
	case 0x01: // start pad
		StatReg |= RX_RDY;		// Transfer is Ready

		switch (CtrlReg & 0x2002) {
		case 0x0002: buf[0] = pad1StartPoll(1); break;
		case 0x2002: buf[0] = pad2StartPoll(2); break;
		}
		bufcount = 2;
		parp = 0;
		padst = 1;
		SIO_INT(SIO_CYCLES);
		return;
	case 0x81: // start memcard
		if (CtrlReg & 0x2000) {
			if (!psxMcd2.isEnabled())
				goto no_device;
			memcpy(buf, cardh2, 4);
		} else {
			if (!psxMcd1.isEnabled())
				goto no_device;
			memcpy(buf, cardh1, 4);
		}
		StatReg |= RX_RDY;
		parp = 0;
		bufcount = 3;
		mcdst = 1;
		rdwr = 0;
		SIO_INT(SIO_CYCLES);
		return;
	default:
	no_device:
		StatReg |= RX_RDY;
		buf[0] = 0xff;
		parp = 0;
		bufcount = 0;
		return;
	}
}
コード例 #3
0
ファイル: Sio.cpp プロジェクト: mauzus/progenitor
void SIO_CommandWrite(u8 value,int way) {
	PAD_LOG("sio write8 %x", value);

	// PAD COMMANDS
	switch (sio.padst) {
		case 1: SIO_INT();
			if ((value&0x40) == 0x40) {
				sio.padst = 2; sio.parp = 1;
				switch (sio.CtrlReg&0x2002) {
					case 0x0002:
						sio.packetsize ++;	// Total packet size sent
						sio.buf[sio.parp] = PADpoll(value);
						break;
					case 0x2002:
						sio.packetsize ++;	// Total packet size sent
						sio.buf[sio.parp] = PADpoll(value);
						break;
				}
				if (!(sio.buf[sio.parp] & 0x0f)) {
					sio.bufcount = 2 + 32;
				} else {
					sio.bufcount = 2 + (sio.buf[sio.parp] & 0x0f) * 2;
				}
			}
			else sio.padst = 0;
			return;
		case 2:
			sio.parp++;
			switch (sio.CtrlReg&0x2002) {
				case 0x0002: sio.packetsize ++; sio.buf[sio.parp] = PADpoll(value); break;
				case 0x2002: sio.packetsize ++; sio.buf[sio.parp] = PADpoll(value); break;
			}
			if (sio.parp == sio.bufcount) { sio.padst = 0; return; }
			SIO_INT();
			return;
		case 3:
			// No pad connected.
			sio.parp++;
			if (sio.parp == sio.bufcount) { sio.padst = 0; return; }
			SIO_INT();
			return;
	}

	// MEMORY CARD COMMANDS
	switch (sio.mcdst) {
		case 1:
		{
			sio.packetsize++;
			SIO_INT();
			if (sio.rdwr) { sio.parp++; return; }
			sio.parp = 1;

			const char* log_cmdname = "";

			switch (value) {
			case 0x11: // RESET
				log_cmdname = "Reset1";

				sio.bufcount =  8;
				memset8<0xff>(sio.buf);
				sio.buf[3] = sio.terminator;
				sio.buf[2] = '+';
				sio.mcdst = 99;
				sio2.packet.recvVal3 = 0x8c;
				break;

			// FIXME : Why are there two identical cases for resetting the
			// memorycard(s)?  there doesn't appear to be anything dealing with
			// card slots here.  --air
			case 0x12: // RESET
				log_cmdname = "Reset2";
				sio.bufcount =  8;
				memset8<0xff>(sio.buf);
				sio.buf[3] = sio.terminator;
				sio.buf[2] = '+';
				sio.mcdst = 99;
				sio2.packet.recvVal3 = 0x8c;
				break;

			case 0x81: // COMMIT
				log_cmdname = "Commit";
				sio.bufcount =  8;
				memset8<0xff>(sio.buf);
				sio.mcdst = 99;
				sio.buf[3] = sio.terminator;
				sio.buf[2] = '+';
				sio2.packet.recvVal3 = 0x8c;
				if(value == 0x81) {
					if(sio.mc_command==0x42)
						sio2.packet.recvVal1 = 0x1600; // Writing
					else if(sio.mc_command==0x43) sio2.packet.recvVal1 = 0x1700; // Reading
				}
				break;
			case 0x21:
			case 0x22:
			case 0x23: // SECTOR SET
				log_cmdname = "SetSector";
                sio.bufcount =  8; sio.mcdst = 99; sio.sector=0; sio.k=0;
				memset8<0xff>(sio.buf);
				sio2.packet.recvVal3 = 0x8c;
				sio.buf[8]=sio.terminator;
				sio.buf[7]='+';
				break;

			case 0x24: break;
			case 0x25: break;

			case 0x26:
			{
				log_cmdname = "GetInfo";

				const uint port = sio.GetMemcardIndex();
				const uint slot = sio.activeMemcardSlot[port];

				mc_command_0x26_tag cmd = mc_sizeinfo_8mb;
				PS2E_McdSizeInfo info;
				
				info.SectorSize			= cmd.sectorSize;
				info.EraseBlockSizeInSectors			= cmd.eraseBlocks;
				info.McdSizeInSectors	= cmd.mcdSizeInSectors;
				
				SysPlugins.McdGetSizeInfo( port, slot, info );
				pxAssumeDev( cmd.mcdSizeInSectors >= mc_sizeinfo_8mb.mcdSizeInSectors,
					"Mcd plugin returned an invalid memorycard size: Cards smaller than 8MB are not supported." );
				
				cmd.sectorSize			= info.SectorSize;
				cmd.eraseBlocks			= info.EraseBlockSizeInSectors;
				cmd.mcdSizeInSectors	= info.McdSizeInSectors;
				
				// Recalculate the xor summation
				// This uses a trick of removing the known xor values for a default 8mb memorycard (for which the XOR
				// was calculated), and replacing it with our new values.
				
				apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.sectorSize );
				apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.eraseBlocks );
				apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.mcdSizeInSectors );

				apply_xor( cmd.mc_xor, cmd.sectorSize );
				apply_xor( cmd.mc_xor, cmd.eraseBlocks );
				apply_xor( cmd.mc_xor, cmd.mcdSizeInSectors );
				
				sio.bufcount = 12; sio.mcdst = 99; sio2.packet.recvVal3 = 0x83;
				memset8<0xff>(sio.buf);
				memcpy_fast(&sio.buf[2], &cmd, sizeof(cmd));
				sio.buf[12]=sio.terminator;
			}
			break;

			case 0x27:
			case 0x28:
			case 0xBF:
				log_cmdname = "NotSure";	// FIXME !!
				sio.bufcount =  4; sio.mcdst = 99; sio2.packet.recvVal3 = 0x8b;
				memset8<0xff>(sio.buf);
				sio.buf[4]=sio.terminator;
				sio.buf[3]='+';
				break;

			// FIXME ?
			// sio.lastsector and sio.mode are unused.

			case 0x42: // WRITE
				log_cmdname = "Write";
				//sio.mode = 0;
			goto __doReadWrite;

			case 0x43: // READ
				log_cmdname = "Read";
				//sio.lastsector = sio.sector; // Reading
			goto __doReadWrite;

			case 0x82:
				log_cmdname = "Read(?)"; // FIXME !!
				//if(sio.lastsector==sio.sector) sio.mode = 2;

			__doReadWrite:
				sio.bufcount =133; sio.mcdst = 99;
				memset8<0xff>(sio.buf);
				sio.buf[133]=sio.terminator;
				sio.buf[132]='+';
			break;
			

			case 0xf0:
			case 0xf1:
			case 0xf2:
				log_cmdname = "NoClue"; // FIXME !!
				sio.mcdst = 99;
				break;

			case 0xf3:
			case 0xf7:
				log_cmdname = "NoClueHereEither"; // FIXME !!
				sio.bufcount = 4; sio.mcdst = 99;
				memset8<0xff>(sio.buf);
				sio.buf[4]=sio.terminator;
				sio.buf[3]='+';
				break;

			case 0x52:
				log_cmdname = "FixMe"; // FIXME !!
				sio.rdwr = 1; memset8<0xff>(sio.buf);
				sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
				break;
			case 0x57:
				log_cmdname = "FixMe"; // FIXME !!
				sio.rdwr = 2; memset8<0xff>(sio.buf);
				sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
				break;
			default:
				log_cmdname = "Unknown";
				sio.mcdst = 0;
				memset8<0xff>(sio.buf);
				sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
			}
			MEMCARDS_LOG("MC(%d) command 0x%02X [%s]", sio.GetMemcardIndex()+1, value, log_cmdname);
			sio.mc_command = value;
		}
		return;		// END CASE 1.

		// FURTHER PROCESSING OF THE MEMORY CARD COMMANDS
		case 99:
		{
			sio.packetsize++;
			sio.parp++;
			switch(sio.mc_command)
			{
			// SET_ERASE_PAGE; the next erase commands will *clear* data starting with the page set here
			case 0x21:
			// SET_WRITE_PAGE; the next write commands will commit data starting with the page set here
			case 0x22:
			// SET_READ_PAGE; the next read commands will return data starting with the page set here
			case 0x23:
                if (sio.parp==2)sio.sector|=(value & 0xFF)<< 0;
				if (sio.parp==3)sio.sector|=(value & 0xFF)<< 8;
				if (sio.parp==4)sio.sector|=(value & 0xFF)<<16;
				if (sio.parp==5)sio.sector|=(value & 0xFF)<<24;
				if (sio.parp==6)
				{
					if (sio_xor((u8 *)&sio.sector, 4) == value)
						MEMCARDS_LOG("MC(%d) SET PAGE sio.sector, sector=0x%04X", sio.GetMemcardIndex()+1, sio.sector);
					else
						MEMCARDS_LOG("MC(%d) SET PAGE XOR value ERROR 0x%02X != ^0x%02X",
							sio.GetMemcardIndex()+1, value, sio_xor((u8 *)&sio.sector, 4));
				}
				break;

			// SET_TERMINATOR; reads the new terminator code
			case 0x27:
				if(sio.parp==2)	{
					sio.terminator = value;
					sio.buf[4] = value;
					MEMCARDS_LOG("MC(%d) SET TERMINATOR command, value=0x%02X", sio.GetMemcardIndex()+1, value);

				}
				break;

			// GET_TERMINATOR; puts in position 3 the current terminator code and in 4 the default one
			//                                                                  depending on the param
			case 0x28:
				if(sio.parp == 2) {
					sio.buf[2] = '+';
					sio.buf[3] = sio.terminator;

					//if(value == 0) sio.buf[4] = 0xFF;
					sio.buf[4] = 0x55;
					MEMCARDS_LOG("MC(%d) GET TERMINATOR command, value=0x%02X", sio.GetMemcardIndex()+1, value);
				}
				break;
			// WRITE DATA
			case 0x42:
				if (sio.parp==2) {
					sio.bufcount=5+value;
					memset8<0xff>(sio.buf);
					sio.buf[sio.bufcount-1]='+';
					sio.buf[sio.bufcount]=sio.terminator;
					MEMCARDS_LOG("MC(%d) WRITE command, size=0x%02X", sio.GetMemcardIndex()+1, value);
				}
				else
				if ((sio.parp>2) && (sio.parp<sio.bufcount-2)) {
					sio.buf[sio.parp]=value;
					//MEMCARDS_LOG("MC(%d) WRITING 0x%02X", sio.GetMemcardIndex()+1, value);
				} else
				if (sio.parp==sio.bufcount-2) {
					if (sio_xor(&sio.buf[3], sio.bufcount-5)==value) {
                        _SaveMcd(&sio.buf[3], (512+16)*sio.sector+sio.k, sio.bufcount-5);
						sio.buf[sio.bufcount-1]=value;
						sio.k+=sio.bufcount-5;
					} else {
						MEMCARDS_LOG("MC(%d) write XOR value error 0x%02X != ^0x%02X",
							sio.GetMemcardIndex()+1, value, sio_xor(&sio.buf[3], sio.bufcount-5));
					}
				}
				break;
			// READ DATA
			case 0x43:
				if (sio.parp==2)
				{
					//int i;
					sio.bufcount=value+5;
					sio.buf[3]='+';
					MEMCARDS_LOG("MC(%d) READ command, size=0x%02X", sio.GetMemcardIndex()+1, value);
					_ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value);

					/*if(sio.mode==2)
					{
						int j;
						for(j=0; j < value; j++)
							sio.buf[4+j] = ~sio.buf[4+j];
					}*/

					sio.k+=value;
					sio.buf[sio.bufcount-1]=sio_xor(&sio.buf[4], value);
					sio.buf[sio.bufcount]=sio.terminator;
				}
				break;
			// INTERNAL ERASE
			case 0x82:
				if(sio.parp==2)
				{
					sio.buf[2]='+';
					sio.buf[3]=sio.terminator;
					//if (sio.k != 0 || (sio.sector & 0xf) != 0)
					//	Console.Warning("saving : odd position for erase.");

					_EraseMCDBlock((512+16)*(sio.sector&~0xf));

				/*	memset(sio.buf, -1, 256);
					_SaveMcd(sio.buf, (512+16)*sio.sector, 256);
					_SaveMcd(sio.buf, (512+16)*sio.sector+256, 256);
					_SaveMcd(sio.buf, (512+16)*sio.sector+512, 16);
					sio.buf[2]='+';
					sio.buf[3]=sio.terminator;*/
					//sio.buf[sio.bufcount] = sio.terminator;
					MEMCARDS_LOG("MC(%d) INTERNAL ERASE command 0x%02X", sio.GetMemcardIndex()+1, value);
				}
				break;
			// CARD AUTHENTICATION CHECKS
			case 0xF0:
				if (sio.parp==2)
				{
					MEMCARDS_LOG("MC(%d) CARD AUTH :0x%02X", sio.GetMemcardIndex()+1, value);
					switch(value){
					case  1:
					case  2:
					case  4:
					case 15:
					case 17:
					case 19:
						sio.bufcount=13;
						memset8<0xff>(sio.buf);
						sio.buf[12] = 0; // Xor value of data from index 4 to 11
						sio.buf[3]='+';
						sio.buf[13] = sio.terminator;
						break;
					case  6:
					case  7:
					case 11:
						sio.bufcount=13;
						memset8<0xff>(sio.buf);
						sio.buf[12]='+';
						sio.buf[13] = sio.terminator;
						break;
					default:
						sio.bufcount=4;
						memset8<0xff>(sio.buf);
						sio.buf[3]='+';
						sio.buf[4] = sio.terminator;
					}
				}
				break;
			}
			if (sio.bufcount<=sio.parp)	sio.mcdst = 0;
		}
		return;		// END CASE 99.
	}

	switch (sio.mtapst)
	{
		case 0x1:
			sio.packetsize++;
			sio.parp = 1;
			SIO_INT();
			switch(value) {
			case 0x12:
				// Query number of pads supported.
				sio.buf[3] = 4;
				sio.mtapst = 2;
				sio.bufcount = 5;
				break;
			case 0x13:
				// Query number of memcards supported.
				sio.buf[3] = 4;
				sio.mtapst = 2;
				sio.bufcount = 5;
				break;
			case 0x21:
				// Set pad slot.
				sio.mtapst = value;
				sio.bufcount = 6; // No idea why this is 6, saved from old code.
				break;
			case 0x22:
				// Set memcard slot.
				sio.mtapst = value;
				sio.bufcount = 6; // No idea why this is 6, saved from old code.
				break;
			}
			// Commented out values are from original code.  They break multitap in bios.
			sio.buf[sio.bufcount-1]=0;//'+';
			sio.buf[sio.bufcount]=0;//'Z';
			return;
		case 0x2:
			sio.packetsize++;
			sio.parp++;
            if (sio.bufcount<=sio.parp)	sio.mcdst = 0;
			SIO_INT();
			return;
		case 0x21:
			// Set pad slot.
			sio.packetsize++;
			sio.parp++;
			sio.mtapst = 2;
			if (sio.CtrlReg & 2)
			{
				int port = sio.GetMultitapPort();
				if (IsMtapPresent(port))
					sio.activePadSlot[port] = value;
			}
			SIO_INT();
			return;
		case 0x22:
			// Set memcard slot.
			sio.packetsize++;
			sio.parp++;
			sio.mtapst = 2;
			if (sio.CtrlReg & 2)
			{
				int port = sio.GetMultitapPort();
				if (IsMtapPresent(port))
					sio.activeMemcardSlot[port] = value;
			}
			SIO_INT();
			return;
	}

	if(sio.count == 1 || way == 0) InitializeSIO(value);
}
コード例 #4
0
ファイル: sio.c プロジェクト: Asmodean-/PCSXR
void sioWrite8(unsigned char value) {
#ifdef PAD_LOG
	PAD_LOG("sio write8 %x (PAR:%x PAD:%x MCDL%x)\n", value, parp, padst, mcdst);
#endif
	switch (padst) {
		case 1: SIO_INT(SIO_CYCLES);
			/*
			$41-4F
			$41 = Find bits in poll respones
			$42 = Polling command
			$43 = Config mode (Dual shock?)
			$44 = Digital / Analog (after $F3)
			$45 = Get status info (Dual shock?)

			ID:
			$41 = Digital
			$73 = Analogue Red LED
			$53 = Analogue Green LED

			$23 = NegCon
			$12 = Mouse
			*/

			if ((value & 0x40) == 0x40) {
				padst = 2; parp = 1;
				if (!Config.UseNet) {
					switch (CtrlReg & 0x2002) {
						case 0x0002:
							buf[parp] = PAD1_poll(value);
							break;
						case 0x2002:
							buf[parp] = PAD2_poll(value);
							break;
					}
				}/* else {
//					SysPrintf("%x: %x, %x, %x, %x\n", CtrlReg&0x2002, buf[2], buf[3], buf[4], buf[5]);
				}*/

				if (!(buf[parp] & 0x0f)) {
					bufcount = 2 + 32;
				} else {
					bufcount = 2 + (buf[parp] & 0x0f) * 2;
				}


				// Digital / Dual Shock Controller
				if (buf[parp] == 0x41) {
					switch (value) {
						// enter config mode
						case 0x43:
							buf[1] = 0x43;
							break;

						// get status
						case 0x45:
							buf[1] = 0xf3;
							break;
					}
				}


				// NegCon - Wipeout 3
				if( buf[parp] == 0x23 ) {
					switch (value) {
						// enter config mode
						case 0x43:
							buf[1] = 0x79;
							break;

						// get status
						case 0x45:
							buf[1] = 0xf3;
							break;
					}
				}
			}
			else padst = 0;
			return;
		case 2:
			parp++;
/*			if (buf[1] == 0x45) {
				buf[parp] = 0;
				SIO_INT(SIO_CYCLES);
				return;
			}*/
			if (!Config.UseNet) {
				switch (CtrlReg & 0x2002) {
					case 0x0002: buf[parp] = PAD1_poll(value); break;
					case 0x2002: buf[parp] = PAD2_poll(value); break;
				}
			}

			if (parp == bufcount) { padst = 0; return; }
			SIO_INT(SIO_CYCLES);
			return;
	}

	switch (mcdst) {
		case 1:
			SIO_INT(SIO_CYCLES);
			if (rdwr) { parp++; return; }
			parp = 1;
			switch (value) {
				case 0x52: rdwr = 1; break;
				case 0x57: rdwr = 2; break;
				default: mcdst = 0;
			}
			return;
		case 2: // address H
			SIO_INT(SIO_CYCLES);
			adrH = value;
			*buf = 0;
			parp = 0;
			bufcount = 1;
			mcdst = 3;
			return;
		case 3: // address L
			SIO_INT(SIO_CYCLES);
			adrL = value;
			*buf = adrH;
			parp = 0;
			bufcount = 1;
			mcdst = 4;
			return;
		case 4:
			SIO_INT(SIO_CYCLES);
			parp = 0;
			switch (rdwr) {
				case 1: // read
					buf[0] = 0x5c;
					buf[1] = 0x5d;
					buf[2] = adrH;
					buf[3] = adrL;
					switch (CtrlReg & 0x2002) {
						case 0x0002:
							memcpy(&buf[4], Mcd1Data + (adrL | (adrH << 8)) * 128, 128);
							break;
						case 0x2002:
							memcpy(&buf[4], Mcd2Data + (adrL | (adrH << 8)) * 128, 128);
							break;
					}
					{
					char xorsum = 0;
					int i;
					for (i = 2; i < 128 + 4; i++)
						xorsum ^= buf[i];
					buf[132] = xorsum;
					}
					buf[133] = 0x47;
					bufcount = 133;
					break;
				case 2: // write
					buf[0] = adrL;
					buf[1] = value;
					buf[129] = 0x5c;
					buf[130] = 0x5d;
					buf[131] = 0x47;
					bufcount = 131;
					cardh[1] &= ~MCDST_CHANGED;
					break;
			}
			mcdst = 5;
			return;
		case 5:
			parp++;
			if (rdwr == 2) {
				if (parp < 128) buf[parp + 1] = value;
			}
			SIO_INT(SIO_CYCLES);
			return;
	}


	/*
	GameShark CDX
	
	ae - be - ef - 04 + [00]
	ae - be - ef - 01 + 00 + [00] * $1000
	ae - be - ef - 01 + 42 + [00] * $1000
	ae - be - ef - 03 + 01,01,1f,e3,85,ae,d1,28 + [00] * 4
	*/
	switch (gsdonglest) {
		// main command loop
		case 1:
			SIO_INT( SIO_CYCLES );

			// GS CDX
			// - unknown output

			// reset device when fail?
			if( value == 0xae )
			{
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;
			}


			// GS CDX
			else if( value == 0xbe )
			{
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;


				buf[0] = reverse_8( 0xde );
			}


			// GS CDX
			else if( value == 0xef )
			{
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;


				buf[0] = reverse_8( 0xad );
			}


			// GS CDX [1 in + $1000 out + $1 out]
			else if( value == 0x01 )
			{
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;


				// $00 = 0000 0000
				// - (reverse) 0000 0000
				buf[0] = 0x00;
				gsdonglest = 2;
			}


			// GS CDX [1 in + $1000 in + $1 out]
			else if( value == 0x02 )
			{
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;


				// $00 = 0000 0000
				// - (reverse) 0000 0000
				buf[0] = 0x00;
				gsdonglest = 3;
			}


			// GS CDX [8 in, 4 out]
			else if( value == 0x03 )
			{
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;

				// $00 = 0000 0000
				// - (reverse) 0000 0000
				buf[0] = 0x00;

				gsdonglest = 4;
			}


			// GS CDX [out 1]
			else if( value == 0x04 )
			{
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;


				// $00 = 0000 0000
				// - (reverse) 0000 0000
				buf[0] = 0x00;
				gsdonglest = 5;
			}
			else
			{
				// ERROR!!
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;
				buf[0] = 0xff;

				gsdonglest = 0;
			}

			return;


		// be - ef - 01
		case 2: {
			unsigned char checksum;
			unsigned int lcv;

			SIO_INT( SIO_CYCLES );
			StatReg |= RX_RDY;


			// read 1 byte
			DongleBank = buf[ 0 ];


			// write data + checksum
			checksum = 0;
			for( lcv = 0; lcv < 0x1000; lcv++ )
			{
				unsigned char data;

				data = DongleData[ DongleBank * 0x1000 + lcv ];

				buf[ lcv+1 ] = reverse_8( data );
				checksum += data;
			}


			parp = 0;
			bufcount = 0x1001;
			buf[ 0x1001 ] = reverse_8( checksum );


			gsdonglest = 255;
			return;
		}


		// be - ef - 02
		case 3:
			SIO_INT( SIO_CYCLES );
			StatReg |= RX_RDY;

			// command start
			if( parp < 0x1000+1 )
			{
				// read 1 byte
				buf[ parp ] = value;
				parp++;
			}

			if( parp == 0x1001 )
			{
				unsigned char checksum;
				unsigned int lcv;

				DongleBank = buf[0];
				memcpy( DongleData + DongleBank * 0x1000, buf+1, 0x1000 );

				// save to file
				SaveDongle( "memcards/CDX_Dongle.bin" );


				// write 8-bit checksum
				checksum = 0;
				for( lcv = 1; lcv < 0x1001; lcv++ )
				{
					checksum += buf[ lcv ];
				}

				parp = 0;
				bufcount = 1;
				buf[1] = reverse_8( checksum );


				// flush result
				gsdonglest = 255;
			}
			return;


		// be - ef - 03
		case 4:
			SIO_INT( SIO_CYCLES );
			StatReg |= RX_RDY;

			// command start
			if( parp < 8 )
			{
				// read 2 (?,?) + 4 (DATA?) + 2 (CRC?)
				buf[ parp ] = value;
				parp++;
			}

			if( parp == 8 )
			{
				// now write 4 bytes via -FOUR- $00 writes
				parp = 8;
				bufcount = 12;


				// TODO: Solve CDX algorithm


				// GS CDX [magic key]
				if( buf[2] == 0x12 && buf[3] == 0x34 &&
						buf[4] == 0x56 && buf[5] == 0x78 )
				{
					buf[9] = reverse_8( 0x3e );
					buf[10] = reverse_8( 0xa0 );
					buf[11] = reverse_8( 0x40 );
					buf[12] = reverse_8( 0x29 );
				}

				// GS CDX [address key #2 = 6ec]
				else if( buf[2] == 0x1f && buf[3] == 0xe3 &&
								 buf[4] == 0x45 && buf[5] == 0x60 )
				{
					buf[9] = reverse_8( 0xee );
					buf[10] = reverse_8( 0xdd );
					buf[11] = reverse_8( 0x71 );
					buf[12] = reverse_8( 0xa8 );
				}

				// GS CDX [address key #3 = ???]
				else if( buf[2] == 0x1f && buf[3] == 0xe3 &&
								 buf[4] == 0x72 && buf[5] == 0xe3 )
				{
					// unsolved!!

					// Used here: 80090348 / 80090498

					// dummy value - MSB
					buf[9] = reverse_8( 0xfa );
					buf[10] = reverse_8( 0xde );
					buf[11] = reverse_8( 0x21 );
					buf[12] = reverse_8( 0x97 );
				}

				// GS CDX [address key #4 = a00]
				else if( buf[2] == 0x1f && buf[3] == 0xe3 &&
								 buf[4] == 0x85 && buf[5] == 0xae )
				{
					buf[9] = reverse_8( 0xee );
					buf[10] = reverse_8( 0xdd );
					buf[11] = reverse_8( 0x7d );
					buf[12] = reverse_8( 0x44 );
				}

				// GS CDX [address key #5 = 9ec]
				else if( buf[2] == 0x17 && buf[3] == 0xe3 &&
								 buf[4] == 0xb5 && buf[5] == 0x60 )
				{
					buf[9] = reverse_8( 0xee );
					buf[10] = reverse_8( 0xdd );
					buf[11] = reverse_8( 0x7e );
					buf[12] = reverse_8( 0xa8 );
				}

				else
				{
					// dummy value - MSB
					buf[9] = reverse_8( 0xfa );
					buf[10] = reverse_8( 0xde );
					buf[11] = reverse_8( 0x21 );
					buf[12] = reverse_8( 0x97 );
				}						

				// flush bytes -> done
				gsdonglest = 255;
			}
			return;


		// be - ef - 04
		case 5:
			if( value == 0x00 )
			{
				SIO_INT( SIO_CYCLES );
				StatReg |= RX_RDY;


				// read 1 byte
				parp = 0;
				bufcount = parp;

				// size of dongle card?
				buf[ 0 ] = reverse_8( DONGLE_SIZE / 0x1000 );


				// done already
				gsdonglest = 0;
			}
			return;


		// flush bytes -> done
		case 255:
			if( value == 0x00 )
			{
				//SIO_INT( SIO_CYCLES );
				SIO_INT(1);
				StatReg |= RX_RDY;

				parp++;
				if( parp == bufcount )
				{
					gsdonglest = 0;

#ifdef GSDONGLE_LOG
					PAD_LOG("(gameshark dongle) DONE!!\n" );
#endif
				}
			}
			else
			{
				// ERROR!!
				StatReg |= RX_RDY;

				parp = 0;
				bufcount = parp;
				buf[0] = 0xff;

				gsdonglest = 0;
			}
			return;
	}


	switch (value) {
		case 0x01: // start pad
			StatReg |= RX_RDY;		// Transfer is Ready

			if (!Config.UseNet) {
				switch (CtrlReg & 0x2002) {
					case 0x0002: buf[0] = PAD1_startPoll(1); break;
					case 0x2002: buf[0] = PAD2_startPoll(2); break;
				}
			} else {
				if ((CtrlReg & 0x2002) == 0x0002) {
					int i, j;

					PAD1_startPoll(1);
					buf[0] = 0;
					buf[1] = PAD1_poll(0x42);
					if (!(buf[1] & 0x0f)) {
						bufcount = 32;
					} else {
						bufcount = (buf[1] & 0x0f) * 2;
					}
					buf[2] = PAD1_poll(0);
					i = 3;
					j = bufcount;
					while (j--) {
						buf[i++] = PAD1_poll(0);
					}
					bufcount+= 3;

					if (NET_sendPadData(buf, bufcount) == -1)
						netError();

					if (NET_recvPadData(buf, 1) == -1)
						netError();
					if (NET_recvPadData(buf + 128, 2) == -1)
						netError();
				} else {
					memcpy(buf, buf + 128, 32);
				}
			}

			bufcount = 2;
			parp = 0;
			padst = 1;
			SIO_INT(SIO_CYCLES);
			return;
		case 0x81: // start memcard
		//case 0x82: case 0x83: case 0x84: // Multitap memcard access
			StatReg |= RX_RDY;

			// Chronicles of the Sword - no memcard = password options
			if( Config.NoMemcard || ((strlen(Config.Mcd1) <=0) && (strlen(Config.Mcd2) <=0)) ) {
				memset(buf, 0x00, 4);
			} else {
				memcpy(buf, cardh, 4);
			}

			parp = 0;
			bufcount = 3;
			mcdst = 1;
			rdwr = 0;
			SIO_INT(SIO_CYCLES);
			return;
		case 0xae: // GameShark CDX - start dongle
			StatReg |= RX_RDY;
			gsdonglest = 1;

			parp = 0;
			bufcount = parp;

			if( !DongleInit )
			{
				LoadDongle( "memcards/CDX_Dongle.bin" );

				DongleInit = 1;
			}

			SIO_INT( SIO_CYCLES );
			return;

		default: // no hardware found
			StatReg |= RX_RDY;
			return;
	}
}