diff --git a/PSNee/BIOS_patching.h b/PSNee/BIOS_patching.h index 803d6ac..fb6ec27 100644 --- a/PSNee/BIOS_patching.h +++ b/PSNee/BIOS_patching.h @@ -1,84 +1,141 @@ #pragma once -void Timer_Start(void); -void Timer_Stop(void); +#ifdef BIOS_PATCH -extern volatile uint8_t count_isr; -extern volatile uint32_t microsec; -extern volatile uint32_t millisec; + volatile uint8_t impulse = 0; + volatile uint8_t patch = 0; -volatile uint8_t impulse = 0; -volatile uint8_t patch = 0; + #ifdef INTERRUPT_RISING -#if defined(SCPH_102) || defined(SCPH_100) || defined(SCPH_7000_9000) || defined(SCPH_5500) || defined(SCPH_3500_5000) || defined(SCPH_3000) || defined(SCPH_1000) + ISR(PIN_AX_INTERRUPT_VECTOR) { + impulse++; + if (impulse == TRIGGER){ // If impulse reaches the value defined by TRIGGER, the following actions are performed: + _delay_us(HOLD); + PIN_DX_OUTPUT; + _delay_us(PATCHING); + PIN_DX_INPUT; + PIN_AX_INTERRUPT_DISABLE; - ISR(PIN_AX_INTERRUPT_VECTOR) { - impulse++; - if (impulse == TRIGGER){ // If impulse reaches the value defined by TRIGGER, the following actions are performed: - HOLD; - #ifdef HIGH_PATCH - PIN_DX_SET; - #endif - PIN_DX_OUTPUT; - PATCHING; - #ifdef HIGH_PATCH - PIN_DX_CLEAR; - #endif - PIN_DX_INPUT; - PIN_AX_INTERRUPT_DISABLE; - - impulse = 0; - patch = 1; // patch is set to 1, indicating that the first patch is completed. + impulse = 0; + patch = 1; // patch is set to 1, indicating that the first patch is completed. + } } - } + void Bios_Patching(){ - #ifdef HIGH_PATCH + PIN_AX_INTERRUPT_RISING; + + if (PIN_AX_READ != 0) // If the AX pin is high + { + while (PIN_AX_READ != 0); // Wait for it to go low + while (PIN_AX_READ == 0); // Then wait for it to go high again. + } + else // If the AX pin is low + { + while (PIN_AX_READ == 0); // Wait for it to go high. + } + + // Wait until the number of microseconds elapsed reaches a value defined by CHECKPOINT. + _delay_ms(CHECKPOINT); + PIN_AX_INTERRUPT_ENABLE; + + while (patch != 1); // Wait for the first stage of the patch to complete: + + } + + #endif + + #ifdef INTERRUPT_FALLING + + ISR(PIN_AX_INTERRUPT_VECTOR) { + impulse++; + if (impulse == TRIGGER){ // If impulse reaches the value defined by TRIGGER, the following actions are performed: + _delay_us (HOLD); + PIN_DX_OUTPUT; + _delay_us (PATCHING); + PIN_DX_INPUT; + PIN_AX_INTERRUPT_DISABLE; + + impulse = 0; + patch = 1; // patch is set to 1, indicating that the first patch is completed. + } + } + + void Bios_Patching(){ + + PIN_AX_INTERRUPT_FALLING; + + if (PIN_AX_READ != 0) // If the AX pin is high + { + while (PIN_AX_READ != 0); // Wait for it to go low + while (PIN_AX_READ == 0); // Then wait for it to go high again. + } + else // If the AX pin is low + { + while (PIN_AX_READ == 0); // Wait for it to go high. + } + + _delay_ms(CHECKPOINT); // Wait until the number of microseconds elapsed reaches a value defined by CHECKPOINT. + PIN_AX_INTERRUPT_ENABLE; + + while (patch != 1); // Wait for the first stage of the patch to complete: + } + + #endif + + #ifdef INTERRUPT_RISING_HIGH_PATCH + + ISR(PIN_AX_INTERRUPT_VECTOR) { + impulse++; + if (impulse == TRIGGER){ // If impulse reaches the value defined by TRIGGER, the following actions are performed: + _delay_us (HOLD); + PIN_DX_SET; + PIN_DX_OUTPUT; + _delay_us (PATCHING); + PIN_DX_CLEAR; + PIN_DX_INPUT; + PIN_AX_INTERRUPT_DISABLE; + + impulse = 0; + patch = 1; // patch is set to 1, indicating that the first patch is completed. + } + } + ISR(PIN_AY_INTERRUPT_VECTOR){ impulse++; if (impulse == TRIGGER2) // If impulse reaches the value defined by TRIGGER2, the following actions are performed: { - HOLD2; + _delay_us (HOLD2); PIN_DX_OUTPUT; - PATCHING2; + _delay_us (PATCHING2); PIN_DX_INPUT; PIN_AY_INTERRUPT_DISABLE; patch = 2; // patch is set to 2, indicating that the second patch is completed. } } - #endif + void Bios_Patching(){ - void Bios_Patching(){ + PIN_AX_INTERRUPT_RISING; - // If LOW_TRIGGER is defined - #ifdef LOW_TRIGGER - PIN_AX_INTERRUPT_FALLING; - #else - PIN_AX_INTERRUPT_RISING; - #endif + if (PIN_AX_READ != 0) // If the AX pin is high + { + while (PIN_AX_READ != 0); // Wait for it to go low + while (PIN_AX_READ == 0); // Then wait for it to go high again. + } + else // If the AX pin is low + { + while (PIN_AX_READ == 0); // Wait for it to go high. + } + + _delay_ms(CHECKPOINT); // Wait until the number of microseconds elapsed reaches a value defined by CHECKPOINT. + PIN_AX_INTERRUPT_ENABLE; + + while (patch != 1); // Wait for the first stage of the patch to complete: - if (PIN_AX_READ != 0) // If the AX pin is high - { - while (PIN_AX_READ != 0); // Wait for it to go low - while (PIN_AX_READ == 0); // Then wait for it to go high again. - } - else // If the AX pin is low - { - while (PIN_AX_READ == 0); // Wait for it to go high. - } - - Timer_Start(); - while (microsec < CHECKPOINT); // Wait until the number of microseconds elapsed reaches a value defined by CHECKPOINT. - Timer_Stop(); - PIN_AX_INTERRUPT_ENABLE; - - while (patch != 1); // Wait for the first stage of the patch to complete: - - #ifdef HIGH_PATCH #ifdef HIGH_PATCH PIN_AY_INTERRUPT_FALLING; @@ -86,105 +143,17 @@ volatile uint8_t patch = 0; PIN_AY_INTERRUPT_RISING; #endif - while (PIN_AY_READ != 0); // Wait for it to go low - Timer_Start(); - while (microsec < CHECKPOINT2); // Wait until the number of microseconds elapsed reaches a value defined by CHECKPOINT2. - Timer_Stop(); + while (PIN_AY_READ != 0); // Wait for it to go low + + _delay_ms(CHECKPOINT2); // Wait until the number of microseconds elapsed reaches a value defined by CHECKPOINT2. PIN_AY_INTERRUPT_ENABLE; while (patch != 2); // Wait for the second stage of the patch to complete: - #endif - } -#endif + } -#ifdef SCPH_102_legacy -//void Bios_Patching_SCPH_102_legacy() { - -// PIN_AX_INPUT; //A18 -// PIN_DX_INPUT; //D2 - -// Timer_Start(); -// while (millisec < SATBILIZATIONPOINT); // this is right after SQCK appeared. wait a little to avoid noise -// while (PIN_AX_READ != 0); -// Timer_Stop(); - -// // //wait for stage 1 A18 pulse + #endif -// Timer_Start(); -// while (millisec < DELAYPOINT); //wait through stage 1 of A18 activity delay(1350) -// Timer_Stop(); - -// //noInterrupts(); // start critical section -// GLOBAL_INTERRUPT_DISABLE; -// Timer_Start(); -// while (PIN_AX_READ != 0); -// { -// ; //wait for priming A18 pulse -// } -// //while (microsec < HOLD ); // delayMicroseconds(17) min 13us max 17us for 16Mhz ATmega (maximize this when tuning!) -// HOLD; -// PIN_DX_CLEAR; // store a low -// PIN_DX_OUTPUT; // D2 = output. drags line low now -// PATCHING; -// //while (microsec < PATCHING ); // delayMicroseconds(4) min 2us for 16Mhz ATmega, 8Mhz requires 3us (minimize this when tuning, after maximizing first us delay!) -// PIN_DX_INPUT; // D2 = input / high-z -// GLOBAL_INTERRUPT_ENABLE; -// //interrupts(); // end critical section -// Timer_Stop(); -// // not necessary but I want to make sure these pins are now high-z again -// PIN_AX_INPUT; -// PIN_DX_INPUT; -// } - -// Original function equivalent to NTSC_fix(), using macros -void Bios_Patching_SCPH_102_legacy(void) { - - // configure A18 and D2 as inputs - PIN_AX_INPUT; - PIN_DX_INPUT; - - // arm A18 interrupt for noise immunity (optional) - PIN_AX_INTERRUPT_RISING; - PIN_AX_INTERRUPT_ENABLE; - - // initial stabilization delay - Timer_Start(); - SATBILIZATIONPOINT; // _delay_ms(100) - Timer_Stop(); - - // wait for stage 1 A18 pulse - while (!PIN_AX_READ) ; - - // wait through stage 1 of A18 activity - Timer_Start(); - DELAYPOINT; // _delay_ms(1350) - Timer_Stop(); - - // critical section - noInterrupts(); - // wait for priming A18 pulse - while (!PIN_AX_READ) ; - Timer_Start(); - HOLD; // _delay_us(17) - Timer_Stop(); - - // drive D2 low for patch - PIN_DX_CLEAR; // clear D2 - PIN_DX_OUTPUT; // set D2 as output - Timer_Start(); - PATCH; // _delay_us(4) - Timer_Stop(); - PIN_DX_INPUT; // release D2 (input/high-Z) - interrupts(); - - // restore pins to input - PIN_AX_INPUT; - PIN_DX_INPUT; - - // disable A18 interrupt now that patch is done - PIN_AX_INTERRUPT_DISABLE; -} #endif diff --git a/PSNee/MCU.h b/PSNee/MCU.h index dfb1cf8..2618da0 100644 --- a/PSNee/MCU.h +++ b/PSNee/MCU.h @@ -96,21 +96,45 @@ #ifdef ATmega328_168 + + // Configuring Port C (A0-A5) as Digital Inputs + // DDRC at 0 = Input. Ensure that the first 6 bits are 0. + #define A DDRC &= ~0x3F; + + // Disable the ADC (Analog-to-Digital Converter) + // ADEN at 0 disables the module. PRADC at 1 disables the module's clock. + #define B ADCSRA &= ~(1 << ADEN); + #define C PRR |= (1 << PRADC); + + // Configure DIDR0 (Digital Input Disable Register) + // To read digitally via PINC, the bits of DIDR0 MUST be set to 0. + // (0 = Digital Buffer enabled) + #define D DIDR0 &= ~0x3F; + + // Stop Timer 0 (Stops Arduino millis/micros) + // Setting TCCR0B to 0 stops the clock source. Setting TIMSK0 to 0 disables interrupts. + #define E TCCR0B = 0; + #define F TIMSK0 = 0; + + // Disable the Analog Comparator (Frees up resources on PD6/PD7) + // ACD at 1 = Comparator off. + #define G ACSR |= (1 << ACD); + // Define the clock speed for the microcontroller #define F_CPU 16000000L // Clear the timer count register (TCNT0) - #define TIMER_TCNT_CLEAR TCNT0 = 0x00 // TCNT0 - Timer/Counter Register, clears the timer count + //#define TIMER_TCNT_CLEAR TCNT0 = 0x00 // TCNT0 - Timer/Counter Register, clears the timer count // Set OCR0A to achieve a 100KHz clock frequency - #define SET_OCROA_DIV OCR0A = 159; // OCR0A – Output Compare Register A, 100KHz clock generation, 0x10011111 + //#define SET_OCROA_DIV OCR0A = 159; // OCR0A – Output Compare Register A, 100KHz clock generation, 0x10011111 // Configure Timer/Counter 0 for CTC mode and enable the clock source - #define SET_TIMER_TCCROA TCCR0A |= (1 << WGM01); // TCCR0A – Timer/Counter Control Register A, enable CTC mode (WGM01) - #define SET_TIMER_TCCROB TCCR0B |= (1 << CS00); // TCCR0B – Timer/Counter Control Register B, set clock source to I/O clock + //#define SET_TIMER_TCCROA TCCR0A |= (1 << WGM01); // TCCR0A – Timer/Counter Control Register A, enable CTC mode (WGM01) + //#define SET_TIMER_TCCROB TCCR0B |= (1 << CS00); // TCCR0B – Timer/Counter Control Register B, set clock source to I/O clock //Waveform Generation Mode, Mode 2 CTC // Interrupt vector for timer compare match event - #define CTC_TIMER_VECTOR TIMER0_COMPA_vect //interrupt vector for match event, OCR0A comparison and Timer/Counter 0 + //#define CTC_TIMER_VECTOR TIMER0_COMPA_vect //interrupt vector for match event, OCR0A comparison and Timer/Counter 0 #include #include @@ -124,8 +148,8 @@ #define GLOBAL_INTERRUPT_DISABLE SREG &= ~(1 << 7) // Clear the I-bit (bit 7) in the Status Register to disable global interrupts // Enable/Disable timer interrupts - #define TIMER_INTERRUPT_ENABLE TIMSK0 |= (1 << OCIE0A) // Enable interrupt on Timer0 Compare Match A - #define TIMER_INTERRUPT_DISABLE TIMSK0 &= ~(1 << OCIE0A) // Disable interrupt on Timer0 Compare Match A + //#define TIMER_INTERRUPT_ENABLE TIMSK0 |= (1 << OCIE0A) // Enable interrupt on Timer0 Compare Match A + //#define TIMER_INTERRUPT_DISABLE TIMSK0 &= ~(1 << OCIE0A) // Disable interrupt on Timer0 Compare Match A // Main pin configuration for input and output @@ -159,10 +183,10 @@ #endif // Handling the BIOS patch - #if defined(SCPH_102) || defined(SCPH_102_legacy) || defined(SCPH_100) || defined(SCPH_7000_9000) || defined(SCPH_5500) || defined(SCPH_3500_5000) || defined(SCPH_3000) || defined(SCPH_1000) + #if defined(SCPH_102) || defined(SCPH_102_legacy) || defined(SCPH_100) || defined(SCPH_7500_9000) || defined(SCPH_7000) || defined(SCPH_5500) || defined(SCPH_3500_5000) || defined(SCPH_3000) || defined(SCPH_1000) // Clear the timer interrupt flag - #define TIMER_TIFR_CLEAR TIFR0 |= (1 << OCF0A) // Clear the Timer0 Compare Match A interrupt flag + //#define TIMER_TIFR_CLEAR TIFR0 |= (1 << OCF0A) // Clear the Timer0 Compare Match A interrupt flag // Define input pins for the BIOS patch #define PIN_AX_INPUT DDRD &= ~(1 << DDD2) // Set DDRD register to configure PIND2 as input @@ -604,11 +628,6 @@ #ifdef LGT8F328P #define F_CPU 32000000L -#define TIMER_TCNT_CLEAR TCNT0 = 0x00 -#define SET_OCROA_DIV OCR0A = 319; -#define SET_TIMER_TCCROA TCCR0A |= (1 << WGM01); -#define SET_TIMER_TCCROB TCCR0B |= (1 << CS00); -#define CTC_TIMER_VECTOR TIMER0_COMPA_vect #include @@ -699,89 +718,3 @@ #endif -#ifdef CH32V003 - -#include "ch32v003.h" // Inclure le fichier d'en-tête spécifique au microcontrôleur -#include -#include - -// Fréquence d'horloge -#define F_CPU 8000000L - -// Configuration du timer pour une fréquence de 100 kHz -#define TIMER_TCNT_CLEAR TIM2_CNT = 0x00 // ok Effacer le compteur du Timer 2 -#define SET_OCROA_DIV TIM2_ARR = 79 // not Définir la valeur de comparaison pour générer une interruption à 100 kHz -#define SET_TIMER_TCCROA TIM2_CR1 |= TIM_CR1_OPM // notMettre le Timer en mode One Pulse (à adapter selon le mode souhaité) -#define SET_TIMER_TCCROB TIM2_PSC = 0 // ok Définir le prescaler à 0 pour une fréquence maximale - -// Vecteur d'interruption pour le Timer 2 -#define CTC_TIMER_VECTOR TIM2_UP_IRQHandler // Remplacer par le vecteur d'interruption approprié - -// Interruption globale -#define GLOBAL_INTERRUPT_ENABLE __enable_irq() -#define GLOBAL_INTERRUPT_DISABLE __disable_irq() - -// Configuration des broches GPIO -#define PIN_DATA_INPUT GPIOA->INDR &= ~(GPIO_MODER_MODER0) -#define PIN_WFCK_INPUT GPIOA->INDR &= ~(GPIO_MODER_MODER1) -#define PIN_SQCK_INPUT GPIOA->INDR &= ~(GPIO_MODER_MODER6) -#define PIN_SUBQ_INPUT GPIOA->INDR &= ~(GPIO_MODER_MODER7) - -#define PIN_DATA_OUTPUT GPIOA->OUTDR |= (GPIO_MODER_MODER0_0) -#define PIN_WFCK_OUTPUT GPIOA->OUTDR |= (GPIO_MODER_MODER1_0) - -#define PIN_DATA_SET GPIOA->BSHR |= (GPIO_ODR_ODR_0) - -#define PIN_DATA_CLEAR GPIOA->BRC &= ~(GPIO_ODR_ODR_0) -#define PIN_WFCK_CLEAR GPIOA->BRC &= ~(GPIO_ODR_ODR_1) - -#define PIN_SQCK_READ (GPIOA->IDR & (GPIO_IDR_IDR_6)) -#define PIN_SUBQ_READ (GPIOA->IDR & (GPIO_IDR_IDR_7)) -#define PIN_WFCK_READ (GPIOA->IDR & (GPIO_IDR_IDR_1)) - -// Gestion de la broche LED -#define PIN_LED_OUTPUT GPIOA->MODER |= (GPIO_MODER_MODER5_0) -#define PIN_LED_ON GPIOA->ODR |= (GPIO_ODR_ODR_5) -#define PIN_LED_OFF GPIOA->ODR &= ~(GPIO_ODR_ODR_5) - -// Gestion des interruptions du timer -#define TIMER_INTERRUPT_ENABLE TIM2_DIER |= (TIM_DIER_UIE) -#define TIMER_INTERRUPT_DISABLE TIM2_DIER &= ~(TIM_DIER_UIE) -#define TIMER_TIFR_CLEAR TIM2_SR &= ~(TIM_SR_UIF) - -// Configuration des broches pour le BIOS -#define PIN_AX_INPUT GPIOA->MODER &= ~(GPIO_MODER_MODER2)AFIO_EXTICR -#define PIN_AY_INPUT GPIOA->MODER &= ~(GPIO_MODER_MODER3) -#define PIN_DX_INPUT GPIOA->MODER &= ~(GPIO_MODER_MODER4) - -#define PIN_DX_OUTPUT GPIOA->MODER |= (GPIO_MODER_MODER4_0) - -#define PIN_DX_SET GPIOA->ODR |= (GPIO_ODR_ODR_4) - -#define PIN_DX_CLEAR GPIOA->ODR &= ~(GPIO_ODR_ODR_4) - -#define PIN_AX_READ (GPIOA->IDR & (GPIO_IDR_IDR_2)) -#define PIN_AY_READ (GPIOA->IDR & (GPIO_IDR_IDR_3)) - -// Gestion des interruptions externes -#define PIN_AX_INTERRUPT_ENABLE EXTI->IMR |= (EXTI_IMR_MR0) //1<IMR |= (EXTI_IMR_MR1) - -#define PIN_AX_INTERRUPT_DISABLE EXTI->IMR &= ~(EXTI_IMR_MR0) //EXTI_INTENR -#define PIN_AY_INTERRUPT_DISABLE EXTI->IMR &= ~(EXTI_IMR_MR1) - -#define PIN_AX_INTERRUPT_RISING EXTI->RTSR |= (EXTI_RTSR_TR0) //EXTI_RTENR -#define PIN_AY_INTERRUPT_RISING EXTI->RTSR |= (EXTI_RTSR_TR1) - -#define PIN_AX_INTERRUPT_FALLING EXTI->FTSR |= (EXTI_FTENR_MR0) //EXTI_FTENR -#define PIN_AY_INTERRUPT_FALLING EXTI->FTSR |= (EXTI_FTENR_MR1) - -#define PIN_AX_INTERRUPT_VECTOR EXTI0_IRQHandler -#define PIN_AY_INTERRUPT_VECTOR EXTI1_IRQHandler - -// Gestion de la broche de commutation pour le BIOS -#define PIN_SWITCH_INPUT GPIOA->MODER &= ~(GPIO_MODER_MODER5) -#define PIN_SWITCH_SET GPIOA->ODR |= (GPIO_ODR_ODR_5) -#define PIN_SWITCH_READ (GPIOA->IDR & (GPIO_IDR_IDR_5)) - -#endif diff --git a/PSNee/PSNee.ino b/PSNee/PSNee.ino index dfb0cfe..bfcfc79 100644 --- a/PSNee/PSNee.ino +++ b/PSNee/PSNee.ino @@ -6,7 +6,7 @@ // MCU // Arduino //------------------------------------------------------------------------------------------------ -//#define ATmega328_168 // Nano, Pro Mini, Uno +#define ATmega328_168 // Nano, Pro Mini, Uno //#define ATmega32U4_16U4 // Micro, Pro Micro //#define ATtiny85_45_25 // ATtiny @@ -44,9 +44,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX SCPH model number // Data pin | 32-pin BIOS | 40-pin BIOS | BIOS version -------------------------------------------------------------------------------------------------*/ //#define SCPH_102 // DX - D0 | AX - A7 | | 4.4e - CRC 0BAD7EA9, 4.5e -CRC 76B880E5 -//#define SCPH_102_legacy // ! works in progress DX - D2, AX - A18. | 4.4e - CRC 0BAD7EA9, 4.5e -CRC 76B880E5 //#define SCPH_100 // DX - D0 | AX - A7 | | 4.3j - CRC F2AF798B -//#define SCPH_7000_9000 // DX - D0 | AX - A7 | | 4.0j - CRC EC541CD0 +//#define SCPH_7500_9000 // DX - D0 | AX - A7 | | 4.0j - CRC EC541CD0 +//#define SCPH_7000 // DX - D0 | AX - A7 | | 4.0j - CRC EC541CD0 Enables hardware support for disabling BIOS patching. //#define SCPH_5500 // DX - D0 | AX - A5 | | 3.0j - CRC FF3EEB8C //#define SCPH_3500_5000 // DX - D0 | AX - A5 | AX - A4 | 2.2j - CRC 24FC7E17, 2.1j - CRC BC190209 //#define SCPH_3000 // DX - D5 | AX - A7, AY - A8 | AX - A6, AY - A7 | 1.1j - CRC 3539DEF6 @@ -59,9 +59,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #define LED_RUN // Turns on the LED when injections occur. // D13 for Arduino, ATtiny add a led between PB3 (pin 2) and gnd with a 1k resistor in series, ATmega32U4 (Pro Micro) add a led between PB6 (pin 10) and gnd with a 1k resistor in series. -//#define PATCH_SWITCH // Enables hardware support for disabling BIOS patching. -// With SCPH_7000 - 9000 models, Bios 4.0j, the bios patch prevents reading memory cards in the console interface, and in some cases can cause a crash (No problem in game). -// In rare cases where the BIOS patch prevents the playback of original games. //#define PSNEE_DEBUG_SERIAL_MONITOR // Enables serial monitor output. /* Requires compilation with Arduino libs! @@ -125,14 +122,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "settings.h" #include "BIOS_patching.h" -//Initializing values ​​for region code injection timing -#define DELAY_BETWEEN_BITS 4000 // 250 bits/s (microseconds) (ATtiny 8Mhz works from 3950 to 4100) PU-23 PU-22 MAX 4250 MIN 3850 -#define DELAY_BETWEEN_INJECTIONS 90 // The sweet spot is around 80~100. For all observed models, the worst minimum time seen is 72, and it works well up to 250. - -//Creation of the different variables for the counter -volatile uint8_t count_isr = 0; -volatile uint32_t microsec = 0; -volatile uint32_t millisec = 0; //Flag initializing for automatic console generation selection 0 = old, 1 = pu-22 end ++ volatile bool wfck_mode = 0; @@ -143,89 +132,6 @@ volatile bool Flag_Switch = 0; Code section ------------------------------------------------------------------------------------------------*/ -/*------------------------------------------------------------------------------------------------ - Interrupt Service Routine: CTC_TIMER_VECTOR - Description: - This ISR is triggered by the Timer/Counter Compare Match event. It increments time-related - counters used for tracking microseconds and milliseconds. - - Functionality: - - Increments `microsec` by 10 on each interrupt call. - - Increments `count_isr` to keep track of the number of interrupts. - - When `count_isr` reaches 100, it means 1 millisecond has elapsed: - - `millisec` is incremented. - - `count_isr` is reset to 0. - - Notes: - - This method provides a simple way to maintain a software-based timekeeping system. -------------------------------------------------------------------------------------------------*/ -ISR(CTC_TIMER_VECTOR) { - microsec += 10; - count_isr++; - if (count_isr == 100) - { - millisec++; - count_isr = 0; - } -} - -// ***************************************************************************************** -// Function: Timer_Start -// Description: -// This function initializes and starts the timer by resetting the timer counter register -// and enabling timer interrupts. It ensures compatibility across multiple microcontrollers. -// -// Supported Microcontrollers: -// - ATmega328/168 -// - ATmega32U4/16U4 -// - ATtiny85/45/25 -// -// Functionality: -// - Clears the timer counter to ensure a fresh start. -// - Enables the timer interrupt to allow periodic execution of ISR routines. -// - If BIOS_PATCH is defined, it also clears the timer interrupt flag to prevent -// unwanted immediate interrupts. -// -// Notes: -// - The actual timer configuration is handled in MCU.h. -// - This function ensures that all supported MCUs behave consistently. -// -// ***************************************************************************************** -void Timer_Start() { -#if defined(ATmega328_168) || defined(ATmega32U4_16U4) || defined(ATtiny85_45_25) - TIMER_TCNT_CLEAR; - TIMER_INTERRUPT_ENABLE; - #if defined(BIOS_PATCH) - TIMER_TIFR_CLEAR; - #endif -#endif -} - -// ***************************************************************************************** -// Function: Timer_Stop -// Description: -// Stops the timer by disabling interrupts and resetting the timer counter. -// It also clears the time tracking variables (count_isr, microsec, millisec) -// to ensure a fresh start when the timer is restarted. -// -// Supported Microcontrollers: -// - ATmega328/168 -// - ATmega32U4/16U4 -// - ATtiny85/45/25 -// -// ***************************************************************************************** -void Timer_Stop() { - - #if defined(ATmega328_168) || defined(ATmega32U4_16U4) || defined(ATtiny85_45_25) - TIMER_INTERRUPT_DISABLE; // Disable timer interrupts to stop counting - TIMER_TCNT_CLEAR; // Reset the timer counter to ensure proper timing when restarted - #endif - // Reset time tracking variables - count_isr = 0; - microsec = 0; - millisec = 0; -} - // ***************************************************************************************** // Function: readBit // Description: @@ -293,7 +199,10 @@ void inject_SCEX(const char region) { 0b00000010 }; - // Iterate through 44 bits of SCEX data + //Initializing values ​​for region code injection timing +#define DELAY_BETWEEN_BITS 4000 // 250 bits/s (microseconds) (ATtiny 8Mhz works from 3950 to 4100) PU-23 PU-22 MAX 4250 MIN 3850 +#define DELAY_BETWEEN_INJECTIONS 90 // The sweet spot is around 80~100. For all observed models, the worst minimum time seen is 72, and it works well up to 250. + for (uint8_t bit_counter = 0; bit_counter < 44; bit_counter++) { // Check if the current bit is 0 if (readBit(bit_counter, region == 'e' ? SCEEData : region == 'a' ? SCEAData : SCEIData) == 0) { @@ -306,19 +215,29 @@ void inject_SCEX(const char region) { if (wfck_mode) // WFCK mode (pu22mode enabled): synchronize PIN_DATA with WFCK clock signal { PIN_DATA_OUTPUT; - Timer_Start(); - do { - // Read the WFCK pin and set or clear DATA accordingly - if (PIN_WFCK_READ) { - PIN_DATA_SET; - } + uint8_t count = 30; + uint8_t last_wfck = PIN_WFCK_READ; - else { + while (count > 0) { + uint8_t current_wfck = PIN_WFCK_READ; + + if (current_wfck) { + _delay_us(5); + PIN_DATA_SET; + _delay_us(55); + PIN_DATA_CLEAR; + _delay_us(10); + } else { PIN_DATA_CLEAR; - } - } - while (microsec < DELAY_BETWEEN_BITS); - Timer_Stop(); // Stop the timer after the delay + } + + if (current_wfck && !last_wfck) { + count--; + } + + last_wfck = current_wfck; + } + } // PU-18 or lower mode: simply set PIN_DATA as input with a delay else { @@ -335,21 +254,14 @@ void inject_SCEX(const char region) { void Init() { #if defined(ATmega328_168) || defined(ATmega32U4_16U4) || defined(ATtiny85_45_25) - TIMER_TCNT_CLEAR; - SET_OCROA_DIV; - SET_TIMER_TCCROA; - SET_TIMER_TCCROB; + A; + B; + D; + E; + F; + G; #endif -#if defined(ATmega328_168) - // 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(PATCH_SWITCH) && defined(BIOS_PATCH) PIN_SWITCH_INPUT; @@ -384,6 +296,8 @@ int main() { uint8_t bitpos = 0; uint8_t scpos = 0; // scbuf position uint16_t lows = 0; + uint8_t preset = 0; + uint32_t totalSamples = 400000; Init(); @@ -394,11 +308,7 @@ int main() { #endif if (Flag_Switch == 0) { - #ifdef SCPH_102_legacy - Bios_Patching_SCPH_102_legacy(); - #else - Bios_Patching(); - #endif + Bios_Patching(); } #ifdef LED_RUN @@ -407,7 +317,7 @@ int main() { #endif - Timer_Start(); + //Timer_Start(); /*---------------------------------------------------------------------- Board detection @@ -415,18 +325,21 @@ int main() { __-_-_-_-_-_-_-_-_-_-_-_- // this is a PU-22 or newer board! - typical readouts PU-22: highs: 2449 lows: 2377 -----------------------------------------------------------------------*/ - do { - if (PIN_WFCK_READ == 0) lows++; // good for ~5000 reads in 1s - _delay_us(200); - } - while (millisec < 1000); // sample 1s - Timer_Stop(); - if (lows > 100) { + while (totalSamples > 0 && lows < 500){ + if (PIN_WFCK_READ != preset){ + preset = PIN_WFCK_READ; + if (preset == 0){ + lows++; + } + } + totalSamples--; + } + + if (lows > 499) { wfck_mode = 1; //flag pu22mode } diff --git a/PSNee/settings.h b/PSNee/settings.h index d59cb89..1ff8e90 100644 --- a/PSNee/settings.h +++ b/PSNee/settings.h @@ -22,6 +22,7 @@ #ifdef SCPH_102_legacy #define BIOS_PATCH +//#define INTERRUPT_RISING #define SATBILIZATIONPOINT 100 #define DELAYPOINT 1350 #define HOLD _delay_us(17) @@ -30,74 +31,85 @@ #ifdef SCPH_102 #define BIOS_PATCH -#define HOLD _delay_us(2.75) -#define PATCHING _delay_us(0.2) -#define CHECKPOINT 83900 +#define INTERRUPT_RISING +#define CHECKPOINT 83.9 #define TRIGGER 48 +#define HOLD 2.75 +#define PATCHING 0.2 #endif #ifdef SCPH_100 #define BIOS_PATCH -#define HOLD _delay_us(2.7) -#define PATCHING _delay_us(0.2) -#define CHECKPOINT 83900 +#define INTERRUPT_RISING +#define CHECKPOINT 83.9 #define TRIGGER 48 +#define HOLD 2.8 +#define PATCHING 0.2 #endif -#ifdef SCPH_7000_9000 +#ifdef SCPH_7500_9000 #define BIOS_PATCH -#define HOLD _delay_us(2.85) -#define PATCHING _delay_us(0.1) -#define CHECKPOINT 75270 +#define INTERRUPT_RISING +#define CHECKPOINT 75.2 // ms SCPH_9000 74.95-75.55. #define TRIGGER 16 +#define HOLD 2.8 +#define PATCHING 0.2 +#endif + +#ifdef SCPH_7000 +#define BIOS_PATCH +//#define PATCH_SWITCH +#define INTERRUPT_RISING +#define CHECKPOINT 74.7 +#define TRIGGER 16 +#define HOLD 2.75 +#define PATCHING 0.6 #endif #ifdef SCPH_5500 #define BIOS_PATCH -#define HOLD _delay_us(2.85) -#define PATCHING _delay_us(0.1) -#define CHECKPOINT 76130 +#define INTERRUPT_FALLING +#define CHECKPOINT 76.13 #define TRIGGER 21 -#define LOW_TRIGGER +#define HOLD 2.85 +#define PATCHING 0.1 #endif #ifdef SCPH_3500_5000 #define BIOS_PATCH -#define HOLD _delay_us(2.85) -#define PATCHING _delay_us(0.1) -#define CHECKPOINT 75260 +#define INTERRUPT_FALLING +#define CHECKPOINT 75.26 #define TRIGGER 21 -#define LOW_TRIGGER +#define HOLD 2.85 +#define PATCHING 0.1 #endif #ifdef SCPH_3000 -#define BIOS_PATCH -#define HOLD _delay_us(2.75) -#define PATCHING _delay_us(0.1) -#define CHECKPOINT 83000 +#define BIOS_PATCH +#define INTERRUPT_RISING_HIGH_PATCH +#define CHECKPOINT 83 #define TRIGGER 60 -//#define DOUBLE_PATCH -//#define LOW_TRIGGER2 +#define HOLD 2.75 +#define PATCHING 0.1 #define HIGH_PATCH -#define HOLD2 _delay_us(2.88) -#define PATCHING2 _delay_us(0.15) #define CHECKPOINT2 253300 #define TRIGGER2 43 +#define HOLD2 2.88 +#define PATCHING2 0.15 #endif #ifdef SCPH_1000 #define BIOS_PATCH -#define HOLD _delay_us(2.7) -#define PATCHING _delay_us(0.1) -#define CHECKPOINT 83000 +#define INTERRUPT_RISING_HIGH_PATCH +#define CHECKPOINT 83 #define TRIGGER 92 -//#define DOUBLE_PATCH -//#define LOW_TRIGGER2 +#define HOLD 2.7 +#define PATCHING 0.1 #define HIGH_PATCH -#define HOLD2 _delay_us(2.88) -#define PATCHING2 _delay_us(0.15) -#define CHECKPOINT2 272800 +#define CHECKPOINT2 27.28 #define TRIGGER2 71 +#define HOLD2 2.88 +#define PATCHING2 0.15 #endif /*------------------------------------------------------------------------------------------------ @@ -108,11 +120,11 @@ const char region[3] = {'a', 'a', 'a'}; #endif -#if defined(SCPH_102) || defined(SCPH_xxx2) // PAL | Europ. +#if defined(SCPH_102) || defined(SCPH_xxx2) // PAL | Europ. const char region[3] = {'e', 'e', 'e'}; #endif -#if defined(SCPH_100) || defined(SCPH_7000_9000) || defined(SCPH_5500) || defined(SCPH_3500_5000) || defined(SCPH_3000) || defined(SCPH_1000) || defined(SCPH_xxx3) // NTSC J | Asia. +#if defined(SCPH_100) || defined(SCPH_7500_9000) || defined(SCPH_7000) || defined(SCPH_5500) || defined(SCPH_3500_5000) || defined(SCPH_3000) || defined(SCPH_1000) || defined(SCPH_xxx3) // NTSC J | Asia. const char region[3] = {'i', 'i', 'i'}; #endif @@ -169,7 +181,7 @@ void Debug_Inject(){ // Confirmation of region code injection #if defined(ATtiny85_45_25) mySerial.print("!"); -#elif !defined(ATtiny85_45_25) +#elif !defined(ATtiny85_45_25)|| defined(SCPH_102_legacy) Serial.println(" INJECT ! "); #endif } @@ -180,17 +192,17 @@ void Debug_Inject(){ // Confirmation of region code injection Compilation message -----------------------------------------------------------------------------------------------*/ -#if !defined(SCPH_103) && \ - !defined(SCPH_102) && !defined(SCPH_101) && !defined(SCPH_100) && !defined(SCPH_7000_9000) && \ - !defined(SCPH_5500) && !defined(SCPH_3500_5000) && !defined(SCPH_3000) && \ - !defined(SCPH_1000) && !defined(SCPH_xxxx) && !defined(SCPH_102_legacy) && \ - !defined(SCPH_xxx1) && !defined(SCPH_xxx2) && !defined(SCPH_xxxx3) +#if !defined(SCPH_xxx3) && \ + !defined(SCPH_102) && !defined(SCPH_101) && !defined(SCPH_100) && !defined(SCPH_7500_9000) && \ + !defined(SCPH_7000) && !defined(SCPH_5500) && !defined(SCPH_3500_5000) && !defined(SCPH_3000) && \ + !defined(SCPH_1000) && !defined(SCPH_xxxx) && \ + !defined(SCPH_xxx1) && !defined(SCPH_xxx2) #error "Console not selected! Please uncoment #define with SCPH model number." -#elif !defined(SCPH_103) ^ \ - defined(SCPH_102) ^ defined(SCPH_101) ^ defined(SCPH_100) ^ defined(SCPH_7000_9000) ^ \ - defined(SCPH_5500) ^ defined(SCPH_3500_5000) ^ defined(SCPH_3000) ^ \ - defined(SCPH_1000) ^ defined(SCPH_xxxx) ^ defined(SCPH_102_legacy) ^ \ - defined(SCPH_xxx1) ^ defined(SCPH_xxx2) ^ defined(SCPH_xxx3) +#elif !defined(SCPH_xxx3) ^ \ + defined(SCPH_102) ^ defined(SCPH_101) ^ defined(SCPH_100) ^ defined(SCPH_7500_9000) ^ \ + defined(SCPH_7000) ^ defined(SCPH_5500) ^ defined(SCPH_3500_5000) ^ defined(SCPH_3000) ^ \ + defined(SCPH_1000) ^ defined(SCPH_xxxx) ^ \ + defined(SCPH_xxx1) ^ defined(SCPH_xxx2) #error "May be selected only one console! Please check #define with SCPH model number." #endif