1
0
mirror of https://github.com/kalymos/PsNee.git synced 2026-05-09 08:37:11 +00:00

Refactor BIOS patching logic and clean up codebase

New 2-phase sync (Stabilization + Silence detection).
Refactored GPIO macros for faster execution.
Cleaned up SCPH model definitions and fixed backslash warnings.
Removed unused global variables to save RAM.
This commit is contained in:
kalymos
2026-03-14 22:44:57 +01:00
parent 6fd0f51cfa
commit 4a7a429a92
4 changed files with 434 additions and 799 deletions

View File

@@ -1,320 +1,152 @@
#pragma once
#ifdef BIOS_PATCH
volatile uint8_t pulseCounter = 0;
volatile uint8_t patchStep = 0;
#ifdef INTERRUPT_RISING
ISR(PIN_AX_INTERRUPT_VECTOR) {
/*
* PHASE 3: Pulse Counting (Inside ISR)
* The hardware Interrupt Service Routine (ISR) now takes over.
* It counts the exact number of incoming pulses on PIN_AX until it
* matches the PULSE_COUNT value.
*/
//if (--pulseCounter == 0) {
pulseCounter++;
if (pulseCounter == PULSE_COUNT){ // If pulseCounter reaches the value defined by PULSE_COUNT
/*
* PHASE 4: Precision Bit Alignment
* Once the PULSE_COUNT is reached, a micro-delay (BIT_OFFSET) is applied.
* This shifts the timing from the clock edge to the exact bit position
* within the data stream that needs modification.
*/
_delay_us(BIT_OFFSET);
/*
* PHASE 5: Data Bus Overdrive (The Patch)
* Briefly forcing PIN_DX to OUTPUT to pull the line and "nullify" the target bit.
* This effectively overwrites the BIOS data on-the-fly
* before reverting the pin to INPUT to release the bus.
*/
PIN_DX_OUTPUT;
_delay_us (OVERRIDE);
PIN_DX_INPUT;
PIN_AX_INTERRUPT_DISABLE;
pulseCounter = 0;
patchStep = 1; // patchStep is set to 1, indicating that the first patch is completed.
}
}
void Bios_Patching(){
/*
* PHASE 1: Signal Stabilization & Alignment
* Detects the startup state (Cold Boot vs. Reset).
* If the line is already HIGH (Cold Boot), we wait for a full LOW-to-HIGH transition
* to ensure we are aligned with the start of a clean clock cycle.
*/
if (PIN_AX_READ != 0) { // Case: Power-on / Line high (---__-_-_)
while (PIN_AX_READ != 0); // Wait for falling edge
while (PIN_AX_READ == 0); // Wait for next rising edge to sync
}
else { // Case: Reset / Line low (_____-_-_)
while (PIN_AX_READ == 0); // Wait for the very first rising edge
}
/*
* PHASE 2: Reaching the Target Memory Window
* We introduce a strategic delay (BOOT_OFFSET) to skip initial noise.
* This points the execution to a known idle gap in the
* address range calls before the critical data appears.
* DELAY: |---//-----|
* AX: -_-_//-_-_________-_-_-_
*/
_delay_ms(BOOT_OFFSET);
// Armed for hardware detection
//pulseCounter = PULSE_COUNT;
PIN_AX_INTERRUPT_RISING;
PIN_AX_INTERRUPT_ENABLE;
while (patchStep != 1); // Wait for the first stage of the patch to complete:
PIN_LED_OFF;
}
#endif
#ifdef INTERRUPT_FALLING
ISR(PIN_AX_INTERRUPT_VECTOR) {
pulseCounter++;
if (pulseCounter == PULSE_COUNT){
_delay_us (BIT_OFFSET);
PIN_DX_OUTPUT;
_delay_us (OVERRIDE);
PIN_DX_INPUT;
PIN_AX_INTERRUPT_DISABLE;
pulseCounter = 0;
patchStep = 1;
}
}
void Bios_Patching(){
if (PIN_AX_READ != 0) {
while (PIN_AX_READ != 0);
while (PIN_AX_READ == 0);
}
else {
while (PIN_AX_READ == 0);
}
_delay_ms(BOOT_OFFSET);
PIN_AX_INTERRUPT_FALLING;
PIN_AX_INTERRUPT_ENABLE;
while (patchStep != 1);
}
#endif
#ifdef INTERRUPT_RISING_HIGH_PATCH
ISR(PIN_AX_INTERRUPT_VECTOR) {
pulseCounter++;
if (pulseCounter == PULSE_COUNT){
_delay_us (BIT_OFFSET);
PIN_DX_SET;
PIN_DX_OUTPUT;
_delay_us (OVERRIDE);
PIN_DX_CLEAR;
PIN_DX_INPUT;
PIN_AX_INTERRUPT_DISABLE;
pulseCounter = 0;
patchStep = 1;
}
}
ISR(PIN_AY_INTERRUPT_VECTOR){
pulseCounter++;
if (pulseCounter == PULSE_COUNT_2) {
_delay_us (BIT_OFFSET_2);
PIN_DX_OUTPUT;
_delay_us (OVERRIDE_2);
PIN_DX_INPUT;
PIN_AY_INTERRUPT_DISABLE;
patchStep = 2;
}
}
void Bios_Patching(){
if (PIN_AX_READ != 0) {
while (PIN_AX_READ != 0);
while (PIN_AX_READ == 0);
}
else {
while (PIN_AX_READ == 0);
}
_delay_ms(BOOT_OFFSET);
PIN_AX_INTERRUPT_RISING;
PIN_AX_INTERRUPT_ENABLE;
while (patchStep != 1);
while (PIN_AY_READ != 0);
_delay_ms(FOLLOWUP_OFFSET);
PIN_AY_INTERRUPT_RISING;
PIN_AY_INTERRUPT_ENABLE;
while (patchStep != 2);
}
#endif
#endif
/*
* ======================================================================================
* FUNCTION : Bios_Patching()
* TARGET : Data Bus (DX) synchronized via Address Bus (AX / AY)
*
* OPERATIONAL LOGIC:
* This function intercepts a specific memory transaction by counting clock cycles
* on Address lines (AX/AY) to inject modified data onto the Data line (DX)
* in real-time (On-the-fly patching).
* Intercepts specific memory transactions by monitoring address lines (AX/AY).
* Uses precise pulse counting and timed delays to inject modified data onto
* the Data line (DX) in real-time (On-the-fly patching).
*
* KEY PHASES:
* 1. SYNC (AX): Aligns the CPU with the first valid address cycle after boot/reset
* to establish a deterministic T0 reference point.
* 2. GATING (BOOT_OFFSET): Skips initial BIOS noise/calls to reach the target
* memory window.
* 3. ADDRESS COUNTING (ISR AX): Hardware-based pulse counting using ultra-fast
* decrement-to-zero logic to identify the exact target bit location.
* 4. DATA OVERDRIVE (DX): Momentarily forces DX pin to OUTPUT mode to overwrite
* the original BIOS bit with a custom logic state.
* 5. SEQUENCING (Optional AY): Transitions to a secondary address line (AY) for
* multi-stage patching or follow-up verification.
* 1. STABILIZATION & ALIGNMENT (AX): Ensures the CPU is synchronized with a
* clean rising edge of the AX signal to establish a stable reference point.
*
* 2. SILENCE DETECTION (GATING): Scans for a specific window of bus inactivity
* (SILENCE_THRESHOLD) to identify the correct pre-patching state and
* avoid false triggers from boot noise.
*
* 3. PULSE COUNTING (AX): Implements a high-speed countdown of address pulses.
* The code blocks on each edge to maintain cycle-accurate synchronization
* with the target memory access.
*
* 4. DATA OVERDRIVE (DX): At the exact target pulse, triggers a calibrated
* delay (BIT_OFFSET) before forcing the DX pin to OUTPUT mode to
* overwrite the original BIOS bit for a specific duration (OVERRIDE).
*
* 5. SECONDARY PATCH (AY): If enabled, repeats the silence detection and
* pulse counting logic on a secondary address line (AY) for multi-stage
* memory patching.
* ======================================================================================
*/
#ifdef BIOS_PATCH_3
// Shared variables between ISR and main loop
volatile uint8_t pulse_counter = 0;
volatile uint8_t patch_done = 0;
// --- MAIN INTERRUPT SERVICE ROUTINE (ADDRESS AX) ---
ISR(PIN_AX_INTERRUPT_VECTOR) {
if (--pulse_counter == 0) {
// --- PHASE 4: Precision Bit Alignment ---
__builtin_avr_delay_cycles(BIT_OFFSET_CYCLES);
// --- PHASE 5: Data Bus Overdrive (Patch applied on DX) ---
#ifdef INTERRUPT_RISING_HIGH_PATCH
PIN_DX_SET; // Pre-set HIGH if needed for this variant
#endif
PIN_DX_OUTPUT; // Take control of the data bus
__builtin_avr_delay_cycles(OVERRIDE_CYCLES);
#ifdef INTERRUPT_RISING_HIGH_PATCH
PIN_DX_CLEAR; // Release HIGH state
#endif
PIN_DX_INPUT; // Immediately release the data bus
PIN_AX_INTERRUPT_DISABLE;
PIN_LED_OFF;
patch_done = 1; // Signal completion of stage 1
}
}
// --- SECONDARY ISR (ADDRESS AY, HIGH_PATCH variant) ---
#ifdef INTERRUPT_RISING_HIGH_PATCH
ISR(PIN_AY_INTERRUPT_VECTOR) {
if (--pulse_counter == 0) {
delay_cycles(BIT_OFFSET_2_CYCLES);
PIN_DX_OUTPUT;
delay_cycles(OVERRIDE_2_CYCLES);
PIN_DX_INPUT;
PIN_AY_INTERRUPT_DISABLE;
patch_done = 2; // Signal completion of stage 2
}
}
#endif
#ifdef BIOS_PATCH
// --- BIOS Patching Main Function ---
void Bios_Patching(void) {
// --- PHASE 1: Signal Stabilization & Alignment (AX) ---
if (PIN_AX_READ != 0) { // Case: Power-on, line is high
while (PIN_AX_READ != 0); // Wait for falling edge
while (PIN_AX_READ == 0); // Wait for next rising edge to sync
} else { // Case: Reset, line is low
while (PIN_AX_READ == 0); // Wait for first rising edge
}
//--- PHASE 2: Reaching the Target Memory Window ---
//_delay_ms(BOOT_OFFSET_MS);
uint8_t pulse_counter = 0;
uint8_t current_confirms = 0;
// --- PHASE 2: Reaching the Target Memory Window (Silence Detection) ---
// Replaces the fixed _delay_ms(BOOT_OFFSET_MS)
PIN_AX_INPUT;
// --- PHASE 1: Signal Stabilization & Alignment (AX) ---
if (PIN_AX_READ != 0) {
while WAIT_AX_FALLING; // Wait for falling edge
while WAIT_AX_RISING; // Wait for next rising edge to sync
} else {
while WAIT_AX_RISING; // Wait for first rising edge
}
uint8_t current_confirms = 0;
// --- PHASE 2: Silence Detection (AX) ---
while (current_confirms < CONFIRM_COUNTER_TARGET) {
uint16_t count = SILENCE_THRESHOLD;
while (current_confirms < CONFIRM_COUNTER_TARGET) {
uint16_t count = SILENCE_THRESHOLD;
// --- Scan for ONE continuous block of silence ---
while (count > 0) {
if (PIN_AX_READ != 0) {
while WAIT_AX_FALLING; // Pulse detected: wait for bus to clear
break; // Reset and try a new silence block
}
count--;
}
// If count reaches 0, a silent block is validated
if (count == 0) {
current_confirms++;
}
}
PIN_LED_ON;
// --- PHASE 3: Pulse Counting & Patch 1 (AX) ---
pulse_counter = PULSE_COUNT;
while (pulse_counter > 0) {
while WAIT_AX_RISING; // Block here until rising edge
// --- Attempt to find ONE block of silence ---
while (count > 0) {
if (PIN_AX_READ != 0) {
// Activity detected: current block is invalid
// Wait for bus to clear before trying a NEW block
while (PIN_AX_READ != 0);
break;
pulse_counter--;
if (pulse_counter == 0) {
// Precise cycle-accurate delay before triggering
__builtin_avr_delay_cycles(BIT_OFFSET_CYCLES);
#ifdef INTERRUPT_RISING_HIGH_PATCH
PIN_DX_SET;
#endif
PIN_DX_OUTPUT; // Pull the line (Override start)
__builtin_avr_delay_cycles(OVERRIDE_CYCLES);
#ifdef INTERRUPT_RISING_HIGH_PATCH
PIN_DX_CLEAR; // Release the bus (Override end)
#endif
PIN_DX_INPUT;
PIN_LED_OFF;
break;
}
while WAIT_AX_FALLING; // Wait for pulse to clear
}
//PIN_LED_OFF;
// -------- Secondary Patch ----------
#ifdef INTERRUPT_RISING_HIGH_PATCH
current_confirms = 0;
while (current_confirms < CONFIRM_COUNTER_TARGET_2) {
uint16_t count = SILENCE_THRESHOLD;
while (count > 0) {
if (PIN_AX_READ != 0) {
while WAIT_AX_FALLING;
break;
}
count--;
}
if (count == 0) {
current_confirms++;
}
count--;
}
// If count reached 0, we found 500us of silence
if (count == 0) {
current_confirms++;
} else {
PIN_LED_ON;
pulse_counter = PULSE_COUNT_2;
}
}
while (pulse_counter > 0) {
while WAIT_AY_RISING;
pulse_counter--;
PIN_LED_ON;
if (pulse_counter == 0) {
__builtin_avr_delay_cycles(BIT_OFFSET_2_CYCLES);
PIN_DX_OUTPUT;
__builtin_avr_delay_cycles(OVERRIDE_2_CYCLES);
PIN_DX_INPUT;
PIN_LED_OFF;
break;
}
while WAIT_AY_FALLING;
// --- Prepare pulse counter and patch status flag ---
pulse_counter = PULSE_COUNT;
patch_done = 0;
// --- Dynamic interrupt configuration ---
#if defined(INTERRUPT_RISING) || defined(INTERRUPT_RISING_HIGH_PATCH)
PIN_AX_INTERRUPT_RISING;
#elif defined(INTERRUPT_FALLING)
PIN_AX_INTERRUPT_FALLING;
#endif
PIN_AX_INTERRUPT_ENABLE;
while (patch_done != 1); // Wait until stage 1 is completed
// --- Optional secondary patch phase for HIGH_PATCH ---
#ifdef INTERRUPT_RISING_HIGH_PATCH
while (PIN_AY_READ != 0); // Ensure AY line is low before arming
_delay_ms(FOLLOWUP_OFFSET_MS);
pulse_counter = PULSE_COUNT_2; // Reload counter for AY pulses
PIN_AY_INTERRUPT_RISING;
PIN_AY_INTERRUPT_ENABLE;
while (patch_done != 2); // Wait until stage 2 is completed
#endif
}
}
#endif

View File

@@ -227,30 +227,38 @@
#ifdef ATmega328_168
static inline void optimizePeripherals(void) {
// --- Port C & Digital Input Configuration (A0-A5) ---
// 1. Set Port C as inputs (DDRC bits 0-5 to 0)
DDRC &= ~((1<<DDC5)|(1<<DDC4)|(1<<DDC3)|(1<<DDC2)|(1<<DDC1)|(1<<DDC0));
// 2. Enable Digital Input Buffers by clearing DIDR0 (Required for digital PINC reads)
DIDR0 &= ~((1<<ADC5D)|(1<<ADC4D)|(1<<ADC3D)|(1<<ADC2D)|(1<<ADC1D)|(1<<ADC0D));
// 1. Disable Interrupts during setup
cli();
// --- Analog Modules Shutdown (Power Saving & Noise Reduction) ---
// 1. Disable the ADC module (ADEN = 0)
ADCSRA &= ~(1 << ADEN);
// 2. Disable the Analog Comparator (ACD = 1) to free resources on PD6/PD7
ACSR |= (1 << ACD);
// 2. Analog Modules Shutdown (Critical for Power)
ADCSRA &= ~(1 << ADEN); // Disable ADC
ACSR |= (1 << ACD); // Disable Analog Comparator
// --- Power Reduction Register (Hard Clock Shut Off) ---
// Stops the clock to internal modules: ADC, Timer 0 (millis), and Timer 2
PRR |= (1 << PRADC) | (1 << PRTIM0) | (1 << PRTIM2);
// 3. Digital Input Disable (Set bits to 1 to DISABLE)
// Disconnects digital buffers on analog pins to stop leakage
DIDR0 = 0x3F; // Pins A0 to A5
// --- Timer 0 Specific Shutdown ---
// Double security: disconnect clock source and disable interrupts
// 4. GPIO Strategy (Unused pins to Pull-up)
// PORTx = 0xFF (Pull-ups) | DDRx = 0x00 (Inputs)
PORTC |= 0xFF;
// 5. Power Reduction Register (PRR)
// We KEEP PRUSART0 (UART) and shut down EVERYTHING else.
// _delay_ms() will still work (it's cycle-based, not timer-based).
PRR = (1 << PRTWI) | // I2C Off
(1 << PRSPI) | // SPI Off
(1 << PRTIM0) | // Timer 0 Off (millis/delay Arduino Off)
(1 << PRTIM1) | // Timer 1 Off
(1 << PRTIM2) | // Timer 2 Off
(1 << PRADC); // ADC Clock Off
// 6. Double Security for Timer 0
TCCR0B = 0;
TIMSK0 = 0;
}
// Define the clock speed for the microcontroller
//#define F_CPU 16000000L
// 7. Restart interrupts if UART uses them (RX/TX ISR)
sei();
}
#include <stdint.h>
#include <stdbool.h>
@@ -259,12 +267,6 @@
#include <avr/sfr_defs.h>
#include <util/delay.h>
// Global interrupt control settings
#define GLOBAL_INTERRUPT_ENABLE sei()
#define GLOBAL_INTERRUPT_DISABLE cli()
// #define GLOBAL_INTERRUPT_ENABLE SREG |= (1 << 7) // Set the I-bit (bit 7) in the Status Register to enable global interrupts
// #define GLOBAL_INTERRUPT_DISABLE SREG &= ~(1 << 7) // Clear the I-bit (bit 7) in the Status Register to disable global interrupts
// Main pin configuration
// Define the main pins as inputs
@@ -297,10 +299,7 @@
#endif
// Handling the BIOS patch
#if defined(SCPH_102) || defined(SCPH_100) || defined(SCPH_7500_9000) || defined(SCPH_7000) || defined(SCPH_5500) || defined(SCPH_5000) || defined(SCPH_3500) || 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
#if defined(SCPH_102) || defined(SCPH_100) || defined(SCPH_7500_9000) || defined(SCPH_7000) || defined(SCPH_5000_5500) || defined(SCPH_3500) || defined(SCPH_3000) || defined(SCPH_1000)
// Define input pins for the BIOS patch
#define PIN_AX_INPUT DDRD &= ~(1 << DDD2) // Set DDRD register to configure PIND2 as input
@@ -315,28 +314,19 @@
// Set pull-ups low on output pins
#define PIN_DX_CLEAR PORTD &= ~(1 << PD4) // Set PORTD register to make PIND4 low
#define WAIT_AX_RISING (!(PIND & (1 << PIND2))) // Attend le début de l'impulsion
#define WAIT_AX_FALLING (PIND & (1 << PIND2)) // Attend la fin de l'impulsion
// Read the input pins for the BIOS patch
#define PIN_AX_READ (!!(PIND & (1 << PIND2))) // Read the state of PIND2
// External interrupt configuration for BIOS patch
#define PIN_AX_INTERRUPT_ENABLE EIMSK |= (1 << INT0) // Enable external interrupt on INT0 (PINB2)
#define PIN_AX_INTERRUPT_DISABLE EIMSK &= ~(1 << INT0) // Disable external interrupt on INT0
#define PIN_AX_INTERRUPT_RISING EICRA |= (1 << ISC01) | (1 << ISC00) // Configure INT0 for rising edge trigger
//#define PIN_AX_INTERRUPT_FALLING (EICRA = (1 << ISC01))
#define PIN_AX_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC00)) | (1 << ISC01)) // Configure INT0 for falling edge trigger
// Interrupt vectors for external interrupts
#define PIN_AX_INTERRUPT_VECTOR INT0_vect // Interrupt vector for INT0 (external interrupt)
// Defin PIN_AY for HIGH_PATCH
#if defined(SCPH_3000) || defined(SCPH_1000)
#define PIN_AY_INPUT DDRD &= ~(1 << DDD3) // Set DDRD register to configure PIND3 as input
#define PIN_AY_READ (!!(PIND & (1 << PIND3))) // Read the state of PIND3
#define PIN_AY_INTERRUPT_ENABLE EIMSK |= (1 << INT1) // Enable external interrupt on INT1 (PINB3)
#define PIN_AY_INTERRUPT_DISABLE EIMSK &= ~(1 << INT1) // Disable external interrupt on INT1
#define PIN_AY_INTERRUPT_RISING EICRA |= (1 << ISC11) | (1 << ISC10) // Configure INT1 for rising edge trigger
#define PIN_AY_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC10)) | (1 << ISC11)) // Configure INT1 for falling edge trigger
#define PIN_AY_INTERRUPT_VECTOR INT1_vect // Interrupt vector for INT1 (external interrupt)
#define WAIT_AY_RISING (!(PIND & (1 << PIND3))) // AY est sur PIND3
#define WAIT_AY_FALLING (PIND & (1 << PIND3))
#endif
// Handle switch input for BIOS patch
#if defined(SCPH_7000)

View File

@@ -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
@@ -47,9 +47,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//#define SCPH_100 // DX - D0 | AX - A7 | | 4.3j - CRC F2AF798B
//#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_5000 // DX - D0 | AX - A5 | AX - A4 | 2.2j - CRC 24FC7E17
//#define SCPH_3500 // DX - D0 | AX - A5 | AX - A4 | 2.1j - CRC BC190209
//#define SCPH_5000_5500 // DX - D0 | AX - A15 | | 3.0j - CRC FF3EEB8C, 2.2j - CRC 24FC7E17
//#define SCPH_3500 // DX - D0 | AX - A15 | AX - A15 | 2.1j - CRC BC190209
//#define SCPH_3000 // DX - D5 | AX - A7, AY - A8 | AX - A6, AY - A7 | 1.1j - CRC 3539DEF6
//#define SCPH_1000 // DX - D5 | AX - A7, AY - A8 | AX - A6, AY - A7 | 1.0j - CRC 3B601FC8
@@ -130,28 +129,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//Flag initializing for automatic console generation selection 0 = old, 1 = pu-22 end ++
volatile uint8_t wfck_mode = 0;
// --- Prototypes (Forward declarations) ---
// These tell the compiler that the functions exist later in the code.
// Function pointer type definition for the console detection logic.
// This allows switching between 'Standard' and 'SCPH-5903' heuristics dynamically.
// Définition du type de pointeur de fonction pour la logique de console
typedef void (*ConsoleLogicPtr)(uint8_t isDataSector);
// Déclarations forward des deux fonctions
void processStandardLogic(uint8_t isDataSector);
void processScph5903Logic(uint8_t isDataSector);
// Pointeur global vers la fonction active
#ifdef SCPH_5903
volatile ConsoleLogicPtr currentLogic = processScph5903Logic;
#else
volatile ConsoleLogicPtr currentLogic = processStandardLogic;
#endif
// Variables de contrôle globales
// Global buffer to store the 12-byte Sub-Q channel data
uint8_t subqBuffer[12];
@@ -225,16 +202,11 @@ void board_detection() {
}
}
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Log(wfck_mode);
#endif
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Log(wfck_mode);
#endif
}
//******************************************************************************************************************
// Reads a complete 12-byte SUBQ transmission from the CD drive.
// Uses clock-edge synchronization and includes a safety timeout for malformatted streams.
@@ -265,9 +237,9 @@ void captureSubQ(void) {
*bufferPtr++ = currentByte;
} while (--bytesRemaining); // Faster than (bytesRemaining < 12)
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
logSubQ(subqBuffer);
#endif
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
logSubQ(subqBuffer);
#endif
}
/**************************************************************************************
@@ -282,8 +254,9 @@ void captureSubQ(void) {
* isDataSector Boolean flag indicating if the current sector contains data.
**************************************************************************************/
#ifdef SCPH_5903
void processScph5903Logic(uint8_t isDataSector) {
void processLogic(uint8_t isDataSector) {
uint8_t currentHysteresis = hysteresis;
// Fast filtering: most sectors fail here by checking sync markers (index 1 and 6)
@@ -310,8 +283,8 @@ void processScph5903Logic(uint8_t isDataSector) {
if (currentHysteresis > 0) {
hysteresis = currentHysteresis - 1;
}
}
}
#else
/******************************************************************************************
* Heuristic logic for standard PlayStation hardware (Non-VCD models).
*
@@ -325,7 +298,8 @@ void processScph5903Logic(uint8_t isDataSector) {
******************************************************************************************/
void processStandardLogic(uint8_t isDataSector) {
void processLogic(uint8_t isDataSector) {
uint8_t currentHysteresis = hysteresis;
// Fast filtering: most sectors fail here by checking sync markers (index 1 and 6)
@@ -357,7 +331,9 @@ void processStandardLogic(uint8_t isDataSector) {
if (currentHysteresis > 0) {
hysteresis = currentHysteresis - 1;
}
}
}
#endif
/*********************************************************************************************
* Executes the SCEx injection sequence to bypass the CD-ROM regional lockout.
@@ -374,168 +350,159 @@ void processStandardLogic(uint8_t isDataSector) {
*********************************************************************************************/
void performInjectionSequence(uint8_t injectSCEx) {
/*
Security strings (44-bit SCEx) for the three main regions:
0: NTSC-J (SCEI - Sony Computer Entertainment Inc.)
1: NTSC-U/C (SCEA - Sony Computer Entertainment America)
2: PAL (SCEE - Sony Computer Entertainment Europe)
Stored in 6 bytes (48 bits); only the first 44 bits are used during injection.
*/
static const uint8_t allRegionsSCEx[3][6] = {
{ 0x59, 0xC9, 0x4B, 0x5D, 0xDA, 0x02 }, // SCEI
{ 0x59, 0xC9, 0x4B, 0x5D, 0xFA, 0x02 }, // SCEA
{ 0x59, 0xC9, 0x4B, 0x5D, 0xEA, 0x02 } // SCEE
};
/*
Security strings (44-bit SCEx) for the three main regions:
0: NTSC-J (SCEI - Sony Computer Entertainment Inc.)
1: NTSC-U/C (SCEA - Sony Computer Entertainment America)
2: PAL (SCEE - Sony Computer Entertainment Europe)
Stored in 6 bytes (48 bits); only the first 44 bits are used during injection.
*/
static const uint8_t allRegionsSCEx[3][6] = {
{ 0x59, 0xC9, 0x4B, 0x5D, 0xDA, 0x02 }, // SCEI
{ 0x59, 0xC9, 0x4B, 0x5D, 0xFA, 0x02 }, // SCEA
{ 0x59, 0xC9, 0x4B, 0x5D, 0xEA, 0x02 } // SCEE
};
hysteresis = 11; // Reset hysteresis to mid-point after triggering
#ifdef LED_RUN
PIN_LED_ON;
#endif
hysteresis = 11; // Reset hysteresis to mid-point after triggering
#ifdef LED_RUN
PIN_LED_ON;
#endif
// Cache wfck_mode to save CPU cycles during the bit loop
uint8_t isWfck = wfck_mode;
// Cache wfck_mode to save CPU cycles during the bit loop
uint8_t isWfck = wfck_mode;
PIN_DATA_OUTPUT;
PIN_DATA_CLEAR;
// Legacy boards require the chip to drive the simulated WFCK/Gate
if (!isWfck) {
PIN_WFCK_OUTPUT;
PIN_WFCK_CLEAR;
}
_delay_ms(DELAY_BETWEEN_INJECTIONS);
// Loop through the selected region(s)
for (uint8_t i = 0; i < 3; i++) {
uint8_t regionIndex = (injectSCEx == 3) ? i : injectSCEx;
const uint8_t* bytePtr = allRegionsSCEx[regionIndex];
uint8_t currentByte = *bytePtr++;
uint8_t bitIdx = 0;
// Process the 44-bit SCEx stream
for (uint8_t totalBits = 44; totalBits > 0; totalBits--) {
uint8_t currentBit = currentByte & 0x01;
currentByte >>= 1;
bitIdx++;
// Reload next byte every 8 bits (except the last partial one)
if (bitIdx == 8 && totalBits > 4) {
currentByte = *bytePtr++;
bitIdx = 0;
}
if (currentBit == 0) {
// BIT 0: Pull DATA low-
PIN_DATA_CLEAR;
if (!isWfck) PIN_DATA_OUTPUT;
_delay_us(DELAY_BETWEEN_BITS);
} else {
// BIT 1: Handle based on board generation
if (!isWfck) {
// Legacy Mode: Set DATA to High-Z (floating)
PIN_DATA_INPUT;
_delay_us(DELAY_BETWEEN_BITS);
} else {
/*
WFCK Modulation Loop: Syncs to 7.3kHz or 14.6kHz.
Follows hardware edges to stay bit-perfect with the console.
*/
uint8_t count = 30;
while (count--) {
while (PIN_WFCK_READ); // Wait for Falling Edge
PIN_DATA_CLEAR;
while (!PIN_WFCK_READ); // Wait for Rising Edge
PIN_DATA_SET;
}
}
}
}
// Clean up state between region cycles
PIN_DATA_OUTPUT;
PIN_DATA_CLEAR;
// Legacy boards require the chip to drive the simulated WFCK/Gate
if (!isWfck) {
PIN_WFCK_OUTPUT;
PIN_WFCK_CLEAR;
}
_delay_ms(DELAY_BETWEEN_INJECTIONS);
// Loop through the selected region(s)
for (uint8_t i = 0; i < 3; i++) {
uint8_t regionIndex = (injectSCEx == 3) ? i : injectSCEx;
const uint8_t* bytePtr = allRegionsSCEx[regionIndex];
uint8_t currentByte = *bytePtr++;
uint8_t bitIdx = 0;
/*
EXIT CONDITION:
If we are NOT in Universal mode (3), we stop after the first
successful region injection.
*/
if (injectSCEx != 3) break;
}
// Process the 44-bit SCEx stream
for (uint8_t totalBits = 44; totalBits > 0; totalBits--) {
uint8_t currentBit = currentByte & 0x01;
currentByte >>= 1;
bitIdx++;
// Restore pins to Input/High-Z to avoid signal interference after injection
if (!isWfck) {
PIN_WFCK_INPUT;
PIN_DATA_INPUT;
}
// Reload next byte every 8 bits (except the last partial one)
if (bitIdx == 8 && totalBits > 4) {
currentByte = *bytePtr++;
bitIdx = 0;
}
if (currentBit == 0) {
// BIT 0: Pull DATA low-
PIN_DATA_CLEAR;
if (!isWfck) PIN_DATA_OUTPUT;
_delay_us(DELAY_BETWEEN_BITS);
} else {
// BIT 1: Handle based on board generation
if (!isWfck) {
// Legacy Mode: Set DATA to High-Z (floating)
PIN_DATA_INPUT;
_delay_us(DELAY_BETWEEN_BITS);
} else {
/*
WFCK Modulation Loop: Syncs to 7.3kHz or 14.6kHz.
Follows hardware edges to stay bit-perfect with the console.
*/
uint8_t count = 30;
while (count--) {
while (PIN_WFCK_READ); // Wait for Falling Edge
PIN_DATA_CLEAR;
while (!PIN_WFCK_READ); // Wait for Rising Edge
PIN_DATA_SET;
}
}
}
}
// Clean up state between region cycles
PIN_DATA_OUTPUT;
PIN_DATA_CLEAR;
_delay_ms(DELAY_BETWEEN_INJECTIONS);
/*
EXIT CONDITION:
If we are NOT in Universal mode (3), we stop after the first
successful region injection.
*/
if (injectSCEx != 3) break;
}
// Restore pins to Input/High-Z to avoid signal interference after injection
if (!isWfck) {
PIN_WFCK_INPUT;
PIN_DATA_INPUT;
}
#ifdef LED_RUN
PIN_LED_OFF;
#endif
#ifdef LED_RUN
PIN_LED_OFF;
#endif
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Inject();
#endif
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Inject();
#endif
}
void Init() {
#if defined(ATmega328_168)
optimizePeripherals();
#endif
#if defined(ATmega328_168)
optimizePeripherals();
#endif
#ifdef LED_RUN
PIN_LED_OUTPUT;
#endif
#ifdef LED_RUN
PIN_LED_OUTPUT;
#endif
#ifdef BIOS_PATCH_3
uint8_t skipPatch = 0;
GLOBAL_INTERRUPT_ENABLE;
#ifdef BIOS_PATCH
//uint8_t skipPatch = 0;
#ifdef SCPH_7000
// Check hardware switch for SCPH-7000 models
PIN_SWITCH_INPUT;
PIN_SWITCH_SET;
if (PIN_SWITCH_READ == 0){
skipPatch =1; // Disable patching if switch is triggered
}
#endif
// #ifdef SCPH_7000
// // Check hardware switch for SCPH-7000 models
// PIN_SWITCH_INPUT;
// PIN_SWITCH_SET;
// if (PIN_SWITCH_READ == 0){
// skipPatch =1; // Disable patching if switch is triggered
// }
// #endif
// #ifdef LED_RUN
// PIN_LED_ON;
// #endif
// Execute BIOS patching unless bypassed by switch
if (skipPatch == 0) {
// if (skipPatch == 0) {
Bios_Patching();
}
// }
// #ifdef LED_RUN
// PIN_LED_OFF;
// #endif
#endif
#endif
// Disable interrupts and set CD-ROM interface pins to Input
GLOBAL_INTERRUPT_DISABLE;
PIN_SQCK_INPUT;
PIN_SUBQ_INPUT;
#if defined(PSNEE_DEBUG_SERIAL_MONITOR) && defined(ATtiny85_45_25)
//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(PSNEE_DEBUG_SERIAL_MONITOR) && !defined(ATtiny85_45_25)
Serial.begin(500000); // 60 bytes in 12ms (expected data: ~26 bytes / 12ms) // update: this is actually quicker
#endif
#if defined(PSNEE_DEBUG_SERIAL_MONITOR) && defined(ATtiny85_45_25)
//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(PSNEE_DEBUG_SERIAL_MONITOR) && !defined(ATtiny85_45_25)
Serial.begin(500000); // 60 bytes in 12ms (expected data: ~26 bytes / 12ms) // update: this is actually quicker
#endif
// Detect board generation (PU-7 to PU-22+) before starting the main loop
board_detection();
@@ -545,12 +512,6 @@ int main() {
Init();
// #ifdef SCPH_5903
// currentLogic = logic_SCPH_5903;
// #else
// currentLogic = logic_Standard;
// #endif
while (1) {
@@ -569,8 +530,8 @@ int main() {
uint8_t isDataSector = ((subqBuffer[0] & 0xD0) == 0x40);
// Execute selected logic through function pointer
currentLogic(isDataSector);
// Execute selected logic
processLogic(isDataSector);
//Trigger SCEx injection once the confidence threshold is reached
if (hysteresis >= HYSTERESIS_MAX) {

View File

@@ -7,12 +7,6 @@
The temporal precision of _delay_us depends on the microcontroller's clock frequency (F_CPU).
For the ATmega328 operating at a typical frequency of 16 MHz, here are some details on the precision.
Clock Frequency: F_CPU must be defined correctly before using the function. For an ATmega328 operating at 16 MHz:
1 clock cycle = 1 / 16,000,000 s ≈ 62.5 ns
1 µs ≈ 16 clock cycles
BIT_OFFSET _delay_us(2.75) = 44 clock cycles
OVERRIDE _delay_us(0.2) = 3,2 clock cycles
*/
@@ -23,304 +17,138 @@
// tested with an Atmega328P
#ifdef SCPH_102
#define BIOS_PATCH_2
#define INTERRUPT_RISING
#define BOOT_OFFSET 83.9
#define PULSE_COUNT 48
//#define BIT_OFFSET 2.75
#define BIT_OFFSET 3.25 //BIOS_PATCH_2
#define OVERRIDE 0.2
#endif
// #ifdef SCPH_100
// #define BIOS_PATCH
// #define INTERRUPT_RISING
// #define BOOT_OFFSET 83.9 //83.72 - 84.15
// #define PULSE_COUNT 48
// #define BIT_OFFSET 2.75 //2.63 - 2.87
// #define OVERRIDE 0.2
// #endif
// #ifdef SCPH_7500_9000
// #define BIOS_PATCH
// #define INTERRUPT_RISING
// #define BOOT_OFFSET 75.2 //74.95 - 75.55
// #define PULSE_COUNT 16
// #define BIT_OFFSET 2.8
// #define OVERRIDE 0.2
// #endif
#ifdef SCPH_7000
#define BIOS_PATCH
#define INTERRUPT_RISING
#define BOOT_OFFSET 75.2 //75.3
#define PULSE_COUNT 16
#define BIT_OFFSET 2.8
#define OVERRIDE 0.2
#endif
#ifdef SCPH_5500
#define BIOS_PATCH
#define INTERRUPT_FALLING
#define BOOT_OFFSET 76.04 //75.99 - 76.14
#define PULSE_COUNT 21
#define BIT_OFFSET 2.8
#define OVERRIDE 0.2
#endif
#ifdef SCPH_5000
#define BIOS_PATCH
#define INTERRUPT_FALLING
#define BOOT_OFFSET 75.2 //75.12 - 75.27
#define PULSE_COUNT 21
#define BIT_OFFSET 2.8 //2.7 - 2.85
#define OVERRIDE 0.1
#endif
#ifdef SCPH_3500
#define BIOS_PATCH
#define INTERRUPT_FALLING
#define BOOT_OFFSET 75.2 //75.12 - 75.27
#define PULSE_COUNT 21
#define BIT_OFFSET 2.75 //2.65 - 2.85
#define OVERRIDE 0.2
#endif
#ifdef SCPH_3000
#define BIOS_PATCH
#define INTERRUPT_RISING_HIGH_PATCH
#define BOOT_OFFSET 82.9 //82.65 - 83.26
#define PULSE_COUNT 60
#define BIT_OFFSET 2.7 //2.58 - 2.8
#define OVERRIDE 0.15
#define HIGH_PATCH
#define FOLLOWUP_OFFSET 253.3
#define PULSE_COUNT_2 43
#define BIT_OFFSET_2 2.88
#define OVERRIDE_2 0.15
#endif
#ifdef SCPH_1000
#define BIOS_PATCH
#define INTERRUPT_RISING_HIGH_PATCH
#define BOOT_OFFSET 82.9 // 82.63 - 83.26
#define PULSE_COUNT 92
#define BIT_OFFSET 2.65 // 2.58 - 2.75
#define OVERRIDE 0.15
#define HIGH_PATCH
#define FOLLOWUP_OFFSET 272.8
#define PULSE_COUNT_2 71
#define BIT_OFFSET_2 2.88
#define OVERRIDE_2 0.15
#endif
// // -------- SCPH 102 --------
// #ifdef SCPH_102
// #define BIOS_PATCH_2
// #define INTERRUPT_RISING
// ------ SCPH 100 / 102 ------
#if defined(SCPH_100) || \
defined(SCPH_102)
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 84
// #define PULSE_COUNT 48
// #define BIT_OFFSET_CYCLES 26 // 3.25us / 0.125us ≈ 26 cycles
// #define OVERRIDE_CYCLES 2 // 0.2us / 0.125us ≈ 2 cycles
// #elif defined(F_CPU_16MHZ)
// #define BOOT_OFFSET_MS 84
// #define PULSE_COUNT 48
// #define BIT_OFFSET_CYCLES 52 // 3.25 / 0.0625 ≈ 52 cycles
// #define OVERRIDE_CYCLES 3 // 0.2 / 0.0625 ≈ 3 cycles
// #endif
// #endif
// -------- SCPH 100 --------
#ifdef SCPH_100
#define BIOS_PATCH_3
#define INTERRUPT_RISING
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 84
// #define PULSE_COUNT 48
// #define BIT_OFFSET_CYCLES 22 // 2.75 / 0.125 ≈ 22 cycles
// #define OVERRIDE_CYCLES 2 // 0.2 / 0.125 ≈ 2 cycles
// #elif defined(F_CPU_16MHZ)
//#define BOOT_OFFSET_MS 84
#define SILENCE_THRESHOLD 1428
#define CONFIRM_COUNTER_TARGET 8
#define PULSE_COUNT 48
#define BIT_OFFSET_CYCLES 47 // 2.75 / 0.0625 ≈ 44 cycles +3
#define OVERRIDE_CYCLES 3 // 0.2 / 0.0625 ≈ 3 cycles
#define BIOS_PATCH
#define SILENCE_THRESHOLD 1400
#define CONFIRM_COUNTER_TARGET 8
#define PULSE_COUNT 47
#define BIT_OFFSET_CYCLES 67 //60+7
#define OVERRIDE_CYCLES 3
#endif
// #endif
// // -------- SCPH 7500 / 9000 --------
#ifdef SCPH_7500_9000
#define BIOS_PATCH_3
#define INTERRUPT_RISING
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 75
// #define PULSE_COUNT 16
// #define BIT_OFFSET_CYCLES 22 // 2.8 / 0.125 ≈ 22 cycles
// #define OVERRIDE_CYCLES 2 // 0.2 / 0.125 ≈ 2 cycles
//#elif defined(F_CPU_16MHZ)
//#define BOOT_OFFSET_MS 75
#define SILENCE_THRESHOLD 1428
#define CONFIRM_COUNTER_TARGET 1
#define PULSE_COUNT 16
#define BIT_OFFSET_CYCLES 47 // 2.8 / 0.0625 ≈ 45 cycles
#define OVERRIDE_CYCLES 3 // 0.2 / 0.0625 ≈ 3 cycles
#define BIOS_PATCH
#define SILENCE_THRESHOLD 1400
#define CONFIRM_COUNTER_TARGET 1
#define PULSE_COUNT 15
#define BIT_OFFSET_CYCLES 66 //60+
#define OVERRIDE_CYCLES 4
#endif
// #endif
// // -------- SCPH 7000 --------
// #ifdef SCPH_7000
// #define BIOS_PATCH
// #define INTERRUPT_RISING
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 75
// #define PULSE_COUNT 16
// #define BIT_OFFSET_CYCLES 22
// #define OVERRIDE_CYCLES 2
// #elif defined(F_CPU_16MHZ)
// #define BOOT_OFFSET_MS 75
// #define PULSE_COUNT 16
// #define BIT_OFFSET_CYCLES 45
// #define OVERRIDE_CYCLES 3
// #endif
// #endif
// -------- SCPH 7000 --------
#ifdef SCPH_7000
#define BIOS_PATCH
#define SILENCE_THRESHOLD 1400
#define CONFIRM_COUNTER_TARGET 1
#define PULSE_COUNT 15
#define BIT_OFFSET_CYCLES 66
#define OVERRIDE_CYCLES 4
#endif
// // -------- SCPH 5500 --------
// #ifdef SCPH_5500
// #define BIOS_PATCH
// #define INTERRUPT_FALLING
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 76
// #define PULSE_COUNT 21
// #define BIT_OFFSET_CYCLES 22
// #define OVERRIDE_CYCLES 2
// #elif defined(F_CPU_16MHZ)
// #define BOOT_OFFSET_MS 76
// #define PULSE_COUNT 21
// #define BIT_OFFSET_CYCLES 45
// #define OVERRIDE_CYCLES 3
// #endif
// #endif
// // ----- SCPH 5000 / 5500 -----
#ifdef SCPH_5000_5500
#define BIOS_PATCH
#define SILENCE_THRESHOLD 35000
#define CONFIRM_COUNTER_TARGET 1
#define PULSE_COUNT 84
#define BIT_OFFSET_CYCLES 60
#define OVERRIDE_CYCLES 3
#endif
// // -------- SCPH 5000 --------
// // // -------- SCPH 5000 --------
// #ifdef SCPH_5000
// #define BIOS_PATCH
// #define INTERRUPT_FALLING
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 75
// #define PULSE_COUNT 21
// #define BIT_OFFSET_CYCLES 22
// #define OVERRIDE_CYCLES 1
// #elif defined(F_CPU_16MHZ)
// #define BOOT_OFFSET_MS 75
// #define PULSE_COUNT 21
// #define BIT_OFFSET_CYCLES 45
// #define OVERRIDE_CYCLES 2
// #endif
// #define BIOS_PATCH_3
// #define INTERRUPT_RISING
// #define SILENCE_THRESHOLD 35000
// #define CONFIRM_COUNTER_TARGET 1
// #define PULSE_COUNT 84
// #define BIT_OFFSET_CYCLES 60
// #define OVERRIDE_CYCLES 3
// #endif
// // #endif
// // -------- SCPH 3500 --------
// #ifdef SCPH_3500
// #define BIOS_PATCH
// #define INTERRUPT_FALLING
#ifdef SCPH_3500
#define BIOS_PATCH
#define SILENCE_THRESHOLD 34000
#define CONFIRM_COUNTER_TARGET 1
#define PULSE_COUNT 85
#define BIT_OFFSET_CYCLES 44
#define OVERRIDE_CYCLES 3
#endif
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 75
// #define PULSE_COUNT 21
// #define BIT_OFFSET_CYCLES 22
// #define OVERRIDE_CYCLES 2
// #elif defined(F_CPU_16MHZ)
// #define BOOT_OFFSET_MS 75
// #define PULSE_COUNT 21
// #define BIT_OFFSET_CYCLES 44
// #define OVERRIDE_CYCLES 3
// #endif
// #endif
// // -------- SCPH 3000 --------
// #ifdef SCPH_3000
// #define BIOS_PATCH
// #define INTERRUPT_RISING_HIGH_PATCH
// #define HIGH_PATCH
#ifdef SCPH_3000
#define BIOS_PATCH
#define INTERRUPT_RISING_HIGH_PATCH
#define SILENCE_THRESHOLD 1200
#define CONFIRM_COUNTER_TARGET 9
#define PULSE_COUNT 60
#define BIT_OFFSET_CYCLES 46
#define OVERRIDE_CYCLES 3
#define SILENCE_THRESHOLD_2 1200
#define CONFIRM_COUNTER_TARGET_2 206
#define PULSE_COUNT_2 43
#define BIT_OFFSET_2_CYCLES 54
#define OVERRIDE_2_CYCLES 2
#endif
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 83
// #define PULSE_COUNT 60
// #define BIT_OFFSET_CYCLES 22
// #define OVERRIDE_CYCLES 1
// #define FOLLOWUP_OFFSET_MS 253
// #define PULSE_COUNT_2 43
// #define BIT_OFFSET_2_CYCLES 23
// #define OVERRIDE_2_CYCLES 1
// #elif defined(F_CPU_16MHZ)
// #define BOOT_OFFSET_MS 83
// #define PULSE_COUNT 60
// #define BIT_OFFSET_CYCLES 43
// #define OVERRIDE_CYCLES 2
// #define FOLLOWUP_OFFSET_MS 253
// #define PULSE_COUNT_2 43
// #define BIT_OFFSET_2_CYCLES 46
// #define OVERRIDE_2_CYCLES 2
// #endif
// #endif
// // -------- SCPH 1000 --------
// #ifdef SCPH_1000
// #define BIOS_PATCH
// #define INTERRUPT_RISING_HIGH_PATCH
// #define HIGH_PATCH
// #ifdef F_CPU_8MHZ
// #define BOOT_OFFSET_MS 83
// #define PULSE_COUNT 92
// #define BIT_OFFSET_CYCLES 21
// #define OVERRIDE_CYCLES 1
// #define FOLLOWUP_OFFSET_MS 273
// #define PULSE_COUNT_2 71
// #define BIT_OFFSET_2_CYCLES 23
// #define OVERRIDE_2_CYCLES 1
// #elif defined(F_CPU_16MHZ)
// #define BOOT_OFFSET_MS 83
// #define PULSE_COUNT 92
// #define BIT_OFFSET_CYCLES 42
// #define OVERRIDE_CYCLES 2
// #define FOLLOWUP_OFFSET_MS 273
// #define PULSE_COUNT_2 71
// #define BIT_OFFSET_2_CYCLES 46
// #define OVERRIDE_2_CYCLES 2
// #endif
#ifdef SCPH_1000
#define BIOS_PATCH
#define INTERRUPT_RISING_HIGH_PATCH
#define SILENCE_THRESHOLD 1300
#define CONFIRM_COUNTER_TARGET 9
#define PULSE_COUNT 91
#define BIT_OFFSET_CYCLES 58
#define OVERRIDE_CYCLES 3
#define CONFIRM_COUNTER_TARGET_2 222
#define PULSE_COUNT_2 71
#define BIT_OFFSET_2_CYCLES 54
#define OVERRIDE_2_CYCLES 3
#endif
// #endif
/*------------------------------------------------------------------------------------------------
Region Settings Section
------------------------------------------------------------------------------------------------*/
#if defined(SCPH_100) || defined(SCPH_7500_9000) || defined(SCPH_7000) || \
defined(SCPH_5500) || defined(SCPH_5000) ||defined(SCPH_3500) || defined(SCPH_3000) || \
defined(SCPH_1000) || defined(SCPH_xxx3) || defined(SCPH_5903)
#define INJECT_SCEx 0 // NTSC-J
#endif
#if defined(SCPH_100) || \
defined(SCPH_7500_9000) || \
defined(SCPH_7000) || \
defined(SCPH_5000_5500) || \
defined(SCPH_3500) || \
defined(SCPH_3000) || \
defined(SCPH_1000) || \
defined(SCPH_xxx3) || \
defined(SCPH_5903)
#if defined(SCPH_xxx1)
#define INJECT_SCEx 1 // NTSC-U/C
#endif
#define INJECT_SCEx 0 // NTSC-J
#if defined(SCPH_xxx2) || defined(SCPH_102)
#define INJECT_SCEx 2 // PAL
#endif
#elif defined(SCPH_xxx1)
#define INJECT_SCEx 1 // NTSC-U/C
#elif defined(SCPH_xxx2) || \
defined(SCPH_102)
#define INJECT_SCEx 2 // PAL
#elif defined(SCPH_xxxx)
#define INJECT_SCEx 3 // Universal: NTSC-J -> NTSC-U/C -> PAL
#if defined(SCPH_xxxx)
#define INJECT_SCEx 3 // Universal: NTSC-J -> NTSC-U/C -> PAL
#endif
@@ -335,7 +163,7 @@ void Debug_Log (int Wfck_mode){ //Information about the MCU, and old or
#if defined(ATtiny85_45_25)
mySerial.print("m "); mySerial.println(Wfck_mode);
#elif !defined(ATtiny85_45_25)
#else
Serial.print(" MCU frequency: "); Serial.print(F_CPU); Serial.println(" Hz");
//Serial.print(" lows: "); Serial.println(Lows);
Serial.print(" wfck_mode: "); Serial.println(Wfck_mode);
@@ -380,7 +208,7 @@ void Debug_Inject(){ // Confirmation of region code injection
#if defined(ATtiny85_45_25)
mySerial.print("!");
#elif !defined(ATtiny85_45_25)|| defined(SCPH_102_legacy)
#else
Serial.println(" INJECT ! ");
#endif
}
@@ -391,26 +219,50 @@ void Debug_Inject(){ // Confirmation of region code injection
Compilation message
-----------------------------------------------------------------------------------------------*/
#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_5000) && !defined(SCPH_3500) && !defined(SCPH_3000) && \
!defined(SCPH_1000) && !defined(SCPH_5903) &&\
!defined(SCPH_xxx1) && !defined(SCPH_xxx2) && !defined(SCPH_xxxx)
#if !defined(SCPH_xxx3) && \
!defined(SCPH_102) && \
!defined(SCPH_101) && \
!defined(SCPH_100) && \
!defined(SCPH_7500_9000) && \
!defined(SCPH_7000) && \
!defined(SCPH_5000_5500) && \
!defined(SCPH_3500) && \
!defined(SCPH_3000) && \
!defined(SCPH_1000) && \
!defined(SCPH_5903) && \
!defined(SCPH_xxx1) && \
!defined(SCPH_xxx2) && \
!defined(SCPH_xxxx)
#error "Console not selected! Please uncoment #define with SCPH model number."
#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_5000) ^ defined(SCPH_3500) ^ defined(SCPH_3000) ^ \
defined(SCPH_1000) ^ defined(SCPH_xxxx) ^ defined(SCPH_5903) ^ \
defined(SCPH_xxx1) ^ defined(SCPH_xxx2)
#elif !defined(SCPH_xxx3) ^ \
defined(SCPH_102) ^ \
defined(SCPH_101) ^ \
defined(SCPH_100) ^ \
defined(SCPH_7500_9000) ^ \
defined(SCPH_7000) ^ \
defined(SCPH_5000_5500) ^ \
defined(SCPH_3500) ^ \
defined(SCPH_3000) ^ \
defined(SCPH_1000) ^ \
defined(SCPH_xxxx) ^ \
defined(SCPH_5903) ^ \
defined(SCPH_xxx1) ^ \
defined(SCPH_xxx2)
#error "May be selected only one console! Please check #define with SCPH model number."
#endif
#if !defined(ATmega328_168) && !defined(ATmega32U4_16U4) && !defined(ATtiny85_45_25)
#if !defined(ATmega328_168) && \
!defined(ATmega32U4_16U4) && \
!defined(ATtiny85_45_25)
#error "MCU not selected! Please choose one"
#elif !defined(ATmega328_168) ^ defined(ATmega32U4_16U4 ) ^ defined(ATtiny85_45_25)
#elif !defined(ATmega328_168) ^ \
defined(ATmega32U4_16U4 ) ^ \
defined(ATtiny85_45_25)
#error "May be selected only one MCU"
#endif
#if defined(LED_RUN) && defined(PSNEE_DEBUG_SERIAL_MONITOR) && defined(ATtiny85_45_25)
#if defined(LED_RUN) && \
defined(PSNEE_DEBUG_SERIAL_MONITOR) && \
defined(ATtiny85_45_25)
#error"Compilation options LED_RUN and PSNEE_DEBUG_SERIAL_MONITOR are not simultaneously compatible with ATtiny85_45_25"
#endif