1
0
mirror of https://github.com/kalymos/PsNee.git synced 2026-03-02 01:50:20 +00:00

obtimisation

This commit is contained in:
kalymos
2026-02-28 19:46:25 +01:00
parent 9fcaeb719c
commit 11299a9c34
4 changed files with 706 additions and 139 deletions

View File

@@ -18,6 +18,9 @@
* It counts the exact number of incoming pulses on PIN_AX until it
* matches the PULSE_COUNT value.
*/
//if (--pulse_counter == 0) {
pulse_counter++;
if (pulse_counter == PULSE_COUNT){ // If pulse_counter reaches the value defined by PULSE_COUNT
/*
@@ -69,6 +72,7 @@
*/
_delay_ms(BOOT_OFFSET);
// Armed for hardware detection
//pulse_counter = PULSE_COUNT;
PIN_AX_INTERRUPT_RISING;
PIN_AX_INTERRUPT_ENABLE;
while (patch_done != 1); // Wait for the first stage of the patch to complete:
@@ -172,4 +176,123 @@
#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).
*
* 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.
* ======================================================================================
*/
#ifdef BIOS_PATCH_2
volatile uint8_t pulse_counter = 0;
volatile uint8_t patch_done = 0;
// --- MAIN INTERRUPT SERVICE ROUTINE (ADDRESS AX) ---
ISR(PIN_AX_INTERRUPT_VECTOR) {
/*
* PHASE 3: Pulse Counting (Inside ISR)
* Decrementing towards zero is the fastest operation on AVR architecture.
*/
if (--pulse_counter == 0) {
/* PHASE 4: Precision Bit Alignment */
_delay_us(BIT_OFFSET);
/* PHASE 5: Data Bus Overdrive (The Patch on DX) */
#ifdef INTERRUPT_RISING_HIGH_PATCH
PIN_DX_SET; // Pre-set HIGH state for Variant 3
#endif
PIN_DX_OUTPUT; // Take control of the Data Bus
_delay_us(OVERRIDE);
#ifdef INTERRUPT_RISING_HIGH_PATCH
PIN_DX_CLEAR; // Release HIGH state
#endif
PIN_DX_INPUT; // Immediately release the Data Bus
PIN_AX_INTERRUPT_DISABLE;
patch_done = 1; // Notify Stage 1 completion
}
}
// --- SECONDARY INTERRUPT SERVICE ROUTINE (ADDRESS AY - Variant 3) ---
#ifdef INTERRUPT_RISING_HIGH_PATCH
ISR(PIN_AY_INTERRUPT_VECTOR) {
if (--pulse_counter == 0) {
_delay_us(BIT_OFFSET_2);
PIN_DX_OUTPUT;
_delay_us(OVERRIDE_2);
PIN_DX_INPUT;
PIN_AY_INTERRUPT_DISABLE;
patch_done = 2; // Notify Stage 2 completion
}
}
#endif
void Bios_Patching() {
/*
* PHASE 1: Signal Stabilization & Alignment (AX)
* Handles Cold Boot (Line High) vs Reset (Line Low) states.
*/
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 */
_delay_ms(BOOT_OFFSET);
// Countdown Preparation (Optimized for speed)
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
// Arm Hardware Interrupt
PIN_AX_INTERRUPT_ENABLE;
while (patch_done != 1); // Block until first patch is applied
/*
* OPTIONAL PHASE: Secondary Patch (Variant 3 only)
* Switches detection to the second Address line (AY).
*/
#ifdef INTERRUPT_RISING_HIGH_PATCH
while (PIN_AY_READ != 0); // Ensure AY is low before arming
_delay_ms(FOLLOWUP_OFFSET);
pulse_counter = PULSE_COUNT_2; // Re-load counter for AY pulses
PIN_AY_INTERRUPT_RISING;
PIN_AY_INTERRUPT_ENABLE;
while (patch_done != 2); // Block until second patch is applied
#endif
}
#endif

View File

@@ -250,7 +250,7 @@
}
// Define the clock speed for the microcontroller
#define F_CPU 16000000L
//#define F_CPU 16000000L
#include <stdint.h>
#include <stdbool.h>

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
@@ -21,7 +21,7 @@
-------------------------------------------------------------------------------------------------*/
//#define SCPH_xxxx // | Universal.
//#define SCPH_xxx1 // NTSC U/C | America.
//#define SCPH_xxx2 // PAL | Europ.
#define SCPH_xxx2 // PAL | Europ.
//#define SCPH_xxx3 // NTSC J | Asia.
//#define SCPH_5903 // NTSC J | Asia VCD.
@@ -185,33 +185,108 @@ uint8_t hysteresis = 0;
-----------------------------------------------------------------------*/
void board_detection() {
uint16_t pulses = 0;
uint32_t totalSamples = 600000; // Timeout/Sampling window to limit detection duration
// void board_detection() {
// uint16_t pulses = 0;
// uint32_t totalSamples = 600000; // Timeout/Sampling window to limit detection duration
// Runs until 600,000 cycles pass
while (totalSamples--) {
// If the current pin state is HIGH, wait for it to go LOW
if (PIN_WFCK_READ) {
// Wait for falling edge OR timeout to prevent infinite hang
while (PIN_WFCK_READ && --totalSamples);
// // Runs until 600,000 cycles pass
// while (totalSamples--) {
// // If the current pin state is HIGH, wait for it to go LOW
// if (PIN_WFCK_READ) {
// // Wait for falling edge OR timeout to prevent infinite hang
// while (PIN_WFCK_READ && --totalSamples);
pulses++;
// pulses++;
// High count (> 500) oscillating signal (Newer boards)
if (pulses > 500) {
wfck_mode = 1; // Target: PU-22 or newer
return;
}
// // High count (> 500) oscillating signal (Newer boards)
// if (pulses > 500) {
// wfck_mode = 1; // Target: PU-22 or newer
// return;
// }
// }
// }
// // Low count implies a static signal (Older boards)
// wfck_mode = 0; // Target: PU-7 to PU-20
// #if defined(PSNEE_DEBUG_SERIAL_MONITOR)
// Debug_Log(wfck_mode);
// #endif
// }
// void board_detection() {
// // Universal 16-bit timeout (covers ~100ms at 16MHz)
// uint16_t timeout = 60000;
// uint8_t pulses = 200;
// while (--timeout) {
// // 1. Wait for RISING edge (Signal goes HIGH)
// if (PIN_WFCK_READ) {
// // 2. Wait for FALLING edge (Signal goes LOW)
// while (PIN_WFCK_READ && --timeout);
// // If we find 500 falling edges, it's a newer board (WFCK)
// if (--pulses == 0) {
// wfck_mode = 1; // PU-22+
// return;
// }
// }
// }
// // Timeout reached or static signal (Gate)
// wfck_mode = 0; // PU-7 to PU-20
// }
// void board_detection() {
// uint16_t timeout = 60000;
// uint8_t pulses = 100;
// // 1. SYNC PHASE: Bypasses the initial "Blank" state (High or Low)
// uint8_t start_state = PIN_WFCK_READ;
// while (PIN_WFCK_READ == start_state && --timeout);
// // 2. DETECTION PHASE: Counts 100 Falling Edges
// while (--timeout) {
// if (PIN_WFCK_READ) {
// // Wait for falling edge
// while (PIN_WFCK_READ && --timeout);
// if (--pulses == 0) {
// wfck_mode = 1; // Oscillating WFCK (PU-22+)
// return;
// }
// }
// }
// wfck_mode = 0; // Static Signal or Timeout (PU-7 to PU-20)
// }
void board_detection() {
uint16_t timeout = 60000;
uint8_t pulses = 100;
uint8_t mode = 0;
// 1. SYNC PHASE: Wait for the first transition to align with the signal
uint8_t start_state = PIN_WFCK_READ;
while (PIN_WFCK_READ == start_state && --timeout);
// 2. DETECTION PHASE: Count edges with minimal logic inside the loop
while (timeout > 0) {
// Wait for WFCK to go HIGH
while (!PIN_WFCK_READ && --timeout);
if (timeout == 0) break;
// Wait for WFCK to go LOW (Falling Edge)
while (PIN_WFCK_READ && --timeout);
if (timeout == 0) break;
// Count pulses
if (--pulses == 0) {
mode = 1; // Oscillating signal detected
break;
}
}
}
// Low count implies a static signal (Older boards)
wfck_mode = 0; // Target: PU-7 to PU-20
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Log(wfck_mode);
#endif
wfck_mode = mode;
}
@@ -221,32 +296,63 @@ void board_detection() {
// Uses clock-edge synchronization and includes a safety timeout for malformatted streams.
//******************************************************************************************************************
void captureSubQ(void) {
uint8_t scpos = 0;
//uint8_t bitbuf = 0;
do {
uint8_t bitbuf = 0;
// Process 8 bits for each of the 12 bytes
for (uint8_t i = 0; i < 8; i++) {
// Wait for Clock to go LOW then HIGH (Sampling on Rising Edge)
// Wait for SQCK Clock: sampling occurs on the Rising Edge
while (PIN_SQCK_READ); // Wait for LOW
while (! PIN_SQCK_READ); // Wait for HIGH
while (!PIN_SQCK_READ); // Wait for HIGH
// Shift buffer and sample the SUBQ pin
// Shift and sample SUBQ data pin
bitbuf >>= 1;
if (PIN_SUBQ_READ) {
bitbuf |= 0x80;
}
}
// Direct index storage for smaller binary size
scbuf[scpos++] = bitbuf;
} while (scpos < 12);
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Scbuf(scbuf);
#endif
}
// void captureSubQ(void) {
// uint8_t scpos = 12; // Start with total count for decrement-to-zero optimization
// uint8_t* ptr = scbuf;
// do {
// uint8_t bitbuf = 0;
// uint8_t i = 8;
// while (i--) {
// // PHASE 1: Wait for Clock (SQCK) to go LOW then HIGH (Sampling on Rising Edge)
// while (PIN_SQCK_READ); // Wait for LOW
// while (!PIN_SQCK_READ); // Wait for HIGH
// // PHASE 2: Shift buffer and sample the SUBQ pin
// // Optimized bit rotation
// bitbuf >>= 1;
// if (PIN_SUBQ_READ) {
// bitbuf |= 0x80;
// }
// }
// // Store byte and move pointer
// *ptr++ = bitbuf;
// } while (--scpos); // Decrement-to-zero is faster than (scpos < 12)
// #if defined(PSNEE_DEBUG_SERIAL_MONITOR)
// Debug_Scbuf(scbuf);
// #endif
// }
/**************************************************************************************
* Processes sector data for the SCPH-5903 (Dual-interface PS1) to differentiate
* between PlayStation games and Video CDs (VCD).
@@ -260,31 +366,62 @@ void captureSubQ(void) {
**************************************************************************************/
void logic_SCPH_5903(uint8_t isDataSector) {
// Optimization: Pre-check common markers (1 and 6) to save CPU cycles
if (scbuf[1] == 0x00 && scbuf[6] == 0x00) {
// void logic_SCPH_5903(uint8_t isDataSector) {
// // Optimization: Pre-check common markers (1 and 6) to save CPU cycles
// if (scbuf[1] == 0x00 && scbuf[6] == 0x00) {
// Identify Lead-In patterns (0xA0, 0xA1, 0xA2)
if (isDataSector && (scbuf[2] >= 0xA0 && scbuf[2] <= 0xA2)) {
// Identify PSX Lead-In: same patterns but sub-mode is NOT 0x02
if (scbuf[3] != 0x02) {
hysteresis++;
return;
}
// If it is 0x02, it's a VCD Lead-In: we fall through to the final else if
}
// Maintain/Increase confidence for valid non-VCD sectors (0x01 or Data)
else if (hysteresis > 0 && (scbuf[0] == 0x01 || isDataSector)) {
hysteresis++;
// // Identify Lead-In patterns (0xA0, 0xA1, 0xA2)
// if (isDataSector && (scbuf[2] >= 0xA0 && scbuf[2] <= 0xA2)) {
// // Identify PSX Lead-In: same patterns but sub-mode is NOT 0x02
// if (scbuf[3] != 0x02) {
// hysteresis++;
// return;
// }
// // If it is 0x02, it's a VCD Lead-In: we fall through to the final else if
// }
// // Maintain/Increase confidence for valid non-VCD sectors (0x01 or Data)
// else if (hysteresis > 0 && (scbuf[0] == 0x01 || isDataSector)) {
// hysteresis++;
// return;
// }
// }
// // Patterns stop matching or VCD Lead-In detected: decrease confidence
// if (hysteresis > 0) {
// hysteresis--;
// }
// }
void logic_SCPH_5903(uint8_t isDataSector) {
uint8_t h = hysteresis;
// Fast check: most sectors will fail here (sync markers 1 and 6)
if (scbuf[1] == 0x00 && scbuf[6] == 0x00) {
uint8_t s2 = scbuf[2];
// Combine all "Success" conditions for a single increment path:
// 1. Valid PSX Lead-In: isDataSector AND (A0-A2 range) AND NOT VCD (sub-mode 0x02)
// 2. OR General valid sector: (Mode 0x01 or Data) while already tracking (h > 0)
if ( (isDataSector && (uint8_t)(s2 - 0xA0) <= 2 && scbuf[3] != 0x02) ||
(h > 0 && (scbuf[0] == 0x01 || isDataSector)) )
{
hysteresis = h + 1;
return;
}
}
// Patterns stop matching or VCD Lead-In detected: decrease confidence
if (hysteresis > 0) {
hysteresis--;
// Default: no match found or VCD Lead-In detected, decrease confidence
if (h > 0) {
hysteresis = h - 1;
}
}
/******************************************************************************************
* Heuristic logic for standard PlayStation hardware (Non-VCD models).
*
@@ -298,31 +435,75 @@ void logic_SCPH_5903(uint8_t isDataSector) {
******************************************************************************************/
void logic_Standard(uint8_t isDataSector) {
// Optimization: Check common markers once (scbuf[1] and scbuf[6])
if (scbuf[1] == 0x00 && scbuf[6] == 0x00) {
// void logic_Standard(uint8_t isDataSector) {
// // Optimization: Check common markers once (scbuf[1] and scbuf[6])
// if (scbuf[1] == 0x00 && scbuf[6] == 0x00) {
// Detect specific Lead-In patterns (A0, A1, A2 or 01 with specific time ranges)
if (isDataSector && (scbuf[2] >= 0xA0 ||
(scbuf[2] == 0x01 && (scbuf[3] >= 0x98 || scbuf[3] <= 0x02)))) {
hysteresis++;
return; // Pattern found, exit early
}
// // Detect specific Lead-In patterns (A0, A1, A2 or 01 with specific time ranges)
// if (isDataSector && (scbuf[2] >= 0xA0 ||
// (scbuf[2] == 0x01 && (scbuf[3] >= 0x98 || scbuf[3] <= 0x02)))) {
// hysteresis++;
// return; // Pattern found, exit early
// }
// Maintain confidence if general valid sector markers are found
if (hysteresis > 0 && (scbuf[0] == 0x01 || isDataSector)) {
hysteresis++;
// // Maintain confidence if general valid sector markers are found
// if (hysteresis > 0 && (scbuf[0] == 0x01 || isDataSector)) {
// hysteresis++;
// return;
// }
// }
// // No valid pattern found: decrease confidence
// if (hysteresis > 0) {
// hysteresis--;
// }
// }
// void logic_Standard(uint8_t isDataSector) {
// uint8_t h = hysteresis;
// // Combine scbuf check and Lead-In detection into a single path
// if (scbuf == 0 && scbuf == 0) {
// uint8_t s2 = scbuf;
// // Logical OR for all "Increment" conditions
// if ( (isDataSector && (s2 >= 0xA0 || (s2 == 0x01 && (scbuf >= 0x98 || scbuf <= 0x02)))) ||
// (h > 0 && (scbuf == 0x01 || isDataSector)) )
// {
// hysteresis = h + 1;
// return;
// }
// }
// // Single point for decrement
// if (h > 0) hysteresis = h - 1;
// }
void logic_Standard(uint8_t isDataSector) {
uint8_t h = hysteresis;
// Fast reject: most sectors fail here
if (scbuf[1] == 0x00 && scbuf[6] == 0x00) {
uint8_t s2 = scbuf[2];
// Single unified condition for "Increment"
// 1. Lead-In: isDataSector AND (s2>=A0 OR (s2==01 AND (s3>=98 OR s3<=02)))
// 2. Standard: (h>0) AND (s0==01 OR isDataSector)
if ( (isDataSector && (s2 >= 0xA0 || (s2 == 0x01 && ( (uint8_t)(scbuf[3] - 0x03) >= 0xF5)))) ||
(h > 0 && (scbuf[0] == 0x01 || isDataSector)) )
{
hysteresis = h + 1;
return;
}
}
// No valid pattern found: decrease confidence
if (hysteresis > 0) {
hysteresis--;
}
// Default: decrement
if (h > 0) hysteresis = h - 1;
}
/*********************************************************************************************
* Executes the SCEx signal injection sequence to bypass regional lockout.
*
@@ -333,96 +514,358 @@ void logic_Standard(uint8_t isDataSector) {
* injectSCEx 0:NTSC-J SCEI, 1:NTSC-U/C SCEA, 2:PAL SCEE, 3:Universal (Cycles through all).
*********************************************************************************************/
void performInjectionSequence(uint8_t injectSCEx) {
// 44-bit SCEx strings for Japan Asia, USA, and Europe
static const uint8_t allRegionsSCEx[3][6] = {
{ 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11011010, 0b00000010 }, // SCEI
{ 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11111010, 0b00000010 }, // SCEA
{ 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11101010, 0b00000010 } // SCEE
};
// void performInjectionSequence(uint8_t injectSCEx) {
// // 44-bit SCEx strings for Japan Asia, USA, and Europe
// static const uint8_t allRegionsSCEx[3][6] = {
// { 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11011010, 0b00000010 }, // SCEI
// { 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11111010, 0b00000010 }, // SCEA
// { 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11101010, 0b00000010 } // SCEE
// };
hysteresis = 11;
#ifdef LED_RUN
PIN_LED_ON;
#endif
// hysteresis = 11;
// #ifdef LED_RUN
// PIN_LED_ON;
// #endif
// Pin initialization
PIN_DATA_OUTPUT;
PIN_DATA_CLEAR;
// // Pin initialization
// PIN_DATA_OUTPUT;
// PIN_DATA_CLEAR;
if (!wfck_mode) {
PIN_WFCK_OUTPUT; PIN_WFCK_CLEAR;
}
// if (!wfck_mode) {
// PIN_WFCK_OUTPUT; PIN_WFCK_CLEAR;
// }
_delay_ms(DELAY_BETWEEN_INJECTIONS);
// _delay_ms(DELAY_BETWEEN_INJECTIONS);
// Injection loop (3 cycles)
for (uint8_t i = 0; i < 3; i++) {
// // Injection loop (3 cycles)
// for (uint8_t i = 0; i < 3; i++) {
// Mode 3: cycles through all regions; Others: stay on fixed region
uint8_t regionIndex = (injectSCEx == 3) ? i : injectSCEx;
const uint8_t* ByteSet = allRegionsSCEx[regionIndex];
// // Mode 3: cycles through all regions; Others: stay on fixed region
// uint8_t regionIndex = (injectSCEx == 3) ? i : injectSCEx;
// const uint8_t* ByteSet = allRegionsSCEx[regionIndex];
// Process 6 bytes to reach 44 bits
for (uint8_t b = 0; b < 6; b++) {
uint8_t currentByte = ByteSet[b];
// // Process 6 bytes to reach 44 bits
// for (uint8_t b = 0; b < 6; b++) {
// uint8_t currentByte = ByteSet[b];
for (uint8_t bit = 0; bit < 8; bit++) {
// Stop exactly at 44 bits (6th byte, 4th bit)
if (b == 5 && bit == 4) break;
// for (uint8_t bit = 0; bit < 8; bit++) {
// // Stop exactly at 44 bits (6th byte, 4th bit)
// if (b == 5 && bit == 4) break;
// Bit-level extraction: isolate the target bit and prepare next
uint8_t currentBit = currentByte & 0x01;
currentByte >>= 1;
// // Bit-level extraction: isolate the target bit and prepare next
// uint8_t currentBit = currentByte & 0x01;
// currentByte >>= 1;
if (!wfck_mode) {
// LOGIC GATE MODE (Old boards)
if (currentBit == 0) {
PIN_DATA_OUTPUT; PIN_DATA_CLEAR;
}
else {
PIN_DATA_INPUT; // High Impedance = 1
}
_delay_us(DELAY_BETWEEN_BITS);
}
else {
// WFCK MODULATION (Newer boards / PU-18+)
if (currentBit == 0) {
PIN_DATA_CLEAR;
_delay_us(DELAY_BETWEEN_BITS);
} else {
// Synchronize injection with WFCK clock edges
uint8_t count = 30;
while (count--) {
while (PIN_WFCK_READ); // Wait for LOW
PIN_DATA_CLEAR;
while (!PIN_WFCK_READ); // Wait for HIGH
PIN_DATA_SET;
}
}
}
}
}
// Inter-string silence
// if (!wfck_mode) {
// // LOGIC GATE MODE (Old boards)
// if (currentBit == 0) {
// PIN_DATA_OUTPUT; PIN_DATA_CLEAR;
// }
// else {
// PIN_DATA_INPUT; // High Impedance = 1
// }
// _delay_us(DELAY_BETWEEN_BITS);
// }
// else {
// // WFCK MODULATION (Newer boards / PU-18+)
// if (currentBit == 0) {
// PIN_DATA_CLEAR;
// _delay_us(DELAY_BETWEEN_BITS);
// } else {
// // Synchronize injection with WFCK clock edges
// uint8_t count = 30;
// while (count--) {
// while (PIN_WFCK_READ); // Wait for LOW
// PIN_DATA_CLEAR;
// while (!PIN_WFCK_READ); // Wait for HIGH
// PIN_DATA_SET;
// }
// }
// }
// }
// }
// // Inter-string silence
// PIN_DATA_OUTPUT;
// PIN_DATA_CLEAR;
// _delay_ms(DELAY_BETWEEN_INJECTIONS);
// }
// // Cleanup: Set pins to High-Z (Safe mode)
// if (!wfck_mode) {
// PIN_WFCK_INPUT;
// PIN_DATA_INPUT;
// }
// #ifdef LED_RUN
// PIN_LED_OFF;
// #endif
// #if defined(PSNEE_DEBUG_SERIAL_MONITOR)
// Debug_Inject();
// #endif
// }
// void performInjectionSequence(uint8_t injectSCEx) {
// // 44-bit SCEx patterns (6 bytes: 5 full + 4 bits)
// 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;
// #ifdef LED_RUN
// PIN_LED_ON;
// #endif
// // --- HARDWARE INITIALIZATION ---
// PIN_DATA_OUTPUT;
// PIN_DATA_CLEAR;
// if (!wfck_mode) {
// PIN_WFCK_OUTPUT;
// PIN_WFCK_CLEAR;
// }
// _delay_ms(DELAY_BETWEEN_INJECTIONS);
// // --- MAIN INJECTION LOOP (3 BURSTS) ---
// for (uint8_t i = 0; i < 3; i++) {
// // Select region pattern: Cycle through all if injectSCEx == 3
// uint8_t regionIndex = (injectSCEx == 3) ? i : injectSCEx;
// const uint8_t* bytePtr = allRegionsSCEx[regionIndex];
// // Branching here instead of inside the loops for assembly optimization
// if (!wfck_mode) {
// // --- LOGIC GATE MODE (PU-7 to PU-20) ---
// for (uint8_t b = 0; b < 6; b++) {
// uint8_t currentByte = bytePtr[b];
// uint8_t bitsToProcess = (b == 5) ? 4 : 8;
// while (bitsToProcess--) {
// if (currentByte & 0x01) {
// PIN_DATA_INPUT; // Logic '1' via High-Impedance
// } else {
// PIN_DATA_OUTPUT; // Logic '0' via Active Drive
// PIN_DATA_CLEAR;
// }
// currentByte >>= 1;
// _delay_us(DELAY_BETWEEN_BITS);
// }
// }
// }
// else {
// // --- WFCK MODULATION MODE (PU-22+) ---
// for (uint8_t b = 0; b < 6; b++) {
// uint8_t currentByte = bytePtr[b];
// uint8_t bitsToProcess = (b == 5) ? 4 : 8;
// while (bitsToProcess--) {
// if (currentByte & 0x01) {
// // Modulate '1' bit using WFCK clock edges (30 cycles)
// uint8_t count = 30;
// while (count--) {
// while (PIN_WFCK_READ); // Wait for LOW
// PIN_DATA_CLEAR;
// while (!PIN_WFCK_READ); // Wait for HIGH
// PIN_DATA_SET;
// }
// } else {
// // Static '0' bit
// PIN_DATA_CLEAR;
// _delay_us(DELAY_BETWEEN_BITS);
// }
// currentByte >>= 1;
// }
// }
// }
// // --- INTER-STRING GAP ---
// PIN_DATA_OUTPUT;
// PIN_DATA_CLEAR;
// _delay_ms(DELAY_BETWEEN_INJECTIONS);
// }
// // --- CLEANUP ---
// if (!wfck_mode) {
// PIN_WFCK_INPUT;
// PIN_DATA_INPUT;
// }
// #ifdef LED_RUN
// PIN_LED_OFF;
// #endif
// }
// void performInjectionSequence(uint8_t injectSCEx) {
// // 44-bit SCEx patterns (6 bytes: 5 full + 4 bits)
// 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;
// #ifdef LED_RUN
// PIN_LED_ON;
// #endif
// // --- HARDWARE INITIALIZATION ---
// PIN_DATA_OUTPUT;
// PIN_DATA_CLEAR;
// if (!wfck_mode) {
// PIN_WFCK_OUTPUT;
// PIN_WFCK_CLEAR;
// }
// _delay_ms(DELAY_BETWEEN_INJECTIONS);
// // --- MAIN INJECTION LOOP (3 BURSTS) ---
// for (uint8_t i = 0; i < 3; i++) {
// // Select region pattern: Cycle through all if injectSCEx == 3
// uint8_t regionIndex = (injectSCEx == 3) ? i : injectSCEx;
// const uint8_t* bytePtr = allRegionsSCEx[regionIndex];
// for (uint8_t b = 0; b < 6; b++) {
// uint8_t currentByte = bytePtr[b];
// // On the 6th byte, only process 4 bits (Total 44 bits)
// uint8_t bits = (b == 5) ? 4 : 8;
// while (bits--) {
// uint8_t currentBit = currentByte & 0x01;
// currentByte >>= 1;
// if (currentBit == 0) {
// // --- LOGIC FOR '0' BIT (Universal) ---
// PIN_DATA_CLEAR;
// if (!wfck_mode) PIN_DATA_OUTPUT;
// _delay_us(DELAY_BETWEEN_BITS);
// }
// else {
// // --- LOGIC FOR '1' BIT ---
// if (!wfck_mode) {
// // OLD BOARDS: High Impedance
// PIN_DATA_INPUT;
// _delay_us(DELAY_BETWEEN_BITS);
// }
// else {
// // NEW BOARDS: WFCK Modulation (30 cycles)
// uint8_t count = 30;
// while (count--) {
// while (PIN_WFCK_READ); // Wait for LOW
// PIN_DATA_CLEAR;
// while (!PIN_WFCK_READ); // Wait for HIGH
// PIN_DATA_SET;
// }
// }
// }
// }
// }
// // --- INTER-STRING GAP ---
// PIN_DATA_OUTPUT;
// PIN_DATA_CLEAR;
// _delay_ms(DELAY_BETWEEN_INJECTIONS);
// }
// // --- CLEANUP ---
// if (!wfck_mode) {
// PIN_WFCK_INPUT;
// PIN_DATA_INPUT;
// }
// #ifdef LED_RUN
// PIN_LED_OFF;
// #endif
// }
void performInjectionSequence(uint8_t injectSCEx) {
static const uint8_t allRegionsSCEx[3][6] = {
{ 0x59, 0xC9, 0x4B, 0x5D, 0xDA, 0x02 },
{ 0x59, 0xC9, 0x4B, 0x5D, 0xFA, 0x02 },
{ 0x59, 0xC9, 0x4B, 0x5D, 0xEA, 0x02 }
};
hysteresis = 11;
#ifdef LED_RUN
PIN_LED_ON;
#endif
uint8_t isWfck = wfck_mode;
PIN_DATA_OUTPUT;
PIN_DATA_CLEAR;
_delay_ms(DELAY_BETWEEN_INJECTIONS);
}
// Cleanup: Set pins to High-Z (Safe mode)
if (!wfck_mode) {
PIN_WFCK_INPUT;
PIN_DATA_INPUT;
}
#ifdef LED_RUN
PIN_LED_OFF;
#endif
if (!isWfck) {
PIN_WFCK_OUTPUT;
PIN_WFCK_CLEAR;
}
_delay_ms(DELAY_BETWEEN_INJECTIONS);
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;
// OPTIMIZATION: One single loop for all 44 bits
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) {
PIN_DATA_CLEAR;
if (!isWfck) PIN_DATA_OUTPUT;
_delay_us(DELAY_BETWEEN_BITS);
} else {
if (!isWfck) {
PIN_DATA_INPUT;
_delay_us(DELAY_BETWEEN_BITS);
} else {
uint8_t count = 30;
while (count--) {
while (PIN_WFCK_READ);
PIN_DATA_CLEAR;
while (!PIN_WFCK_READ);
PIN_DATA_SET;
}
}
}
}
PIN_DATA_OUTPUT;
PIN_DATA_CLEAR;
_delay_ms(DELAY_BETWEEN_INJECTIONS);
}
if (!isWfck) {
PIN_WFCK_INPUT;
PIN_DATA_INPUT;
}
#ifdef LED_RUN
PIN_LED_OFF;
#endif
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Inject();
#endif
}
void Init() {
#if defined(ATmega328_168)
@@ -433,7 +876,7 @@ void Init() {
PIN_LED_OUTPUT;
#endif
#ifdef BIOS_PATCH
#ifdef BIOS_PATCH_2
uint8_t Flag_Switch = 0;
GLOBAL_INTERRUPT_ENABLE;
#ifdef SCPH_7000

View File

@@ -24,11 +24,12 @@
// tested with an Atmega328P
#ifdef SCPH_102
#define BIOS_PATCH
#define BIOS_PATCH_2
#define INTERRUPT_RISING
#define BOOT_OFFSET 83.9
#define PULSE_COUNT 48
#define BIT_OFFSET 2.75
//#define BIT_OFFSET 2.75
#define BIT_OFFSET 3.25 //BIOS_PATCH_2
#define OVERRIDE 0.2
#endif