Example #1
0
File: Sio.c Project: 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;
	}
}
Example #2
0
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;
	}
}