diff --git a/PsNee.ino b/PsNee.ino index b921ba3..b5680c3 100644 --- a/PsNee.ino +++ b/PsNee.ino @@ -1,87 +1,45 @@ //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -//||||||MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM||||| -//||||||M*************************************************************M||||| -//||||||M*************************************************************M||||| -//||||||M***QQQQQQQQQ***************Q******Q**************************M||||| -//||||||M***Q********Q**************QQ*****Q**************************M||||| -//||||||M***Q********Q**************QQ*****Q**************************M||||| -//||||||M***Q********Q**************Q*Q****Q**************************M||||| -//||||||M***Q********Q**************Q*Q****Q**************************M||||| -//||||||M***Q********Q**************Q*Q****Q**************************M||||| -//||||||M***Q********Q**************Q**Q***Q**************************M||||| -//||||||M***QQQQQQQQQ***************Q**Q***Q**************************M||||| -//||||||M***Q***********QQQQQQQQ****Q***Q**Q******QQQQ*******QQQQ*****M||||| -//||||||M***Q**********QQ******Q****Q***Q**Q*****QQ**Q******QQ**Q*****M||||| -//||||||M***Q**********Q************Q***Q**Q****QQ***Q*****Q***QQ*****M||||| -//||||||M***Q**********QQQ**********Q****Q*Q***QQ**QQQ****QQQQQQ******M||||| -//||||||M***Q************QQQQQ******Q****Q*Q***QQQQQ******QQ**********M||||| -//||||||M***Q****************QQQ****Q*****QQ**QQ**********Q***********M||||| -//||||||M***Q******************Q****Q*****QQ**Q**********QQ***********M||||| -//||||||M***Q**********Q*******QQ***Q*****QQ**Q******QQ**Q******QQ****M||||| -//||||||M***Q**********QQ******QQ***Q******Q**QQ****QQ***QQ****QQ*****M||||| -//||||||M***Q***********QQQQQQQQ****Q******Q***QQQQQ******QQQQQQ******M||||| -//||||||M*************************************************************M||||| -//||||||M*************************************************************M||||| -//||||||MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM||||| -//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -//||||||||||||||||||||||||||||||||||||||||||||||||||| VERSION 2! ||||||||||| -//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -//BETA BETA BETA BETA BETA BETA BETA BETA BETA BETA BETA BETA BETA BETA BETA -//Updated on September 10, coded by TheFrietMan, as usual. -// +// PPPPPPPPPPPPPPPP P P +// P P PP P +// P P P P P +// P P P P P +// P P P P P +// P P P P P +// P P P P P +// PPPPPPPPPPPPPPPP PPPPPPPPPPP P P P PPPPPPPPPPP PPPPPPPPPPP +// P P P P P P P +// P P P P P P P +// P P P P P P P +// P P P P P P P +// P PPPPPPPPPPPPPP P PP PPPPPPP PPPPPPP +// P P P P P P +// P P P P P P +// P P P P P P +// P P P P P P +// P P P P P P +// P P P P P P +// PPPPPPPPPPPP P P PPPPPPPPPPP PPPPPPPPPPP VERSION 6! + +//UPDATED AT MAY 14 2016, CODED BY THE FRIENDLY FRIETMAN :-) + //PsNee, an open source stealth modchip for the Sony Playstation 1, usable on //all platforms supported by Arduino, preferably ATTiny. Finally something modern! -// -// -/////////// TO DO: ///////////// -// - Make SCEx-arrays smaller by commoning up the common parts of the arrays and thus use less flash -// - Tidy everything up by using functions instead of code-knitting -// - Implement what needs to be done when it is detected that PsNee is connected to a PU-22, PU-23 or PSOne -// - Slice the data signal in sync with an internal Playstation clock (there should be one on the gate-pin, -// this is the 7.35kHz WFCK) instead of using a free running clock from the modchip -//////////////////////////////// -// -// -/////////// VERSION 2! :D /////////// -//What has changed? -// - Thanks to TriMesh, the gate-pin is now also used to determine in which model of -// Playstation PsNee is installed. The modchip algorithm thus can be optimized for -// optimal performance on specific Playstation revisions. This works by monitoring -// whether a clock signal is present on this pin - when there is one, the modchip is -// installed in a PU-22, PU-23 or PSOne Playstation, else it is installed in an older -// model Playstation. In this version of PsNee, nothing is actually done with this information. -// - Thanks to -again- TriMesh, NTSC support for PAL SCPH-102 Playstations is added! This uses -// the same method the OneChip modchip used for achieving this: -// 1. Monitor the XLAT signal from the CD mechanism controller chip. This requires -// another connection to the Playstation. When this signal is 0, the first CD copy -// protection is passed! After this, there is another one. -// 2. After this, watch the Address18-pin (pin 31) on the BIOS-chip. When this signal -// is high, this means the second CD copy protection is about to run. -// 3. Wait a short time. -// 4. Pull the Data2-pin (pin 15) on the BIOS-chip to 0. This effectively blocks the -// execution of the region check of the inserted disc. -// 5. The Playstation plays the inserted disc and doesn't care whether it's PAL or NTSC! -// 6. Release the 0 of the Data2-pin. -// To correctly output a PAL video color signal for a PAL TV on a PAL PSOne with an NTSC disc -// inserted, Pin 3 of IC502 must be grounded with an external switch. The modchip also could do -// this, although we would need a device with more pins available. -// - The outputted data signal is now "sliced up" to improve (or less distort) the tracking -// signal from the CD mechanism: later Playstations use the CD tracking signal for transmitting -// the SCEx-string to the Playstation instead of using a seperate connection, so when the modchip -// forces a 0 on the data-pin, the tracking signal also is gone temporarily. By slicing the data- -// signal up in little pieces at least some of the tracking signal remains and the Playstation can -// read discs more easily. -// - The two big for-loops are combined into one with an OR-statement describing the two conditions -// modchip should be active: when flagFirstCycle = 0 or when flagFirstCycle = 1 and the lid is opened -// and closed again. This makes code maintenance easier. -// - The pin-out of the modchip is changed slightly to be able to use an interrupt for the PAL=>NTSC -// BIOS-patch for PAL SCPH-102. Please use the revised pin-out found below with this code. -//~TheFrietMan, The Netherlands -///////////////////////////////////// -// -// + + +//-------------------------------------------------- +// TL;DR +//-------------------------------------------------- +//Look for the "Arduino selection!" section and verify the target platform. Hook up your target device and hit Upload! +//BEWARE: when using ATTiny45, make sure the proper device is selected (Extra=>Board=>ATTiny45 (internal 8MHz clock)) +//and the proper fuses are burnt (use Extra=>Burn bootloader for this), otherwise PsNee will malfunction. A tutorial on +//uploading Arduino code via an Arduino Uno to an ATTiny device: http://highlowtech.org/?p=1695 +//Look at the pinout for your device and hook PsNee up to the points on your Playstation. + + +//-------------------------------------------------- +// General info! +//-------------------------------------------------- //PLAYSTATION 1 SECURITY - HOW IT DOES IT'S THING: //Sony didn't really go through great lenghts to protect it's precious Playstation //from running unauthorised software; the main security is based on a simple ASCII @@ -92,21 +50,21 @@ //The nifty Sony engineers did not use the pits and stuff to store the security checks for //Playstation discs but went crazy with the rolled up carrier string. In an ordinary CD, the //string is rolled up so that the spacing between the tracks is as equal as possible. If that -//namely is not the case, the laser itself needs to move a bit to keep track of the track and +//is not the case, the laser itself needs to move a bit to keep track of the track and //reliably read the data off the disc. //If you wonder how the laser knows when it follows the track optimally: four photodiodes, light //intensity measurement, difference measurements, servo. There. //To the point: the Sony engineers decidedly "fumbled up" the track of sector 4 on a Playstation //disc (the track was modulated in nerd-speak) so that the error correction circuit outputs a //recognisable signal, as the laser needs to be corrected to follow the track optimally. -//This outputted signal actually is a 250bps serial bitstream (with 1 startbit and 2 stopbits) which +//This output signal actually is a 250bps serial bitstream (with 1 start bit and 2 stop bits) which //in plain ASCII says SCEA (Sony Computer Entertainment of America), SCEE (Sony Computer Entertainment //of Europe) or SCEI (Sony Computer Entertainment of Japan), depending on the region of the disc inserted. //The security thus functions not only as copy protection, but also as region protection. //The text string from the disc is compared with the text string that is embedded in the Playstation //hardware. When these text strings are the same, the disc is interpreted to be authentic and from //the correct region. Bingo! -// + //HOW THE MODCHIP TRICKS THE PLAYSTATION: //The modchip isn't all that of a complicated device: clever reverse engineers found the point on the //Playstation motherboard that carried the text string from the disc and found a way to temporarily block @@ -115,238 +73,256 @@ //with this after about 25 seconds. Because all the possible valid region options are outputted on the //motherboard the Playstation gets a bit confused and simply accepts the inserted disc as authentic; after all, //one of the codes was the same as that of the Playstation hardware... -//Early modchips applied the text strings as long as there was applied power to them, whereby later Playstation +//Early modchips applied the text strings as long as power was applied to them, whereby later Playstation //software could detect whether a modchip was installed. This is circumvented in this application by idling the //modchip after about 25 seconds. The text strings are only tranmitted again when the CD lid is opened and closed //again, to enable playing multi-disc games. This is also called a stealth modchip in marketing-speak. -// -//This code is verified on an ATTiny45 with the 8MHz internal oscillator using a Saleae Logic Analyser, timing is -//reasonable important in this application. -//Version 1 was kindly coded and documented by TheFrietMan, August 20 2015, The Netherlands. -//The Playstation is great but nothing beats our national pride, the Philips CDi! Cheesiness for the win! -// -// -//PINOUT IC: -// ATTiny45, DIP package: -// Pin 1: OUT - PAL SCPH-102 BIOS Data2 -// Pin 2: IN - PAL SCPH-102 BIOS Address18 -// Pin 3: IN - CD lid -// Pin 4: Ground -// Pin 5: OUT - Data -// Pin 6: OUT - Gate -// Pin 7: IN - XLAT !This is also where INT0 lives on ATTiny45! -// Pin 8: Vcc -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include //Include the Flash library to conveniently store the SCExData-arrays in PROGMEM, see http://arduiniana.org/libraries/flash/ - -//BLOODY GLOBAL VARIABLES -//Pins for the Arduino Uno -//int data = 0; //The pin that outputs the SCEE SCEA SCEI string -//int gate = 1; //The pin that gets pulled low to enable data injection on the Playstation motherboard -//int xlat = 2; //On Arduino Uno, Arduino pin 2 is connected to INT0 -//int lid = 3; //The pin that gets connected to the internal CD lid signal; active high -//int biosA18 = 4; //Only used in SCPH-102 PAL mode -//int biosD2 = 5; //Only used in SCPH-102 PAL mode - -//SET THIS TO 1 IF YOU HAVE A PAL SCPH-102 PLAYSTATION AND WANT TO PLAY NTSC DISCS ON A PAL TV WITHOUT A BOOT DISC -//THIS REQUIRES A MODCHIP WITH MORE PINS. I SUGGEST USING AN ATTINY2313. THE PIN-OUT FOR THIS CHIP IS FOUND A BIT UP -boolean PALSCPH102 = 0; - -//Arduino pins for ATTiny45 + + +//-------------------------------------------------- +// New in this version! +//-------------------------------------------------- +//A lot! +// - The PAL SCPH-102 NTSC BIOS-patch works flawlessly! For speed reasons this is implemented in bare +// AVR C. It is functionally identical to the OneChip modchip, this modchip firmware was disassembled, +// documented (available on request, but written in Dutch...) and analyzed with a logic analyzer to +// make sure PsNee works just as well. +// - The code now is segmented in functions which make the program a lot more maintable and readable +// - Timing is perfected, all discs (both backups and originals of PAL and NTSC games) now work in the +// PAL SCPH-102 test machine +// - It was found out that the gate signal doesn't havbe to be hooked up to a PAL SCPH-102 Playstation +// to circumvent the copy protection. This is not tested on other Playstation models so the signal still +// is available +// - The /xlat signal is no longer required to time the PAL SCPH-102 NTSC BIOS-patch +// - Only AVR PORTB is used for compatibility reasons (almost all the AVR chips available have PORTB) + + +//-------------------------------------------------- +// Pinouts! +//-------------------------------------------------- +//FOR ARDUINO UNO (WITH ATMEGA328): +// - Arduino pin 8 = data = ATMega pin 14 +// - Arduino pin 9 = gate = ATMega pin 15 +// - Arduino pin 10 = lid = ATMega pin 16 +// - Arduino pin 11 = biosA18 = ATMega pin 17 +// - Arduino pin 12 = biosD2 = ATMega pin 18 + +//FOR ATTINY25/45/85: +// - Arduino pin 0 = data = ATTiny pin 5 +// - Arduino pin 1 = gate = ATTiny pin 6 +// - Arduino pin 2 = lid = ATTiny pin 7 +// - Arduino pin 3 = biosA18 = ATTiny pin 2 +// - Arduino pin 4 = biosD2 = ATTiny pin 3 + +//-------------------------------------------------- +// Includes! +//-------------------------------------------------- +#include + +//-------------------------------------------------- +// Arduino selection! +//-------------------------------------------------- +#define ARDUINO_UNO //Make that "#define ARDUINO_UNO" if you want to compile for Arduino Uno instead of ATTiny25/45/85 + +#ifdef ARDUINO_UNO +//Pins +int data = 8; //The pin that outputs the SCEE SCEA SCEI string +int gate = 9; //The pin that outputs the SCEE SCEA SCEI string +int lid = 10; //The pin that gets connected to the internal CD lid signal; active high +int biosA18 = 11; //Only used in SCPH-102 PAL mode +int biosD2 = 12; //Only used in SCPH-102 PAL mode +int delay_ntsc = 2350; +int delay_between_bits = 4; +int delay_between_injections = 74; +#endif + +#ifdef ATTINY +//Pins int data = 0; //The pin that outputs the SCEE SCEA SCEI string -int gate = 1; //The pin that gets pulled low to enable data injection on the Playstation motherboard -int xlat = 2; +int gate = 1; +int lid = 2; //The pin that gets connected to the internal CD lid signal; active high int biosA18 = 3; //Only used in SCPH-102 PAL mode -int lid = 4; //The pin that gets connected to the internal CD lid signal; active high -int biosD2 = 5; //Only used in SCPH-102 PAL mode +int biosD2 = 4; //Only used in SCPH-102 PAL mode +int delay_ntsc = 2400; +int delay_between_bits = 4; +int delay_between_injections = 68; +#endif +//-------------------------------------------------- +// Global variables! +//-------------------------------------------------- +//None, just like it should be! -//Flags -boolean flagFirstCycle = 0; //This flag is 1 when the system completes the first cycle of SCEx-string outputting; this is done to stealth the chip up -boolean flagNewPlaystationModel = 0; //This flag is 1 when it is detected that the modchip is running on PU-22, PU-23 or PSOne hardware -boolean flagBIOSAlreadyFooled = 0; //This flag is 1 when the NTSC=>PAL BIOS-patch for PAL SCPH-102 consoles has been applied. It is reset to 0 when the lid is opened and closed again or when the console is turned off and on again. +//-------------------------------------------------- +// Seperate functions! +//-------------------------------------------------- +void NTSC_fix() +{ + //Make sure all pins are inputs + DDRB = 0x00; + //Wait until just before the pulse on BIOS A18 arrives + delay(delay_ntsc); -//The SCPH102BIOSFooler()-function fools the PAL SCPH-102 into thinking that it also can read NTSC discs -//We execute this code when XLAT goes from high to low, indicating that the first copy protection check has been passed -//delay() doesn't work in an interrupt handler, we use delayMicroseconds() instead, that doesn't rely on using interrupts itself -void SCPH102BIOSFooler() + //...And wait here until it actually happened + while(!(PINB & B00001000)) + { + ; //Wait + } + delayMicroseconds(12); + PORTB = B00000000; + DDRB = B00010000; + delayMicroseconds(5); + DDRB = 0x00; +} + +void inject_SCEE() { - boolean biosA18Status = digitalRead(biosA18); - int addressSignalWaitCounter; + //SCEE-array // Start Data Stop + FLASH_ARRAY (boolean, SCEEData, 1,0,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,0); //SCEE: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01011101 00 44 bits total - if (flagBIOSAlreadyFooled == 0) + int bit_counter; + + for (bit_counter = 0; bit_counter < 44; bit_counter = bit_counter + 1) { - for (addressSignalWaitCounter = 0; addressSignalWaitCounter < 50; addressSignalWaitCounter = addressSignalWaitCounter + 1) + if (SCEEData[bit_counter] == 0) + { + pinMode(data, OUTPUT); + digitalWrite(data, 0); + delay(delay_between_bits); + } + else { - if (biosA18Status == 1) - { - delayMicroseconds(50); //Wait a short time - pinMode(biosD2, OUTPUT); - digitalWrite(biosD2, 0); //Pull the Data2-pin low for a millisecond - delayMicroseconds(1000); - pinMode(biosD2, INPUT); //...And release it again - flagBIOSAlreadyFooled = 1; - return; - } + pinMode(data, INPUT); //We make the data pin high-impedance to let the pull-up of the Playstation motherboard make a 1 + delay(delay_between_bits); } } - else - { - return; - } -} + pinMode(data, OUTPUT); + digitalWrite(data, 0); + delay(delay_between_injections); +} -void setup() +void inject_SCEA() { - pinMode(data, INPUT); //The pins are high-impedance when configured as inputs so they don't interfere with the Playstation mortherboard circuitry - pinMode(gate, INPUT); - pinMode(lid, INPUT); - pinMode(xlat, INPUT); + //SCEE-array // Start Data Stop + FLASH_ARRAY (boolean, SCEAData, 1,0,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0); //SCEA: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01111101 00 + + int bit_counter; - if (PALSCPH102 != 0) + for (bit_counter = 0; bit_counter < 44; bit_counter = bit_counter + 1) { - pinMode(biosA18, INPUT); //Only activate the BIOS-pins when connected to a PAL SCPH-102 - pinMode(biosD2, INPUT); - - //We make an interrupt for XLAT, as we need this signal to detect when we can do our BIOS-magic. The function SCPH102BIOSFooler is ran when the XLAT-pin makes - //a transistion from high to low, the other code is temporarily paused. Only use this when the code is used on a PAL SCPH-102 - attachInterrupt(0, SCPH102BIOSFooler, FALLING); //Interrupt 0 is pin 7 on ATTiny45 + if (SCEAData[bit_counter] == 0) + { + pinMode(data, OUTPUT); + digitalWrite(data, 0); + delay(delay_between_bits); + } + else + { + pinMode(data, INPUT); //We make the data pin high-impedance to let the pull-up of the Playstation motherboard make a 1 + delay(delay_between_bits); + } } - //Determine on which Playstation we are working by watching the gate-signal; we are running on a PU-22, PU-23 or PSOne when there is a clock signal present - //We are taking 10 samples of the gate-signal. As we can't really know the frequency of the clock signal that may or may not be present on this signal, we - //simply take ten samples of the signal and store them in an array. When both 0's and 1's are stored in the array, this means that there is a clock signal - //on the gate-pin. When all the elements in the array are the same, there is no clock signal available and PsNee is installed in an older model Playstation. - boolean gateSamples[10]; - int gateSamplesCounter; - boolean sampleLowDetected = 0; - boolean sampleHighDetected = 0; + pinMode(data, OUTPUT); + digitalWrite(data, 0); + delay(delay_between_injections); +} - for (gateSamplesCounter = 0; gateSamplesCounter < 10; gateSamplesCounter = gateSamplesCounter + 1) - { - gateSamples[gateSamplesCounter] = digitalRead(gate); - } +void inject_SCEI() +{ + //SCEE-array // Start Data Stop + FLASH_ARRAY (boolean, SCEIData, 1,0,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,1,1,0,1,1,0,1,0,0); //SCEI: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01101101 00 - for(gateSamplesCounter = 0; gateSamplesCounter < 10; gateSamplesCounter = gateSamplesCounter + 1) + int bit_counter; + + for (bit_counter = 0; bit_counter < 44; bit_counter = bit_counter + 1) { - if (gateSamples[gateSamplesCounter] == 0) - { - sampleLowDetected = 1; + if (SCEIData[bit_counter] == 0) + { + pinMode(data, OUTPUT); + digitalWrite(data, 0); + delay(delay_between_bits); } else { - sampleHighDetected = 1; + pinMode(data, INPUT); //We make the data pin high-impedance to let the pull-up of the Playstation motherboard make a 1 + delay(delay_between_bits); } - } + } + + pinMode(data, OUTPUT); + digitalWrite(data, 0); + delay(delay_between_injections); +} + +void inject_multiple_times(int number_of_injection_cycles) +{ + int cycle_counter; + + for(cycle_counter = 0; cycle_counter < number_of_injection_cycles; cycle_counter = cycle_counter + 1) + { + inject_SCEE(); + inject_SCEA(); + inject_SCEI(); + } +} + +void inject_playstation() +{ + //Variables + int loop_counter; + + //Code + NTSC_fix(); - if ((sampleLowDetected && sampleHighDetected) == 1) + delay(6900); + digitalWrite(data, 0); + pinMode(data, OUTPUT); + delay(100); + + pinMode(gate, OUTPUT); + digitalWrite(gate, 0); + + for (loop_counter = 0; loop_counter < 25; loop_counter = loop_counter + 1) { - flagNewPlaystationModel = 1; + inject_SCEE(); } + pinMode(gate, INPUT); + pinMode(data, INPUT); + delay(11000); + + pinMode(gate, OUTPUT); + digitalWrite(gate, 0); + + for (loop_counter = 0; loop_counter < 60; loop_counter = loop_counter + 1) + { + inject_SCEE(); + } - delay(1000); //Wait a second before we're really heading off + pinMode(gate, INPUT); + pinMode(data, INPUT); } -void loop() -{ //The bitstreams are reversed (because LSB) and inverted (because the buffer we're injecting our signal after also inverted it's input) - //VARIABLES // Start Data Stop - FLASH_ARRAY (boolean, SCEEData, 1,0,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,0); //SCEE: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01011101 00 44 bits total - FLASH_ARRAY (boolean, SCEAData, 1,0,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0); //SCEA: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01111101 00 - FLASH_ARRAY (boolean, SCEIData, 1,0,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,0,1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,1,1,0,1,1,0,1,0,0); //SCEI: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01101101 00 - int arraycounter; - int datacounter; - int slicercounter; - boolean lidstatus = digitalRead(lid); +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//-------------------------------------------------- +// Setup function - execution starts here! +//-------------------------------------------------- +void setup() +{ + inject_playstation(); +} - if ((flagFirstCycle == 0) || ((flagFirstCycle != 0) && (lidstatus != 0))) //Only execute the modchip code when the Playstation has just booted or when a new disc needs to be inserted on an already running machine +//---------------------------------------------------------------- +// Loop function - executes after the initial injection cycle +//---------------------------------------------------------------- +void loop() +{ + if(lid == 0) { - if ((flagFirstCycle != 0) && (lidstatus != 0)) - { - flagBIOSAlreadyFooled == 0; //When this isn't the first time the modchip does it's thing and the lid has been opened, indicate that the PAL=>NTSC BIOS-patch may be applied again - } - - delay(50); //Extra delay to compensate for the state-switching of the CD lid - if (lidstatus == 0) //Only do your thing when the lid is closed again - { - delay(50); //Just wait a second until the coast is clear - pinMode(gate, OUTPUT); - digitalWrite(gate, 0); //Pull to ground to enable data injecting - - for (datacounter = 0; datacounter < 31; datacounter = datacounter + 1) //One cycle of SCEx-string outputting takes approximately 744 ms; we want to go on for about 25 seconds so we output the cycle 30 times - { - for (arraycounter = 0; arraycounter < 44; arraycounter = arraycounter + 1) - { - if (SCEEData[arraycounter] == 0) - { - for (slicercounter = 0; slicercounter < 15; slicercounter = slicercounter + 1) //This for-loop slices the data signal when it is 0 in small chunks of 130us and do this 14 times; this way, each block of sliced data is about 4ms long, of 250bps - { - pinMode(data, OUTPUT); //We pull the data pin to ground to force a 0 - digitalWrite(data, 0); - delayMicroseconds(130); - - pinMode(data, INPUT); //We make it high-impedance again to let at least some of the CD tracking signal through - delayMicroseconds(130); - } - } - else - { - pinMode(data, INPUT); //We make the data pin high-impedance to let the pull-up of the Playstation motherboard make a 1 - delay(4); - } - } - delay(64); //According to the logic analyser the time between two bitstreams now approximates 72 ms on an ATTiny45 with built-in 8MHz oscillator, just like the doctor ordered - - for (arraycounter = 0; arraycounter < 44; arraycounter = arraycounter + 1) - { - if (SCEAData[arraycounter] == 0) - { - for (slicercounter = 0; slicercounter < 15; slicercounter = slicercounter + 1) //This for-loop slices the data signal when it is 0 in small chunks of 130us; this way, each block of sliced data is about 4ms long, of 250bps - { - pinMode(data, OUTPUT); //We pull the data pin to ground to force a 0 - digitalWrite(data, 0); - delayMicroseconds(130); - - pinMode(data, INPUT); //We make it high-impedance again to let at least some of the CD tracking signal through - delayMicroseconds(130); - } - } - else - { - pinMode(data, INPUT); //We make the data pin high-impedance to let the pull-up of the Playstation motherboard make a 1 - delay(4); - } - } - delay(64); - - for (arraycounter = 0; arraycounter < 44; arraycounter = arraycounter + 1) - { - if (SCEIData[arraycounter] == 0) - { - for (slicercounter = 0; slicercounter < 15; slicercounter = slicercounter + 1) //This for-loop slices the data signal when it is 0 in small chunks of 130us; this way, each block of sliced data is about 4ms long, of 250bps - { - pinMode(data, OUTPUT); //We pull the data pin to ground to force a 0 - digitalWrite(data, 0); - delayMicroseconds(130); - - pinMode(data, INPUT); //We make it high-impedance again to let at least some of the CD tracking signal through - delayMicroseconds(130); - } - } - else - { - pinMode(data, INPUT); //We make the data pin high-impedance to let the pull-up of the Playstation motherboard make a 1 - delay(4); - } - } - delay(64); - } - pinMode(data, INPUT); //Make all outputting pins high-impedance again when we're finished - pinMode(gate, INPUT); - flagFirstCycle = 1; //We completed the initial round of SCEx-outputting; only do this again when a new CD is inserted while the Playstation is turned on! - } + while(lid != 1); //Wait until the lid is closed again (after being opened) to initiate a new injection cycle + inject_playstation(); } }