2015-11-14 12:49:45 +00:00
using System ;
using System.Windows.Forms ;
using BizHawk.Emulation.Common ;
using BizHawk.Client.Common ;
using System.Globalization ;
namespace BizHawk.Client.EmuHawk
{
2015-11-15 14:25:55 +00:00
[ToolAttributes(released: true, supportedSystems: new[] { "GB" , "N64" } ) ]
2015-11-14 12:49:45 +00:00
public partial class GameShark : Form , IToolForm , IToolFormAutoConfig
{
//We are using Memory Domains, so we NEED this.
[RequiredService]
private IMemoryDomains MemoryDomains { get ; set ; }
2015-11-15 14:25:55 +00:00
[RequiredService]
private IEmulator Emulator { get ; set ; }
2015-11-14 12:49:45 +00:00
public GameShark ( )
{
InitializeComponent ( ) ;
}
public bool UpdateBefore
{
get
{
return true ;
}
}
public bool AskSaveChanges ( )
{
return true ;
}
public void FastUpdate ( )
{
2015-11-14 20:10:23 +00:00
2015-11-14 12:49:45 +00:00
}
public void Restart ( )
{
}
public void UpdateValues ( )
{
}
private void btnGo_Click ( object sender , EventArgs e )
{
string parseString = null ;
string RAMAddress = null ;
string RAMValue = null ;
2015-11-15 14:25:55 +00:00
//What System are we running?
2015-11-15 19:09:55 +00:00
//We want Upper Case.
2015-11-16 03:35:05 +00:00
int byteSize = 0 ;
2015-11-15 19:09:55 +00:00
txtCheat . Text = txtCheat . Text . ToUpper ( ) ;
2015-11-16 03:35:05 +00:00
string testo = txtCheat . Text . Remove ( 2 , 11 ) ;
2015-11-15 14:25:55 +00:00
switch ( Emulator . SystemId )
2015-11-14 12:49:45 +00:00
{
2015-11-15 14:25:55 +00:00
case "GB" :
//This Check ONLY applies to GB/GBC codes.
if ( txtCheat . Text . Length ! = 8 )
{
2015-11-16 03:35:05 +00:00
MessageBox . Show ( "All GameShark Codes need to be Eight characters in Length" , "Input Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
2015-11-15 14:25:55 +00:00
return ;
}
2015-11-15 19:09:55 +00:00
//Let's make sure we start with zero. We have a good length, and a good starting zero, we should be good. Hopefully.
2015-11-16 03:35:05 +00:00
switch ( testo )
2015-11-15 19:09:55 +00:00
{
2015-11-16 03:35:05 +00:00
//Is this 00 or 01?
case "00" :
case "01" :
//Good.
break ;
default :
//No.
MessageBox . Show ( "All GameShark Codes for GameBoy need to start with 00 or 01" , "Input Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return ;
2015-11-15 19:09:55 +00:00
}
2015-11-15 14:25:55 +00:00
//Sample Input for GB/GBC:
//010FF6C1
//Becomes:
//Address C1F6
//Value 0F
parseString = txtCheat . Text . Remove ( 0 , 2 ) ;
//Now we need to break it down a little more.
RAMValue = parseString . Remove ( 2 , 4 ) ;
parseString = parseString . Remove ( 0 , 2 ) ;
//The issue is Endian... Time to get ultra clever. And Regret it.
//First Half
RAMAddress = parseString . Remove ( 0 , 2 ) ;
RAMAddress = RAMAddress + parseString . Remove ( 2 , 2 ) ;
//We now have our values.
//This part, is annoying...
try
{
//A Watch needs to be generated so we can make a cheat out of that. This is due to how the Cheat engine works.
//System Bus Domain, The Address to Watch, Byte size (Byte), Hex Display, Description. Not Big Endian.
var watch = Watch . GenerateWatch ( MemoryDomains [ "System Bus" ] , long . Parse ( RAMAddress , NumberStyles . HexNumber ) , Watch . WatchSize . Byte , Watch . DisplayType . Hex , txtDescription . Text , false ) ;
//Take Watch, Add our Value we want, and it should be active when addded?
Global . CheatList . Add ( new Cheat ( watch , int . Parse ( RAMValue , NumberStyles . HexNumber ) ) ) ;
//Clear old Inputs
txtCheat . Clear ( ) ;
txtDescription . Clear ( ) ;
}
//Someone broke the world?
catch ( Exception ex )
{
MessageBox . Show ( "An Error occured: " + ex . GetType ( ) . ToString ( ) , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
}
break ;
case "N64" :
2015-11-15 20:25:32 +00:00
//These codes, more or less work without Needing much work.
2015-11-15 14:25:55 +00:00
if ( txtCheat . Text . Contains ( " " ) = = false )
{
2015-11-16 03:35:05 +00:00
MessageBox . Show ( "All N64 GameShark Codes need to contain a space after the eighth character" , "Input Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
2015-11-15 14:25:55 +00:00
return ;
}
if ( txtCheat . Text . Length ! = 13 )
{
2015-11-16 03:35:05 +00:00
MessageBox . Show ( "All N64 GameShark Codes need to be 13 characters in length." , "Input Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
2015-11-15 14:25:55 +00:00
return ;
}
2015-11-15 19:09:55 +00:00
//We need to determine what kind of cheat this is.
2015-11-15 19:37:30 +00:00
//I need to determine if this is a Byte or Word.
2015-11-15 19:09:55 +00:00
switch ( testo )
{
//80 and 81 are the most common, so let's not get all worried.
case "80" :
2015-11-15 19:37:30 +00:00
//Byte
2015-11-16 03:35:05 +00:00
byteSize = 8 ;
2015-11-15 19:37:30 +00:00
break ;
2015-11-15 19:09:55 +00:00
case "81" :
2015-11-15 19:37:30 +00:00
//Word
2015-11-16 03:35:05 +00:00
byteSize = 16 ;
2015-11-15 19:09:55 +00:00
break ;
//Case A0 and A1 means "Write to Uncached address.
case "A0" :
2015-11-15 19:37:30 +00:00
//Byte
2015-11-16 03:35:05 +00:00
byteSize = 8 ;
2015-11-15 19:09:55 +00:00
break ;
case "A1" :
2015-11-15 19:37:30 +00:00
//Word
2015-11-16 03:35:05 +00:00
byteSize = 16 ;
2015-11-15 19:09:55 +00:00
break ;
//Do we support the GameShark Button? No. But these cheats, can be toggled. Which "Counts"
//<Ocean_Prince> Consequences be damned!
case "88" :
2015-11-15 20:25:32 +00:00
//Byte
2015-11-16 03:35:05 +00:00
byteSize = 8 ;
2015-11-15 19:09:55 +00:00
break ;
case "89" :
2015-11-15 20:25:32 +00:00
//Word
2015-11-16 03:35:05 +00:00
byteSize = 16 ;
2015-11-15 19:09:55 +00:00
break ;
//These are compare Address X to Value Y, then apply Value B to Address A
//This is not supported, yet
//TODO: When BizHawk supports a compare RAM Address's value is true then apply a value to another address, make it a thing.
case "D0" :
2015-11-15 20:25:32 +00:00
//Byte
case "D1" :
//Word
2015-11-15 19:09:55 +00:00
case "D2" :
2015-11-15 20:25:32 +00:00
//Byte
2015-11-15 19:09:55 +00:00
case "D3" :
2015-11-15 20:25:32 +00:00
//Word
2015-11-15 19:09:55 +00:00
MessageBox . Show ( "The code you entered is not supported by BizHawk." , "Emulator Error" , MessageBoxButtons . OK , MessageBoxIcon . Information ) ;
return ;
//These codes are for Disabling the Expansion Pak. that's a bad thing? Assuming bad codes, until told otherwise.
case "EE" :
case "DD" :
case "CC" :
2015-11-15 20:25:32 +00:00
MessageBox . Show ( "The code you entered is for Disabling the Expansion Pak. This is not allowed by this tool." , "Input Error" , MessageBoxButtons . OK , MessageBoxIcon . Information ) ;
2015-11-15 19:09:55 +00:00
return ;
//Enable Code
//Not Necessary? Think so?
case "DE" :
//Single Write ON-Boot code.
//Not Necessary? Think so?
case "F0" :
case "F1" :
case "2A" :
MessageBox . Show ( "The code you entered is not needed by Bizhawk." , "Input Error" , MessageBoxButtons . OK , MessageBoxIcon . Information ) ;
return ;
//TODO: Make Patch Code (5000XXYY) work.
case "50" :
2015-11-15 20:25:32 +00:00
//Word?
2015-11-15 19:09:55 +00:00
MessageBox . Show ( "The code you entered is not supported by this tool. Please Submit the Game's Name, Cheat/Code and Purpose to the BizHawk forums." , "Tool Error" , MessageBoxButtons . OK , MessageBoxIcon . Information ) ;
return ;
//I hope this isn't a thing.
default :
MessageBox . Show ( "The GameShark code entered is not a recognized format." , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
//Leave this Method, before someone gets hurt.
return ;
//break;
}
//Big Endian is USED constantly here. The question is, how do we determine if it's one or two bytes?
2015-11-15 14:25:55 +00:00
//Now to get clever.
//Sample Input for N64:
//8133B21E 08FF
//Becomes:
//Address 33B21E
//Value 08FF
//Note, 8XXXXXXX 00YY
//Is Byte, not Word
//Remove the 8X Octect
parseString = txtCheat . Text . Remove ( 0 , 2 ) ;
//Get RAM Address
RAMAddress = parseString . Remove ( 6 , 5 ) ;
//Get RAM Value
RAMValue = parseString . Remove ( 0 , 7 ) ;
2015-11-15 19:37:30 +00:00
2015-11-15 14:25:55 +00:00
try
{
//A Watch needs to be generated so we can make a cheat out of that. This is due to how the Cheat engine works.
//System Bus Domain, The Address to Watch, Byte size (Word), Hex Display, Description. Big Endian.
2015-11-16 03:35:05 +00:00
if ( byteSize = = 8 )
2015-11-15 14:25:55 +00:00
{
//We have a Word (Double Byte) sized Value
var watch = Watch . GenerateWatch ( MemoryDomains [ "RDRAM" ] , long . Parse ( RAMAddress , NumberStyles . HexNumber ) , Watch . WatchSize . Word , Watch . DisplayType . Hex , txtDescription . Text , true ) ;
//Take Watch, Add our Value we want, and it should be active when addded?
Global . CheatList . Add ( new Cheat ( watch , int . Parse ( RAMValue , NumberStyles . HexNumber ) ) ) ;
}
2015-11-16 03:35:05 +00:00
if ( byteSize = = 16 )
2015-11-15 14:25:55 +00:00
{
//We have a Byte sized value
var watch = Watch . GenerateWatch ( MemoryDomains [ "RDRAM" ] , long . Parse ( RAMAddress , NumberStyles . HexNumber ) , Watch . WatchSize . Byte , Watch . DisplayType . Hex , txtDescription . Text , true ) ;
//Take Watch, Add our Value we want, and it should be active when addded?
Global . CheatList . Add ( new Cheat ( watch , int . Parse ( RAMValue , NumberStyles . HexNumber ) ) ) ;
}
//Clear old Inputs
txtCheat . Clear ( ) ;
txtDescription . Clear ( ) ;
}
//Someone broke the world?
catch ( Exception ex )
{
MessageBox . Show ( "An Error occured: " + ex . GetType ( ) . ToString ( ) , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
}
break ;
2015-11-15 19:09:55 +00:00
case "PSX" :
//Not yet.
2015-11-16 03:35:05 +00:00
//These codes, more or less work without Needing much work.
if ( txtCheat . Text . Contains ( " " ) = = false )
{
MessageBox . Show ( "All PSX GameShark Cheats need to contain a space after the eighth character" , "Input Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return ;
}
if ( txtCheat . Text . Length ! = 13 )
{
MessageBox . Show ( "All PSX GameShark Cheats need to be 13 characters in length." , "Input Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return ;
}
//We need to determine what kind of cheat this is.
//I need to determine if this is a Byte or Word.
switch ( testo )
{
//30 80 Cheats mean, "Write, don't care otherwise."
case "30" :
byteSize = 8 ;
break ;
case "80" :
byteSize = 16 ;
break ;
//When value hits YYYY, make the next cheat go off
case "E0" :
//E0 byteSize = 8;
case "D0" :
//D0 byteSize = 16;
MessageBox . Show ( "The code you entered is not supported by BizHawk." , "Emulator Error" , MessageBoxButtons . OK , MessageBoxIcon . Information ) ;
return ;
//Something wrong with their input.
default :
MessageBox . Show ( "The GameShark code entered is not a recognized format." , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
//Leave this Method, before someone gets hurt.
return ;
}
//MainRAM
2015-11-15 19:09:55 +00:00
break ;
2015-11-15 14:25:55 +00:00
default :
//This should NEVER happen
break ;
2015-11-14 20:10:23 +00:00
}
2015-11-14 12:49:45 +00:00
}
private void btnClear_Click ( object sender , EventArgs e )
{
//Clear old Inputs
txtCheat . Clear ( ) ;
txtDescription . Clear ( ) ;
}
2015-11-14 21:11:13 +00:00
private void GameShark_Load ( object sender , EventArgs e )
{
2015-11-15 14:25:55 +00:00
//Welp, let's determine what System we got.
//NOTE: This is a sloppy Debugger/testing code. For Bad Development usage. DO NOT release with that line uncommented
//MessageBox.Show(Emulator.SystemId);
2015-11-14 21:11:13 +00:00
}
2015-11-14 12:49:45 +00:00
}
}