From 18d66421f749215e301721b03bd356fbc1776e07 Mon Sep 17 00:00:00 2001 From: kalymos Date: Fri, 7 Feb 2025 16:21:02 +0100 Subject: [PATCH] nexgen --- .../PSNee_V8.5}/BIOS_patching.h | 0 .../PSNee_V8 => PSNee_V8.5/PSNee_V8.5}/MUC.h | 0 .../PSNee_V8.5}/PSNee_V8.ino | 0 .../PSNee_V8.5}/settings.h | 0 PsNee.ino | 457 ------------------ changelog | 151 ------ 6 files changed, 608 deletions(-) rename {PSNee_V8/PSNee_V8 => PSNee_V8.5/PSNee_V8.5}/BIOS_patching.h (100%) rename {PSNee_V8/PSNee_V8 => PSNee_V8.5/PSNee_V8.5}/MUC.h (100%) rename {PSNee_V8/PSNee_V8 => PSNee_V8.5/PSNee_V8.5}/PSNee_V8.ino (100%) rename {PSNee_V8/PSNee_V8 => PSNee_V8.5/PSNee_V8.5}/settings.h (100%) delete mode 100644 PsNee.ino delete mode 100644 changelog diff --git a/PSNee_V8/PSNee_V8/BIOS_patching.h b/PSNee_V8.5/PSNee_V8.5/BIOS_patching.h similarity index 100% rename from PSNee_V8/PSNee_V8/BIOS_patching.h rename to PSNee_V8.5/PSNee_V8.5/BIOS_patching.h diff --git a/PSNee_V8/PSNee_V8/MUC.h b/PSNee_V8.5/PSNee_V8.5/MUC.h similarity index 100% rename from PSNee_V8/PSNee_V8/MUC.h rename to PSNee_V8.5/PSNee_V8.5/MUC.h diff --git a/PSNee_V8/PSNee_V8/PSNee_V8.ino b/PSNee_V8.5/PSNee_V8.5/PSNee_V8.ino similarity index 100% rename from PSNee_V8/PSNee_V8/PSNee_V8.ino rename to PSNee_V8.5/PSNee_V8.5/PSNee_V8.ino diff --git a/PSNee_V8/PSNee_V8/settings.h b/PSNee_V8.5/PSNee_V8.5/settings.h similarity index 100% rename from PSNee_V8/PSNee_V8/settings.h rename to PSNee_V8.5/PSNee_V8.5/settings.h diff --git a/PsNee.ino b/PsNee.ino deleted file mode 100644 index 74aa9d3..0000000 --- a/PsNee.ino +++ /dev/null @@ -1,457 +0,0 @@ -// PsNee / psxdev.net version -// For Arduino and ATtiny -// -// Quick start: Select your hardware via the #defines, compile + upload the code, install in PSX. -// There are some pictures in the development thread ( http://www.psxdev.net/forum/viewtopic.php?f=47&t=1262&start=120 ) -// Beware to use the PSX 3.5V / 3.3V power, *NOT* 5V! The installation pictures include an example. -// -// Arduinos: -// Use #define ARDUINO_328_BOARD for the following: -// - Arduino Pro Mini @8Mhz and @16Mhz (supported, tested) -// - Arduino Uno @8Mhz and @16Mhz (supported, tested) -// Use #define ARDUINO_32UX_BOARD for the following: -// - Pro Micro (supported, tested) -// - Arduino Leonardo (supported, untested) - -// ATtiny: -// - ATtiny85: Should work the same as ATtiny45 (supported, untested) -// - ATtiny45: LFUSE 0xE2 HFUSE 0xDF > internal oscillator, full 8Mhz speed (supported, tested) -// - ATtiny25: Should work the same as ATtiny45 but doesn't have enough Flash nor RAM for PSNEEDEBUG (supported, untested) -// - Use #define ATTINY_X5 -// -// To use ATtiny with the Arduino environment, an ATtiny core has to be installed. -// -// PAL PM-41 consoles are supported with #define APPLY_PSONE_PAL_BIOS_PATCH, -// but only on boards with ATmega chips (Arduinos). -// Also, the Arduino must be flashed using SPI (deleting the bootloader), since I expect a signal ~1 second after power on. -// -// This code defaults to multi-region, meaning it will unlock PAL, NTSC-U and NTSC-J machines. -// You can optimize boot times for your console further. See "// inject symbols now" in the main loop. - -//+-------------------------------------------------------------------------------------------+ -//| Choose your hardware! | -//+-------------------------------------------------------------------------------------------+ -// -// To fix the timer problem with APPLY_PSONE_PAL_BIOS_PATCH look at line 223 -// -// 2 main branches available: -// - ATmega based > easy to use, fast and nice features for development, recommended -// - ATtiny based > for minimal installs - -// ATmega32U4/32U2 boards (as in the Pro Micro) have to use different pinouts than the 'regular' -// Arduino ATMega328's. For these, a different define must be used. - -//#define ARDUINO_328_BOARD -//#define ARDUINO_32UX_BOARD -//#define ATTINY_X5 - -//#define APPLY_PSONE_PAL_BIOS_PATCH - -//#define PSNEEDEBUG - -#include - -#if defined(ARDUINO_328_BOARD) -// board pins (code requires porting to reflect any changes) -#if defined(APPLY_PSONE_PAL_BIOS_PATCH) -#define BIOS_A18 3 // connect to PSOne BIOS A18 (pin 31 on that chip) -#define BIOS_D2 4 // connect to PSOne BIOS D2 (pin 15 on that chip) -#endif -#define sqck 6 // connect to PSX HC-05 SQCK pin -#define subq 7 // connect to PSX HC-05 SUBQ pin -#define data 8 // connect to point 6 in old modchip diagrams -#define gate_wfck 9 // connect to point 5 in old modchip diagrams -// MCU I/O definitions -#define SUBQPORT PIND // MCU port for the 2 SUBQ sampling inputs -#define SQCKBIT 6 // PD6 "SQCK" < Mechacon pin 26 (PU-7 and early PU-8 Mechacons: pin 41) -#define SUBQBIT 7 // PD7 "SUBQ" < Mechacon pin 24 (PU-7 and early PU-8 Mechacons: pin 39) -#define GATEWFCKPORT PINB // MCU port for the gate input (used for WFCK) -#define DATAPORT PORTB // MCU port for the gate input (used for WFCK) -#define GATEWFCKBIT 1 // PB1 -#define DATABIT 0 // PB0 -#if defined(APPLY_PSONE_PAL_BIOS_PATCH) -#define BIOSPATCHPORTIN PIND -#define BIOSPATCHPORTOUT PORTD -#define BIOSPATCHDDR DDRD -#define BIOS_A18_BIT 4 -#define BIOS_D2_BIT 5 -#endif -#elif defined(ARDUINO_32UX_BOARD) // ATMega32U2/ATMega32U4 -#if defined(APPLY_PSONE_PAL_BIOS_PATCH) -#define BIOS_A18 2 -#define BIOS_D2 3 -#endif -#define sqck 4 -#define subq 6 -#define data 8 -#define gate_wfck 9 -// MCU I/O definitions -#define SUBQPORT PIND -#define SQCKBIT 1 // -#define SUBQBIT 0 // -#define GATEWFCKPORT PINB -#define DATAPORT PORTB -#define GATEWFCKBIT 1 // -#define DATABIT 3 // -#if defined(APPLY_PSONE_PAL_BIOS_PATCH) -#define BIOSPATCHPORTIN PIND -#define BIOSPATCHPORTOUT PORTD -#define BIOSPATCHDDR DDRD -#define BIOS_A18_BIT 2 //PB4 -#define BIOS_D2_BIT 3 //PB5 -#endif -#elif defined(ATTINY_X5) // ATtiny 25/45/85 -// extras -#define USINGSOFTWARESERIAL -// board pins (Do not change. Changing pins requires adjustments to MCU I/O definitions) -#define sqck 0 -#define subq 1 -#define data 2 -#define gate_wfck 4 -#define debugtx 3 -// MCU I/O definitions -#define SUBQPORT PINB -#define SQCKBIT 0 -#define SUBQBIT 1 -#define GATEWFCKPORT PINB -#define DATAPORT PORTB -#define GATEWFCKBIT 4 -#define DATABIT 2 -#if defined(APPLY_PSONE_PAL_BIOS_PATCH) -#error "ATtiny does not support PAL PSOne patch yet!" -#endif -#else -#error "Select a board!" -#endif - -#if defined(PSNEEDEBUG) && defined(USINGSOFTWARESERIAL) -#include -SoftwareSerial mySerial(-1, 3); // RX, TX. (RX -1 = off) -#define DEBUG_PRINT(x) mySerial.print(x) -#define DEBUG_PRINTHEX(x) mySerial.print(x, HEX) -#define DEBUG_PRINTLN(x) mySerial.println(x) -#define DEBUG_FLUSH mySerial.flush() -#elif defined(PSNEEDEBUG) && !defined(USINGSOFTWARESERIAL) -#define DEBUG_PRINT(x) Serial.print(x) -#define DEBUG_PRINTHEX(x) Serial.print(x, HEX) -#define DEBUG_PRINTLN(x) Serial.println(x) -#define DEBUG_FLUSH Serial.flush() -#else -#define DEBUG_PRINT(x) -#define DEBUG_PRINTHEX(x) -#define DEBUG_PRINTLN(x) -#define DEBUG_FLUSH -#endif - -#define NOP __asm__ __volatile__ ("nop\n\t") - -// Setup() detects which (of 2) injection methods this PSX board requires, then stores it in pu22mode. -boolean pu22mode; - -//Timing -const int delay_between_bits = 4000; // 250 bits/s (microseconds) (ATtiny 8Mhz works from 3950 to 4100) -const int delay_between_injections = 90; // 72 in oldcrow. PU-22+ work best with 80 to 100 (milliseconds) - -// borrowed from AttyNee. Bitmagic to get to the SCEX strings stored in flash (because Harvard architecture) -bool readBit(int index, const unsigned char *ByteSet) -{ - int byte_index = index >> 3; - byte bits = pgm_read_byte(&(ByteSet[byte_index])); - int bit_index = index & 0x7; // same as (index - byte_index<<3) or (index%8) - byte mask = 1 << bit_index; - return (0 != (bits & mask)); -} - -void inject_SCEX(char region) -{ - //SCEE: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01011101 00 - //SCEA: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01111101 00 - //SCEI: 1 00110101 00, 1 00111101 00, 1 01011101 00, 1 01101101 00 - //const boolean SCEEData[44] = {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}; - //const boolean SCEAData[44] = {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}; - //const boolean SCEIData[44] = {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}; - static const PROGMEM unsigned char SCEEData[] = {0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11101010, 0b00000010}; - static const PROGMEM unsigned char SCEAData[] = {0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11111010, 0b00000010}; - static const PROGMEM unsigned char SCEIData[] = {0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11011010, 0b00000010}; - - // pinMode(data, OUTPUT) is used more than it has to be but that's fine. - for (byte bit_counter = 0; bit_counter < 44; bit_counter++) - { - if (readBit(bit_counter, region == 'e' ? SCEEData : region == 'a' ? SCEAData : SCEIData) == 0) - { - pinMode(data, OUTPUT); - bitClear(GATEWFCKPORT, DATABIT); // data low - delayMicroseconds(delay_between_bits); - } - else - { - if (pu22mode) { - pinMode(data, OUTPUT); - unsigned long now = micros(); - do { - bool wfck_sample = bitRead(GATEWFCKPORT, GATEWFCKBIT); - bitWrite(DATAPORT, DATABIT, wfck_sample); // output wfck signal on data pin - } - while ((micros() - now) < delay_between_bits); - } - else { // PU-18 or lower mode - pinMode(data, INPUT); - delayMicroseconds(delay_between_bits); - } - } - } - - pinMode(data, OUTPUT); - bitClear(GATEWFCKPORT, DATABIT); // pull data low - delay(delay_between_injections); -} - -void NTSC_fix() { -#if defined(APPLY_PSONE_PAL_BIOS_PATCH) - pinMode(BIOS_A18, INPUT); - pinMode(BIOS_D2, INPUT); - - delay(100); // this is right after SQCK appeared. wait a little to avoid noise - while (!bitRead(BIOSPATCHPORTIN, BIOS_A18_BIT)) - { - ; //wait for stage 1 A18 pulse - } - delay(1350); //wait through stage 1 of A18 activity - - noInterrupts(); // start critical section - while (!bitRead(BIOSPATCHPORTIN, BIOS_A18_BIT)) - { - ; //wait for priming A18 pulse - } - delayMicroseconds(17); // min 13us max 17us for 16Mhz ATmega (maximize this when tuning!) - bitClear(BIOSPATCHPORTOUT, BIOS_D2_BIT); // store a low - bitSet(BIOSPATCHDDR, BIOS_D2_BIT); // D2 = output. drags line low now - delayMicroseconds(4); // min 2us for 16Mhz ATmega, 8Mhz requires 3us (minimize this when tuning, after maximizing first us delay!) - bitClear(DDRD, BIOS_D2_BIT); // D2 = input / high-z - interrupts(); // end critical section - - // not necessary but I want to make sure these pins are now high-z again - pinMode(BIOS_A18, INPUT); - pinMode(BIOS_D2, INPUT); -#endif -} - -//-------------------------------------------------- -// Setup -//-------------------------------------------------- - -void setup() -{ - pinMode(data, INPUT); - pinMode(gate_wfck, INPUT); - pinMode(subq, INPUT); // PSX subchannel bits - pinMode(sqck, INPUT); // PSX subchannel clock - -#if defined(PSNEEDEBUG) && defined(USINGSOFTWARESERIAL) - pinMode(debugtx, OUTPUT); // software serial tx pin - mySerial.begin(115200); // 13,82 bytes in 12ms, max for softwareserial. (expected data: ~13 bytes / 12ms) // update: this is actually quicker -#elif defined(PSNEEDEBUG) && !defined(USINGSOFTWARESERIAL) - Serial.begin(500000); // 60 bytes in 12ms (expected data: ~26 bytes / 12ms) // update: this is actually quicker - DEBUG_PRINT("MCU frequency: "); DEBUG_PRINT(F_CPU); DEBUG_PRINTLN(" Hz"); - DEBUG_PRINTLN("Waiting for SQCK.."); -#endif - -#if defined(ARDUINO_328_BOARD) || defined(ARDUINO_32UX_BOARD) - pinMode(LED_BUILTIN, OUTPUT); // Blink on injection / debug. - digitalWrite(LED_BUILTIN, HIGH); // mark begin of setup -#endif - - // wait for console power on and stable signals - while (!digitalRead(sqck)); - while (!digitalRead(gate_wfck)); - - // if enabled: patches PAL PSOne consoles so they start all region games - NTSC_fix(); - - // Board detection - // - // GATE: __----------------------- // this is a PU-7 .. PU-20 board! - // - // WFCK: __-_-_-_-_-_-_-_-_-_-_-_- // this is a PU-22 or newer board! - - unsigned int highs = 0, lows = 0; - unsigned long now = millis(); - do { - if (digitalRead(gate_wfck) == 1) highs++; - if (digitalRead(gate_wfck) == 0) lows++; - delayMicroseconds(200); // good for ~5000 reads in 1s - } - while ((millis() - now) < 1000); // sample 1s - - // typical readouts - // PU-22: highs: 2449 lows: 2377 - if (lows > 100) { - pu22mode = 1; - } - else { - pu22mode = 0; - } - -#ifdef ATTINY_X5 - DEBUG_PRINT("m "); DEBUG_PRINTLN(pu22mode); -#else - DEBUG_PRINT("highs: "); DEBUG_PRINT(highs); DEBUG_PRINT(" lows: "); DEBUG_PRINTLN(lows); - DEBUG_PRINT("pu22mode: "); DEBUG_PRINTLN(pu22mode); - // Power saving - // Disable the ADC by setting the ADEN bit (bit 7) of the ADCSRA register to zero. - ADCSRA = ADCSRA & B01111111; - // Disable the analog comparator by setting the ACD bit (bit 7) of the ACSR register to one. - ACSR = B10000000; - // Disable digital input buffers on all analog input pins by setting bits 0-5 of the DIDR0 register to one. - DIDR0 = DIDR0 | B00111111; -#endif - -#if defined(ARDUINO_328_BOARD) || defined(ARDUINO_32UX_BOARD) - digitalWrite(LED_BUILTIN, LOW); // setup complete -#endif - - DEBUG_FLUSH; // empty serial transmit buffer -} - -void loop() -{ - static byte scbuf [12] = { 0 }; // We will be capturing PSX "SUBQ" packets, there are 12 bytes per valid read. - static unsigned int timeout_clock_counter = 0; - static byte bitbuf = 0; // SUBQ bit storage - static bool sample = 0; - static byte bitpos = 0; - byte scpos = 0; // scbuf position - - // start with a small delay, which can be necessary in cases where the MCU loops too quickly - // and picks up the laster SUBQ trailing end - delay(1); - - noInterrupts(); // start critical section -start: - // Capture 8 bits for 12 runs > complete SUBQ transmission - bitpos = 0; - for (; bitpos < 8; bitpos++) { - while (bitRead(SUBQPORT, SQCKBIT) == 1) { - // wait for clock to go low.. - // a timeout resets the 12 byte stream in case the PSX sends malformatted clock pulses, as happens on bootup - timeout_clock_counter++; - if (timeout_clock_counter > 1000) { - scpos = 0; // reset SUBQ packet stream - timeout_clock_counter = 0; - bitbuf = 0; - goto start; - } - } - - // wait for clock to go high.. - while ((bitRead(SUBQPORT, SQCKBIT)) == 0); - - sample = bitRead(SUBQPORT, SUBQBIT); - bitbuf |= sample << bitpos; - - timeout_clock_counter = 0; // no problem with this bit - } - - // one byte done - scbuf[scpos] = bitbuf; - scpos++; - bitbuf = 0; - - // repeat for all 12 bytes - if (scpos < 12) { - goto start; - } - interrupts(); // end critical section - - // log SUBQ packets. We only have 12ms to get the logs written out. Slower MCUs get less formatting. -#ifdef ATTINY_X5 - if (!(scbuf[0] == 0 && scbuf[1] == 0 && scbuf[2] == 0 && scbuf[3] == 0)) { // a bad sector read is all 0 except for the CRC fields. Don't log it. - for (int i = 0; i < 12; i++) { - if (scbuf[i] < 0x10) { - DEBUG_PRINT("0"); // padding - } - DEBUG_PRINTHEX(scbuf[i]); - } - DEBUG_PRINTLN(""); - } -#else - if (!(scbuf[0] == 0 && scbuf[1] == 0 && scbuf[2] == 0 && scbuf[3] == 0)) { - for (int i = 0; i < 12; i++) { - if (scbuf[i] < 0x10) { - DEBUG_PRINT("0"); // padding - } - DEBUG_PRINTHEX(scbuf[i]); - DEBUG_PRINT(" "); - } - DEBUG_PRINTLN(""); - } -#endif - - // check if read head is in wobble area - // We only want to unlock game discs (0x41) and only if the read head is in the outer TOC area. - // We want to see a TOC sector repeatedly before injecting (helps with timing and marginal lasers). - // All this logic is because we don't know if the HC-05 is actually processing a getSCEX() command. - // Hysteresis is used because older drives exhibit more variation in read head positioning. - // While the laser lens moves to correct for the error, they can pick up a few TOC sectors. - static byte hysteresis = 0; - boolean isDataSector = (((scbuf[0] & 0x40) == 0x40) && (((scbuf[0] & 0x10) == 0) && ((scbuf[0] & 0x80) == 0))); - - if ( - (isDataSector && scbuf[1] == 0x00 && scbuf[6] == 0x00) && // [0] = 41 means psx game disk. the other 2 checks are garbage protection - (scbuf[2] == 0xA0 || scbuf[2] == 0xA1 || scbuf[2] == 0xA2 || // if [2] = A0, A1, A2 .. - (scbuf[2] == 0x01 && (scbuf[3] >= 0x98 || scbuf[3] <= 0x02) ) ) // .. or = 01 but then [3] is either > 98 or < 02 - ) { - hysteresis++; - } - else if ( hysteresis > 0 && - ((scbuf[0] == 0x01 || isDataSector) && (scbuf[1] == 0x00 /*|| scbuf[1] == 0x01*/) && scbuf[6] == 0x00) - ) { // This CD has the wobble into CD-DA space. (started at 0x41, then went into 0x01) - hysteresis++; - } - else if (hysteresis > 0) { - hysteresis--; // None of the above. Initial detection was noise. Decrease the counter. - } - - // hysteresis value "optimized" using very worn but working drive on ATmega328 @ 16Mhz - // should be fine on other MCUs and speeds, as the PSX dictates SUBQ rate - if (hysteresis >= 14) { - // If the read head is still here after injection, resending should be quick. - // Hysteresis naturally goes to 0 otherwise (the read head moved). - hysteresis = 11; - -#ifdef ATTINY_X5 - DEBUG_PRINTLN("!"); -#else - DEBUG_PRINTLN("INJECT!INJECT!INJECT!INJECT!INJECT!INJECT!"); -#endif -#if defined(ARDUINO_328_BOARD) || defined(ARDUINO_32UX_BOARD) - digitalWrite(LED_BUILTIN, HIGH); -#endif - - pinMode(data, OUTPUT); - digitalWrite(data, 0); // pull data low - if (!pu22mode) { - pinMode(gate_wfck, OUTPUT); - digitalWrite(gate_wfck, 0); - } - - // HC-05 waits for a bit of silence (pin low) before it begins decoding. - delay(delay_between_injections); - // inject symbols now. 2 x 3 runs seems optimal to cover all boards - for (byte loop_counter = 0; loop_counter < 2; loop_counter++) - { - inject_SCEX('e'); // e = SCEE, a = SCEA, i = SCEI - inject_SCEX('a'); // injects all 3 regions by default - inject_SCEX('i'); // optimize boot time by sending only your console region letter (all 3 times per loop) - } - - if (!pu22mode) { - pinMode(gate_wfck, INPUT); // high-z the line, we're done - } - pinMode(data, INPUT); // high-z the line, we're done -#if defined(ARDUINO_328_BOARD) || defined(ARDUINO_32UX_BOARD) - digitalWrite(LED_BUILTIN, LOW); -#endif - } - // keep catching SUBQ packets forever -} diff --git a/changelog b/changelog deleted file mode 100644 index eba6e4b..0000000 --- a/changelog +++ /dev/null @@ -1,151 +0,0 @@ - -------------------------------------------------- -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 --------------------------------------------------------------- - New in this version! V6 --------------------------------------------------------------- -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) - -------------------------------------------------------------- -A minor detail: The lid detection is missing its digitalRead() ;p -psxdev -------------------------------------------------------------- -Update 7th of May 2017 -Branched and tweaked for use with the Position 0 switch on a PSX laser. -(Requires a bit of sticky tape at the point where the switch touches the laser assembly.) -This allows deterministic SCEX injections, without relying on timing. Also gets rid of connection wires for LID and RESET. -WIP! -psxdev --------------------------------------------------------------- -Update 15th of May 2017 -PSNee now watches the subchannel data and looks at the position information contained within. -This allows deterministic SCEX injections. It knows (almost) exactly when to inject the SCEX string. -Therefore it is now a stealth modchip :) -Required connections: GND, VCC, data, gate, SQCL, SUBQ -No more need to watch the PSX reset or lid open signals or any other typical modchip points (like "sync") -WIP! Only tested on PU-18 board. Should work fine on PU-7, PU-8, PU-18 and PU-20. -Will need adaption for PU-22 to PU-41 (SCPH-750x, 900x and PSOne). -Note: Once this is installed in a PSX, mind the Pin13 LED that many Arduino boards have. Do not upload new sketches while the PSX is on! -(If the PSX is on while uploading a sketch (making the LED blink), a voltage will be fed back into the SCLK pin on the HC-05 in the PSX. -This didn't break my PSX in testing but it does stun the chip and halt CD operation. I'm thinking of a better method to do this but for now I need Arduino pin13..) -Very much recommended to install a 3.3V chip! -psxdev -------------------------------------------------------------- -Update 27th of May 2017 -This version is compatible with 8Mhz and 16Mhz ATmega328 / Arduino boards. -It uses polling to grab the SUBQ packets. This works better than relying on interrupts. -I even have a few cycles to spare on a 8Mhz chip! -psxdev ------------------------------------------------------------- -Update 31st May 2017 - -- supports all motherboard versions except PU-41 (PAL) (will get to it!) -- WFCK modulated injection method for PU-22 and up, just like the last multimode 3 chips -- minimized CD controller interference: PsNee only ever speaks when it has to (also: full stealth) -- not relying on BIOS delays: perfect boot disregarding extension cards etc -- might not be bug free! I'm just one guy and testing on a dozen consoles takes time ;) -psxdev ------------------------------------------------------------- -Update 4 June 2017 -- unified SCEX injection function / easier to read code -- PU-22+ now work without the WFCK wire (but depends on tight timings, tested on 8 and 16Mhz mcu) -- interrupts disabled while sampling SUBQ > much better performance capturing all events correctly -- now blinks the built-in LED on injections for debugging -psxdev - -------------------------------------------------------------- -Updat 29 June 2017 -- final modchip function I / Os: SQCK, SCLK, data, gate_wfck -- hysteresis for injections, fixes anti-mod occasionally triggering when using worn drives -- optimized injection timing for multi-region, multi BIOS versions (Sony added more protection checks over time) -- first attempt to make it more portable to other Arduino variants -- auto console detection works reliably, with and without Arduino bootloader present -- pin assignments changed for practical / installation reasons (ICSP capability, wire routing) -- so many changes, it surely contains all new bugs ;) - -Pin assignments are finalized. We can start producing final installation images / help! -As always, I appreciate code reviews and bug fixes. I'm sorry some of it got so messy ;p -psxdev ---------------------------------------------------------------- -Update 9 July 2017 - -Sure. Consider it work in progress quality ;) -Main changes: -- figured out ATtiny pin assignments :p -- RAM use reduced by only storing the "SCE" part of the license string once. Using a somewhat farfetched method. Maybe someone can make it nicer, without the recursion and over engineering? :p -- tried getting debug prints but it doesn't look like it'll happen (on ATtiny45), too little RAM > the chip crashes -- SUBQ sampling timing reverted to sample while clock is low, instead of right after it goes high - --------------------------------------------------------------- - -Update: 10 July 2017 - -- finished porting to ATtinyX5 (25,45,85 although the 25 has too little resources. for now.) -- store the licensing symbols in flash again, frees a lot of RAM -- bit retrieval code lifted from AttyNee (Nice work guys!) -- extra RAM allows SoftwareSerial debugging prints on an ATtiny45! -- nicer intro readme ;p - --------------------------------------------------------------- - -Update: 16 July 2017 - --The BIOS patch works! -For now it only supports Arduino boards (ATmega chips). -Also, the Arduino must either be powered on first or have no bootloader present (flashed using SPI) since I expect a signal ~1 second after power on. -8Mhz boards are also supported. - ------------------------------------------------------------- - - Update: 16 August 2017 - - -changed the timing for the PAL PM-41 patch to make it more reliable (I had it failing occasionally). - Also I added a warning for people not to use 5V. -