diff --git a/PSNee_V8.6/PSNee_V8.6/MUC.h b/PSNee_V8.6/PSNee_V8.6/MUC.h index 98d5071..329f04e 100644 --- a/PSNee_V8.6/PSNee_V8.6/MUC.h +++ b/PSNee_V8.6/PSNee_V8.6/MUC.h @@ -248,6 +248,7 @@ #include #include #include +#include // Global interrupt control settings #define GLOBAL_INTERRUPT_ENABLE SREG |= (1<<7) // Set the I-bit (bit 7) in the Status Register to enable global interrupts @@ -260,7 +261,13 @@ #define PIN_WFCK_INPUT DDRB &= ~(1< #include #include +#include // Globale interrupt seting #define GLOBAL_INTERRUPT_ENABLE SREG |= (1<<7) @@ -368,6 +376,12 @@ #define PIN_DATA_OUTPUT DDRB |= (1<MODER &= ~(GPIO_MODER_MODER5) #define PIN_SWITCH_SET GPIOA->ODR |= (GPIO_ODR_ODR_5) -#define PIN_SWICHE_READ (GPIOA->IDR & (GPIO_IDR_IDR_5)) +#define PIN_SWITCH_READ (GPIOA->IDR & (GPIO_IDR_IDR_5)) #endif diff --git a/PSNee_V8.6/PSNee_V8.6/PSNee_V8.6.ino b/PSNee_V8.6/PSNee_V8.6/PSNee_V8.6.ino index 98a0dcd..3c36fa1 100644 --- a/PSNee_V8.6/PSNee_V8.6/PSNee_V8.6.ino +++ b/PSNee_V8.6/PSNee_V8.6/PSNee_V8.6.ino @@ -17,7 +17,7 @@ //#define SCPH_102 // DX - D0, AX - A7. BIOS ver. 4.4e, CRC 0BAD7EA9 | 4.5e, CRC 76B880E5 //#define SCPH_100 // DX - D0, AX - A7. BIOS ver. 4.3j, CRC F2AF798B //#define SCPH_7000_9000 // DX - D0, AX - A7. BIOS ver. 4.0j, CRC EC541CD0 -//#define SCPH_5500 // DX - D0, AX - A5. BIOS ver. 3.0j, CRC FF3EEB8C +#define SCPH_5500 // DX - D0, AX - A5. BIOS ver. 3.0j, CRC FF3EEB8C //#define SCPH_5000 // DX - D0, for 40-pin BIOS: AX - A4, for 32-pin BIOS: AX - A5. BIOS ver. 2.2j, CRC 24FC7E17 | 2.1j, CRC BC190209 //#define SCPH_3500 // DX - D0, for 40-pin BIOS: AX - A4, for 32-pin BIOS: AX - A5. BIOS ver. 2.2j, CRC 24FC7E17 | 2.1j, CRC BC190209 //#define SCPH_3000 // DX - D5, for 40-pin BIOS: AX - A6, AY - A7, for 32-pin BIOS: AX - A7, AY - A8. BIOS ver. 1.1j, CRC 3539DEF6 @@ -49,7 +49,7 @@ D7-SUBQ D8-DATA D9-WFCK - RST-RESET* (Only for JAP_FAT) + RST-RESET* (Only for JAP_FAT). If using ENABLE_HOLD_RESET_ON_BOOT see description below. GND-GND Pinout ATtiny: @@ -68,8 +68,17 @@ // Options //------------------------------------------------------------------------------------------------ -#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_SWITCHE // Enables hardware support for disabling BIOS patching, to allow access to the console memory card menu for model 7000. Useful in rare cases where the BIOS patch prevents the playback of original games +//#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_SW // Enables hardware support for disabling BIOS patching, to allow access to the console memory card menu for model 7000. Useful in rare cases where the BIOS patch prevents the playback of original games + +// Holds PS1 reset on boot for more stability in BIOS PATCH for all JAP PS1 and European SCHP-102. D10 for ATMEGA328. A0 for ATMEGA32U4. +// This also makes possible to preserve the bootloader without needing a programmer. +// Caution: +// FAT Models. Instead of connecting PS1's reset line to RST connect it to D10 (ATMEGA328) or A0 (ATMEGA32U4) in Arduino. +// This needs a power cycle for stability. The use of manually pressing PS1's reset button or IGR mod leads to instability in BIOS PATCH (hit and miss). +// +// SLIM Models. Connect PS1's reset line to D10 (ATMEGA328) or A0 (ATMEGA32U4) in Arduino. +#define ENABLE_HOLD_RESET_ON_BOOT //------------------------------------------------------------------------------------------------ // pointer and variable section @@ -289,25 +298,58 @@ void inject_SCEX(const char region) { _delay_ms(DELAY_BETWEEN_INJECTIONS); } +void hold_reset(uint8_t hold_rst_time){ + // AUTO BOOT RESET - PIN D10 ATMEGA328/ A0 ATMEGA32U4 + PIN_RESET_OUTPUT; // Set as output + PIN_RESET_LOW; // Set GND + _delay_ms(hold_rst_time); // Hold reset + PIN_RESET_INPUT; // Set High Impedance +} + 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; -#endif + // Disable watchdog after reset + #if defined(ENABLE_HOLD_RESET_ON_BOOT) && defined(BIOS_PATCH) && (defined(ATmega328_168) || defined(ATmega32U4_16U4)) + MCUSR = 0; + wdt_disable(); + #endif -#if defined(PATCH_SWITCHE) && defined(BIOS_PATCH) - PIN_SWITCH_INPUT; - PIN_SWITCH_SET; - if (PIN_SWICHE_READ == 0){ - Flag_Switch =1; - } -#endif + #if defined(ATmega328_168) || defined(ATmega32U4_16U4) || defined(ATtiny85_45_25) + TIMER_TCNT_CLEAR; + SET_OCROA_DIV; + SET_TIMER_TCCROA; + SET_TIMER_TCCROB; + #endif -#ifdef LED_RUN - PIN_LED_OUTPUT; -#endif + #if defined(PATCH_SW) && defined(BIOS_PATCH) && (defined(ATmega328_168) || defined(ATmega32U4_16U4)) + PIN_SWITCH_INPUT; + PIN_SWITCH_SET; + if (PIN_SWITCH_READ == 0){ + Flag_Switch =1; + } + #endif + + // Reset PS1 when booting + #if defined(ENABLE_HOLD_RESET_ON_BOOT) && defined(BIOS_PATCH) && (defined(ATmega328_168) || defined(ATmega32U4_16U4)) + #ifdef PATCH_SW + if (Flag_Switch == 0) { + #ifdef FAT + hold_reset(1000); + #else + hold_reset(300); + #endif + } + #else + #ifdef FAT + hold_reset(1000); + #else + hold_reset(300); + #endif + #endif + #endif + + #ifdef LED_RUN + PIN_LED_OUTPUT; + #endif GLOBAL_INTERRUPT_ENABLE; @@ -315,6 +357,18 @@ void Init() { PIN_SUBQ_INPUT; } +// CAPTURE MANUAL RESET FOR JAP FAT MODELS THAT REQUIRE BIOS PATCH +void capture_reset(){ + _delay_ms(50); + if (IS_RESET_PRESSED) { + while (IS_RESET_PRESSED); + PIN_RESET_OUTPUT; + PIN_RESET_LOW; + wdt_enable(WDTO_250MS); + while(1); + } +} + int main() { uint8_t hysteresis = 0; uint8_t scbuf[12] = { 0 }; // SUBQ bit storage @@ -326,21 +380,25 @@ int main() { Init(); -#if defined(BIOS_PATCH) + #if defined(BIOS_PATCH) && (defined(ATmega328_168) || defined(ATmega32U4_16U4)) -#ifdef LED_RUN - PIN_LED_ON; -#endif + #ifdef LED_RUN + PIN_LED_ON; + #endif - if (Flag_Switch == 0) { - Bios_Patching(); - } + #if defined(PATCH_SW) + if (Flag_Switch == 0) { + Bios_Patching(); + } + #else + Bios_Patching(); + #endif -#ifdef LED_RUN - PIN_LED_OFF; -#endif + #ifdef LED_RUN + PIN_LED_OFF; + #endif -#endif + #endif Timer_Start(); //************************************************************************ @@ -375,7 +433,15 @@ int main() { } while (1) { - + // CAPTURE MANUAL RESET FOR JAP FAT MODELS THAT REQUIRE BIOS PATCH + #if defined(FAT) && defined(ENABLE_HOLD_RESET_ON_BOOT) && (defined(ATmega328_168) || defined(ATmega32U4_16U4)) + #ifdef PATCH_SW + if (Flag_Switch == 0 && IS_RESET_PRESSED) capture_reset(); + #else + if (IS_RESET_PRESSED) capture_reset(); + #endif + #endif + _delay_ms(1); /* 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*/ diff --git a/PSNee_V8.6/PSNee_V8.6/settings.h b/PSNee_V8.6/PSNee_V8.6/settings.h index 97cfbb3..5ac2557 100644 --- a/PSNee_V8.6/PSNee_V8.6/settings.h +++ b/PSNee_V8.6/PSNee_V8.6/settings.h @@ -58,6 +58,7 @@ #define PATCHING _delay_us(0.1) #define CHECKPOINT 75270 #define TRIGGER 16 +#define FAT #endif #ifdef SCPH_5500 @@ -68,6 +69,7 @@ #define CHECKPOINT 76100 #define TRIGGER 21 #define LOW_TRIGGER +#define FAT #endif // #ifdef SCPH_3500_5000 @@ -78,6 +80,7 @@ // #define CHECKPOINT 75260 // #define TRIGGER 21 // #define LOW_TRIGGER +// #define FAT // #endif // #ifdef SCPH_5500 @@ -88,6 +91,7 @@ // #define CHECKPOINT 76130 // #define TRIGGER 21 // #define LOW_TRIGGER +// #define FAT // #endif #ifdef SCPH_5000 @@ -98,6 +102,7 @@ #define CHECKPOINT 75260 #define TRIGGER 21 #define LOW_TRIGGER +#define FAT #endif #ifdef SCPH_3500 @@ -108,6 +113,7 @@ #define TRIGGER 21 #define HOLD _delay_us(2.75) //2.65 - 2.85 #define PATCHING _delay_us(0.2) +#define FAT #endif #ifdef SCPH_3000 @@ -123,7 +129,8 @@ #define HOLD2 _delay_us(2.88) #define PATCHING2 _delay_us(0.15) #define CHECKPOINT2 253300 -#define TRIGGER2 43 +#define TRIGGER2 43 +#define FAT #endif #ifdef SCPH_1000 @@ -140,6 +147,7 @@ #define PATCHING2 _delay_us(0.15) #define CHECKPOINT2 272800 #define TRIGGER2 71 +#define FAT #endif #ifdef SCEA diff --git a/README.md b/README.md index 78e03a1..0174445 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,25 @@ THE modechip supports the largest number of Playstation 1 variants, and the larg - Remove Disk Region Protection - Patch BIOS - A specific library for card support, to solve the fuse setting problem. -- The mode does not take care of changing PAL <-> NTSC video output (in other words if you use a Japanese console and you put European games, or in older European models you use American or Japanese games... the display will not be correct) +- Hardware Reset Synchronization (Forced Boot Sync): Solves the "race condition" where the console starts faster than the PsNee. +The MCU holds the console in reset until it is fully initialized, ensuring a better success rate on cold boots. +Critical for PSOne (SCPH-102), Japanese models, and known problematic boards using the ATmega328PB. +- Bootloader Friendly: This sync mechanism allows you to keep the standard bootloader, making it easier to update without extra hardware (ISP). +- The PsNee does not take care of changing PAL <-> NTSC video output (in other words if you use a Japanese console and you put European games, or in older European models you use American or Japanese games... the display will not be correct). This is normal. You can either use patches or an RGB cable. + +> [!CAUTION] +>## Forced Boot Sync Implementation +> This section applies only if you enable the hardware-level reset synchronization (e.g., ENABLE_HOLD_RESET_ON_BOOT) for improved stability. +>### Critical Wiring Warning +> **DO NOT connect the console's Reset point to the Arduino’s physical RST pin.** +> Reason: This creates a feedback loop. When the Arduino pulls the line LOW to sync the console, it would simultaneously trigger its own physical reset. This causes the MCU to restart before finishing the sync pulse, leading to an infinite reset cycle. +> Correct Connection: +> - ATmega328/168: Connect console Reset to D10. +> - ATmega32u4: Connect console Reset to A0. +>#### Manual Reset Behavior +> Known Limitations: While cold boot BIOS patching is highly reliable, manual resets remain "hit & miss" on Japanese FAT boards due to potential residual hardware states. A full power cycle is still recommended for best reliability on these models. +>#### Bootloader Preservation +>This mechanism allows you to safely keep the standard Arduino bootloader. You can perform real-time BIOS patching without needing to flash the AVR via ISP, making future updates much easier. ## Supported Playstation 1 All US models, all European models, and the vast majority of Japanese models. diff --git a/images/MUC Arduino/Nano.png b/images/MUC Arduino/Nano.png index a7891a0..da97103 100644 Binary files a/images/MUC Arduino/Nano.png and b/images/MUC Arduino/Nano.png differ diff --git a/images/MUC Arduino/PSNee_V8_pinout.png b/images/MUC Arduino/PSNee_V8_pinout.png index ba28823..509bb9f 100644 Binary files a/images/MUC Arduino/PSNee_V8_pinout.png and b/images/MUC Arduino/PSNee_V8_pinout.png differ diff --git a/images/MUC Arduino/Pro Micro.png b/images/MUC Arduino/Pro Micro.png index b1cdbeb..20a6175 100644 Binary files a/images/MUC Arduino/Pro Micro.png and b/images/MUC Arduino/Pro Micro.png differ diff --git a/images/MUC Arduino/micro.png b/images/MUC Arduino/micro.png index fd8efba..2590750 100644 Binary files a/images/MUC Arduino/micro.png and b/images/MUC Arduino/micro.png differ diff --git a/images/MUC Arduino/pro mini.png b/images/MUC Arduino/pro mini.png index 7054dde..29315be 100644 Binary files a/images/MUC Arduino/pro mini.png and b/images/MUC Arduino/pro mini.png differ diff --git a/images/motherboard/PM-41.png b/images/motherboard/PM-41.png index 01810c7..0e3163c 100644 Binary files a/images/motherboard/PM-41.png and b/images/motherboard/PM-41.png differ