mirror of
https://github.com/kalymos/PsNee.git
synced 2026-05-08 16:32:17 +00:00
Refactor: Clean up SCPH and MCU pragma messages
This commit is contained in:
@@ -1,262 +1,337 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* ======================================================================================
|
||||
* FUNCTION : Bios_Patching()
|
||||
* TARGET : Data Bus (DX) synchronized via Address Bus (AX / AY)
|
||||
*
|
||||
* OPERATIONAL LOGIC:
|
||||
* Intercepts specific memory transactions by monitoring address lines (AX/AY).
|
||||
* Uses hardware interrupts (ISR) for high-speed pulse counting and cycle-accurate
|
||||
* delays to inject modified data onto the Data line (DX) in real-time.
|
||||
*
|
||||
* KEY PHASES:
|
||||
* 1. STABILIZATION & ALIGNMENT (AX): Synchronizes execution with a clean rising
|
||||
* edge of the AX signal to establish a deterministic timing reference.
|
||||
*
|
||||
* 2. ADDRESS CALL DETECTION (PHASE 2): Scans the bus for specific address calls
|
||||
* by validating consecutive polling blocks (SILENCE_THRESHOLD).
|
||||
*
|
||||
* 3. SILENCE CONFIRMATION (GATING): Counts the exact number of validated silence
|
||||
* windows (CONFIRM_COUNTER_TARGET) to reach the correct pre-patching stage.
|
||||
*
|
||||
* 4. HARDWARE PULSE COUNTING (ISR): Uses INT0/INT1 to decrement the 'impulse'
|
||||
* counter on each rising edge with minimal hardware latency.
|
||||
*
|
||||
* 5. DATA OVERDRIVE (DX): Upon reaching the target pulse, triggers a calibrated
|
||||
* delay (BIT_OFFSET) and momentarily forces the DX pin to OUTPUT mode to
|
||||
* overwrite the BIOS bit for a precise duration (OVERRIDE).
|
||||
* ======================================================================================
|
||||
*/
|
||||
|
||||
#ifdef BIOS_PATCH
|
||||
uint8_t current_pulses = 0;
|
||||
volatile uint8_t pulse_counter = 0;
|
||||
volatile uint8_t patch_done = 0;
|
||||
|
||||
#ifdef TEST_BIOS
|
||||
/**
|
||||
* Shared state variables between ISRs and the main patching loop.
|
||||
* Declared 'volatile' to prevent compiler optimization during busy-wait loops.
|
||||
*/
|
||||
volatile uint8_t impulse = 0; // Down-counter for physical address pulses
|
||||
volatile uint8_t patch = 0; // Synchronization flag (0: Idle, 1: AX Done, 2: AY Done)
|
||||
|
||||
void Bios_Patching() {
|
||||
PIN_DX_INPUT;
|
||||
//PIN_DX_LOW;
|
||||
/**
|
||||
* PHASE 3: Primary Interrupt Service Routine (AX)
|
||||
* Triggered on rising edges to perform the real-time bus override.
|
||||
*/
|
||||
ISR(PIN_AX_INTERRUPT_VECTOR) {
|
||||
if (--impulse == 0) {
|
||||
// Precise bit-alignment delay within the memory cycle
|
||||
__builtin_avr_delay_cycles(BIT_OFFSET_CYCLES);
|
||||
|
||||
|
||||
cli(); // Disable interrupts for timing integrity
|
||||
|
||||
/*
|
||||
* PHASE 1: Signal Stabilization & Alignment
|
||||
* Synchronizes the MCU with the PS1 startup state (Cold Boot vs Reset).
|
||||
*/
|
||||
if (PIN_AX_READ != 0) { // Case: Power-on / Line high (---__-_-_)
|
||||
while (PIN_AX_READ != 0); // Wait for falling edge
|
||||
while (PIN_AX_READ == 0); // Sync on first clean rising edge
|
||||
} else { // Case: Reset / Line low (_____-_-_)
|
||||
while (PIN_AX_READ == 0); // Wait for rising edge
|
||||
#ifdef PHASE_TWO_PATCH
|
||||
PIN_DX_SET; // Pre-drive high if required by specific logic
|
||||
#endif
|
||||
|
||||
// DATA OVERDRIVE: Pull the DX bus to the custom state
|
||||
PIN_DX_OUTPUT;
|
||||
__builtin_avr_delay_cycles(OVERRIDE_CYCLES);
|
||||
|
||||
#ifdef PHASE_TWO_PATCH
|
||||
PIN_DX_CLEAR;
|
||||
#endif
|
||||
|
||||
// BUS RELEASE: Return DX to High-Z (Input) mode
|
||||
PIN_DX_INPUT;
|
||||
|
||||
PIN_AX_INTERRUPT_DISABLE; // Stop tracking AX pulses
|
||||
PIN_LED_OFF;
|
||||
patch = 1; // Signal Phase 3 completion
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PHASE 2: Address Bus Window Alignment
|
||||
* Bypassing initial boot routines to reach one window with a
|
||||
* known "idle gap" in the address bus activity, positioned
|
||||
* immediately before the target memory-access cycle.
|
||||
* BOOT_OFFSET: |----//----------|
|
||||
* AX: ___-_-_//-_-_-________________-_-_
|
||||
*/
|
||||
_delay_ms(BOOT_OFFSET);
|
||||
PIN_LED_ON;
|
||||
#ifdef PHASE_TWO_PATCH
|
||||
/**
|
||||
* PHASE 5: Secondary Interrupt Service Routine (AY)
|
||||
* Handles the second injection stage if multi-patching is active.
|
||||
*/
|
||||
ISR(PIN_AY_INTERRUPT_VECTOR) {
|
||||
if (--impulse == 0) {
|
||||
__builtin_avr_delay_cycles(BIT_OFFSET_2_CYCLES);
|
||||
|
||||
/*
|
||||
* PHASE 3: Edge Trigger
|
||||
* Capture the moment AX go HIGH.
|
||||
* Edge Triger: |
|
||||
* AX: _-_-_-_-_-________________-_-_-_-_-_-__
|
||||
*/
|
||||
#ifdef LOW_TRIGGER
|
||||
while (PIN_AX_READ);
|
||||
#else
|
||||
while (! PIN_AX_READ);
|
||||
PIN_DX_OUTPUT;
|
||||
__builtin_avr_delay_cycles(OVERRIDE_2_CYCLES);
|
||||
PIN_DX_INPUT;
|
||||
|
||||
PIN_AY_INTERRUPT_DISABLE;
|
||||
PIN_LED_OFF;
|
||||
patch = 2; // Signal Phase 5 completion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Bios_Patching(void) {
|
||||
|
||||
// --- HARDWARE BYPASS OPTION (SCPH-7000 specific) ---
|
||||
#if defined(SCPH_7000)
|
||||
PIN_SWITCH_INPUT; // Configure Pin D5 as Input
|
||||
PIN_SWITCH_SET; // Enable internal Pull-up (D5 defaults to HIGH)
|
||||
__builtin_avr_delay_cycles(10); // Short delay for voltage stabilization
|
||||
|
||||
/**
|
||||
* Exit immediately if the switch pulls the pin to GND (Logic LOW).
|
||||
* This allows the user to disable the BIOS patch on-the-fly.
|
||||
*/
|
||||
if (PIN_SWITCH_READ == 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PHASE 4: Precision Bit Alignment
|
||||
* Delay to shift from AX address edge to the DX data bit.
|
||||
* BIT_OFFSET: |-------//-----|
|
||||
* AX: _-_-_-_-_-________________-_-_-_-_//_-_-_-_
|
||||
*/
|
||||
_delay_us(BIT_OFFSET);
|
||||
uint8_t current_confirms = 0;
|
||||
//uint16_t count;
|
||||
|
||||
/*
|
||||
* 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; // Force line (Low/High-Z override)
|
||||
_delay_us(OVERRIDE);
|
||||
PIN_DX_INPUT; // Release bus immediately
|
||||
PIN_LED_OFF;
|
||||
sei(); // Restore global interrupts
|
||||
patch = 0; // Reset sync flag
|
||||
sei(); // Enable Global Interrupts
|
||||
PIN_AX_INPUT; // Set AX to monitor mode
|
||||
|
||||
|
||||
patch_done = 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HIGH_PATCH_A
|
||||
|
||||
|
||||
ISR(PIN_AY_INTERRUPT_VECTOR){
|
||||
|
||||
pulse_counter++;
|
||||
if (pulse_counter == PULSE_COUNT_2)
|
||||
{
|
||||
_delay_us (BIT_OFFSET_2);
|
||||
PIN_DX_OUTPUT;
|
||||
_delay_us (OVERRIDE_2);
|
||||
PIN_DX_INPUT;
|
||||
PIN_AY_INTERRUPT_DISABLE;
|
||||
|
||||
patch_done = 2;
|
||||
}
|
||||
// --- PHASE 1: STABILIZATION & ALIGNMENT ---
|
||||
// Align execution pointer to a known rising edge state.
|
||||
if (PIN_AX_READ != 0) {
|
||||
while (WAIT_AX_FALLING); // Wait if bus is busy
|
||||
while (WAIT_AX_RISING); // Sync with next pulse start
|
||||
} else {
|
||||
while (WAIT_AX_RISING); // Sync with upcoming pulse
|
||||
}
|
||||
|
||||
void Bios_Patching(){
|
||||
PIN_DX_INPUT;
|
||||
cli(); // Disable interrupts for timing integrity
|
||||
|
||||
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_LED_ON;
|
||||
while (! PIN_AX_READ);
|
||||
_delay_us(BIT_OFFSET);
|
||||
PIN_DX_SET;
|
||||
PIN_DX_OUTPUT; // Force line (Low/High-Z override)
|
||||
_delay_us(OVERRIDE);
|
||||
PIN_DX_CLEAR;
|
||||
PIN_DX_INPUT; // Release bus immediately
|
||||
PIN_LED_OFF;
|
||||
sei(); // Restore global interrupts
|
||||
|
||||
|
||||
|
||||
PIN_LED_OFF;
|
||||
|
||||
|
||||
_delay_ms(FOLLOWUP_OFFSET);
|
||||
|
||||
PIN_AY_INTERRUPT_RISING;
|
||||
PIN_AY_INTERRUPT_ENABLE;
|
||||
while (patch_done != 2);
|
||||
// --- PHASE 2: SILENCE DETECTION ---
|
||||
// Validate the exact number of silence windows to identify the boot stage.
|
||||
while (current_confirms < CONFIRM_COUNTER_TARGET) {
|
||||
uint16_t count = SILENCE_THRESHOLD;
|
||||
while (count > 0) {
|
||||
if (PIN_AX_READ != 0) {
|
||||
while (WAIT_AX_FALLING);
|
||||
break; // Impulse detected: retry current silence block
|
||||
}
|
||||
#ifdef IS_32U4_FAMILY
|
||||
__asm__ __volatile__ ("nop");
|
||||
#endif
|
||||
|
||||
count--;
|
||||
}
|
||||
if (count == 0) {
|
||||
current_confirms++; // Validated one silence window
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
// --- PHASE 3: LAUNCH HARDWARE COUNTING (AX) ---
|
||||
impulse = PULSE_COUNT;
|
||||
PIN_LED_ON;
|
||||
PIN_AX_INTERRUPT_CLEAR;
|
||||
PIN_AX_INTERRUPT_RISING; // Setup rising-edge trigger
|
||||
PIN_AX_INTERRUPT_ENABLE; // Engage ISR
|
||||
|
||||
#ifdef HIGH_PATCH_B
|
||||
while (patch != 1);
|
||||
|
||||
|
||||
// --- PHASE 4 & 5: SECONDARY PATCHING SEQUENCE ---
|
||||
#ifdef PHASE_TWO_PATCH
|
||||
PIN_AY_INPUT;
|
||||
current_confirms = 0;
|
||||
impulse = PULSE_COUNT_2;
|
||||
// Monitor for the specific silent gap before the second patch window
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef IS_32U4_FAMILY
|
||||
__asm__ __volatile__ ("nop");
|
||||
#endif
|
||||
|
||||
void Bios_Patching(){
|
||||
PIN_DX_INPUT;
|
||||
cli(); // Disable interrupts for timing integrity
|
||||
|
||||
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_LED_ON;
|
||||
while (! PIN_AX_READ);
|
||||
_delay_us(BIT_OFFSET);
|
||||
PIN_DX_SET;
|
||||
PIN_DX_OUTPUT; // Force line (Low/High-Z override)
|
||||
_delay_us(OVERRIDE);
|
||||
PIN_DX_CLEAR;
|
||||
PIN_DX_INPUT; // Release bus immediately
|
||||
PIN_LED_OFF;
|
||||
sei(); // Restore global interrupts
|
||||
|
||||
|
||||
|
||||
//PIN_LED_OFF;
|
||||
PIN_LED_ON;
|
||||
while (PIN_AY_READ != 0);
|
||||
_delay_ms(FOLLOWUP_OFFSET);
|
||||
|
||||
while (PIN_AY_READ);
|
||||
_delay_us (BIT_OFFSET_2);
|
||||
PIN_DX_OUTPUT;
|
||||
_delay_us (OVERRIDE_2);
|
||||
PIN_DX_INPUT;
|
||||
PIN_LED_OFF;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
|
||||
ISR(PIN_AX_INTERRUPT_VECTOR) {
|
||||
pulse_counter++;
|
||||
if (pulse_counter == 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;
|
||||
|
||||
pulse_counter = 0;
|
||||
patch_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ISR(PIN_AY_INTERRUPT_VECTOR){
|
||||
|
||||
pulse_counter++;
|
||||
if (pulse_counter == PULSE_COUNT_2)
|
||||
{
|
||||
_delay_us (BIT_OFFSET_2);
|
||||
PIN_DX_OUTPUT;
|
||||
_delay_us (OVERRIDE_2);
|
||||
PIN_DX_INPUT;
|
||||
PIN_AY_INTERRUPT_DISABLE;
|
||||
|
||||
patch_done = 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 (patch_done != 1);
|
||||
|
||||
while (PIN_AY_READ != 0);
|
||||
|
||||
|
||||
_delay_ms(FOLLOWUP_OFFSET);
|
||||
PIN_LED_ON;
|
||||
PIN_AY_INTERRUPT_RISING;
|
||||
PIN_AY_INTERRUPT_ENABLE;
|
||||
|
||||
while (patch_done != 2);
|
||||
PIN_LED_OFF;
|
||||
}
|
||||
|
||||
#endif
|
||||
count--;
|
||||
}
|
||||
if (count == 0) {
|
||||
current_confirms++;
|
||||
}
|
||||
}
|
||||
|
||||
PIN_LED_ON;
|
||||
PIN_AY_INTERRUPT_CLEAR;
|
||||
PIN_AY_INTERRUPT_FALLING;
|
||||
PIN_AY_INTERRUPT_ENABLE;
|
||||
|
||||
while (patch != 2); // Busy-wait for secondary ISR completion
|
||||
|
||||
|
||||
return;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Portability Note: The non-ISR (polling-based) version of the code is maintained
|
||||
* to facilitate porting to other platforms and architectures that may not support
|
||||
* AVR-specific hardware interrupts.
|
||||
*
|
||||
* Stability Limitation: While the polling version is more portable, it was found
|
||||
* that at 16MHz, achieving consistent DATA OVERDRIVE stability is nearly impossible
|
||||
* without using a Hardware ISR. The latency and jitter of software polling at this
|
||||
* frequency are too high to guarantee a sub-microsecond cycle-accurate injection.
|
||||
* Therefore, for ATmega328P @ 16MHz, the ISR-driven implementation remains the
|
||||
* tandard.
|
||||
*/
|
||||
|
||||
// #ifdef BIOS_PATCH
|
||||
|
||||
// volatile uint8_t impulse = 0;
|
||||
// volatile uint8_t patch = 0;
|
||||
|
||||
|
||||
// ISR(PIN_AX_INTERRUPT_VECTOR) {
|
||||
// //impulse--;
|
||||
// if (--impulse == 0){ // If impulse reaches the value defined by TRIGGER, the following actions are performed:
|
||||
// // Precise cycle-accurate delay before triggering
|
||||
// __builtin_avr_delay_cycles(BIT_OFFSET_CYCLES);
|
||||
|
||||
// #ifdef PHASE_TWO_PATCH
|
||||
// PIN_DX_SET;
|
||||
// #endif
|
||||
|
||||
// PIN_DX_OUTPUT; // Pull the line (Override start)
|
||||
// __builtin_avr_delay_cycles(OVERRIDE_CYCLES);
|
||||
|
||||
// #ifdef PHASE_TWO_PATCH
|
||||
// PIN_DX_CLEAR; // Release the bus (Override end)
|
||||
// #endif
|
||||
|
||||
// PIN_DX_INPUT;
|
||||
|
||||
// PIN_LED_OFF;
|
||||
// PIN_AX_INTERRUPT_DISABLE;
|
||||
// patch = 1; // patch is set to 1, indicating that the first patch is completed.
|
||||
// }
|
||||
// }
|
||||
|
||||
// #ifdef PHASE_TWO_PATCH
|
||||
|
||||
|
||||
// ISR(PIN_AY_INTERRUPT_VECTOR){
|
||||
|
||||
// //impulse--;
|
||||
// if (--impulse == 0) // If impulse reaches the value defined by TRIGGER2, the following actions are performed:
|
||||
// {
|
||||
// __builtin_avr_delay_cycles(BIT_OFFSET_2_CYCLES);
|
||||
|
||||
// PIN_DX_OUTPUT;
|
||||
// __builtin_avr_delay_cycles(OVERRIDE_2_CYCLES);
|
||||
// PIN_DX_INPUT;
|
||||
|
||||
// PIN_AY_INTERRUPT_DISABLE;
|
||||
// PIN_LED_OFF;
|
||||
// patch = 2; // patch is set to 2, indicating that the second patch is completed.
|
||||
// }
|
||||
// }
|
||||
// #endif
|
||||
|
||||
// // --- BIOS Patching Main Function ---
|
||||
// void Bios_Patching(void) {
|
||||
|
||||
// uint8_t current_confirms = 0;
|
||||
// uint8_t count = 0;
|
||||
// patch = 0;
|
||||
// sei();
|
||||
// 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
|
||||
// }
|
||||
|
||||
// // --- PHASE 2: Silence Detection (AX) ---
|
||||
|
||||
// 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++;
|
||||
// }
|
||||
// }
|
||||
// impulse = PULSE_COUNT;
|
||||
// PIN_LED_ON;
|
||||
// PIN_AX_INTERRUPT_RISING;
|
||||
// PIN_AX_INTERRUPT_ENABLE;
|
||||
// while (patch != 1); // Wait for the first stage of the patch to complete:
|
||||
|
||||
// //PIN_LED_OFF;
|
||||
// // -------- Secondary Patch ----------
|
||||
// #ifdef PHASE_TWO_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++;
|
||||
// }
|
||||
// }
|
||||
|
||||
// PIN_LED_ON;
|
||||
// impulse = PULSE_COUNT_2;
|
||||
// PIN_AY_INTERRUPT_RISING;
|
||||
// PIN_AY_INTERRUPT_ENABLE;
|
||||
|
||||
// while (patch != 2); // Wait for the second stage of the patch to complete:
|
||||
|
||||
// #endif
|
||||
|
||||
// cli();
|
||||
// }
|
||||
// #endif
|
||||
|
||||
|
||||
|
||||
399
PSNee/MCU.h
399
PSNee/MCU.h
@@ -93,14 +93,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328A__) || \
|
||||
defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PA__) || \
|
||||
defined(__AVR_ATmega328PB__) || defined(__AVR_ATmega168__) || \
|
||||
defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168P__) || \
|
||||
defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || \
|
||||
defined(__AVR_ATmega128A__) || defined(__AVR_ATmega128PB__)
|
||||
|
||||
#define IS_328_168_FAMILY
|
||||
/*------------------------------------------------------------------------------------------------
|
||||
* FUNCTION : optimizePeripherals()
|
||||
*
|
||||
@@ -113,59 +113,15 @@
|
||||
* 3. CLOCK GATING (PRR): Shuts down clocks to TWI, SPI, and all Timers (0, 1, 2).
|
||||
* 4. UART MAINTENANCE: Keeps PRUSART0 active to allow Serial communication.
|
||||
------------------------------------------------------------------------------------------------*/
|
||||
#define IS_328_168_FAMILY
|
||||
|
||||
static inline void OptimizePeripherals(void) {
|
||||
// 1. Disable Interrupts during setup
|
||||
cli();
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
#ifdef ATmega328_168
|
||||
// 2. Analog Modules Shutdown (Critical for Power)
|
||||
ADCSRA &= ~(1 << ADEN); // Disable ADC
|
||||
ACSR |= (1 << ACD); // Disable Analog Comparator
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
static inline void optimizePeripherals(void) {
|
||||
// Configuring Port C (A0-A5) as Digital Inputs
|
||||
// DDRC at 0 = Input. Ensure that the first 6 bits are 0.
|
||||
DDRC &= ~0x3F;
|
||||
|
||||
// Disable the ADC (Analog-to-Digital Converter)
|
||||
// ADEN at 0 disables the module. PRADC at 1 disables the module's clock.
|
||||
ADCSRA &= ~(1 << ADEN);
|
||||
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)
|
||||
DIDR0 &= ~0x3F;
|
||||
|
||||
// Stop Timer 0 (Stops Arduino millis/micros)
|
||||
// Setting TCCR0B to 0 stops the clock source. Setting TIMSK0 to 0 disables interrupts.
|
||||
TCCR0B = 0;
|
||||
//#define F TIMSK0 = 0;
|
||||
|
||||
// Disable the Analog Comparator (Frees up resources on PD6/PD7)
|
||||
// ACD at 1 = Comparator off.
|
||||
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
|
||||
|
||||
// Set OCR0A to achieve a 100KHz clock frequency
|
||||
//#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
|
||||
//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
|
||||
=======
|
||||
// 3. Digital Input Disable (Set bits to 1 to DISABLE)
|
||||
// Disconnects digital buffers on analog pins to stop leakage
|
||||
DIDR0 = 0xFF; // Pins A0 to A7
|
||||
#if defined(__AVR_ATmega128PB__)
|
||||
DIDR2 = 0xFF;
|
||||
@@ -228,8 +184,6 @@ static inline void optimizePeripherals(void) {
|
||||
TCCR4B = 0; TIMSK4 = 0; // Timer 4 (série PB)
|
||||
#endif
|
||||
|
||||
}
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@@ -238,15 +192,10 @@ static inline void optimizePeripherals(void) {
|
||||
#include <avr/sfr_defs.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
// 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
|
||||
#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
|
||||
|
||||
// Main pin configuration for input and output
|
||||
// Main pin configuration
|
||||
|
||||
// Define the main pins as inputs
|
||||
#define PIN_DATA_INPUT DDRB &= ~(1 << DDB0) // Set DDRB register to configure PINB0 as input
|
||||
@@ -254,82 +203,78 @@ static inline void optimizePeripherals(void) {
|
||||
#define PIN_SQCK_INPUT DDRD &= ~(1 << DDD6) // Set DDRB register to configure PINB6 as input
|
||||
#define PIN_SUBQ_INPUT DDRD &= ~(1 << DDD7) // Set DDRB register to configure PINB7 as input
|
||||
|
||||
// Enable pull-ups and set high on the main pins
|
||||
// Configure lines as outputs (for injection/override)
|
||||
#define PIN_DATA_OUTPUT DDRB |= (1 << DDB0) // Set DDRB register to configure PINB0 as output
|
||||
#define PIN_WFCK_OUTPUT DDRB |= (1 << DDB1) // Set DDRB register to configure PINB1 as output
|
||||
|
||||
// Define pull-ups and set high at the main pin
|
||||
#define PIN_DATA_SET PORTB |= (1 << PB0) // Set PORTB register to make PINB0 high (enable pull-up)
|
||||
|
||||
// Clear the main pins (set low)
|
||||
// Bus line state control (Set High / Clear Low)
|
||||
#define PIN_DATA_SET PORTB |= (1 << PB0) // Set PORTB register to make PINB0 high (enable pull-up))
|
||||
#define PIN_DATA_CLEAR PORTB &= ~(1 << PB0) // Set PORTB register to make PINB0 low
|
||||
#define PIN_WFCK_CLEAR PORTB &= ~(1 << PB1) // Set PORTB register to make PINB1 low
|
||||
|
||||
// Read the state of the main input pins
|
||||
#define PIN_SQCK_READ (PIND & (1 << PIND6)) // Check if the value of PIND6 is high (1)
|
||||
#define PIN_SUBQ_READ (PIND & (1 << PIND7)) // Check if the value of PIND7 is high (1)
|
||||
#define PIN_WFCK_READ (PINB & (1 << PINB1)) // Check if the value of PIND1 is high (1)
|
||||
// Direct Register Reading (High-speed polling)
|
||||
#define PIN_SQCK_READ (!!(PIND & (1 << PIND6))) // Check if the value of PIND6 is high (1)
|
||||
#define PIN_SUBQ_READ (!!(PIND & (1 << PIND7))) // Check if the value of PIND7 is high (1)
|
||||
#define PIN_WFCK_READ (!!(PINB & (1 << PINB1))) // Check if the value of PIND1 is high (1)
|
||||
|
||||
// LED pin handling (for indication)
|
||||
// --- Status Indication (LED) ---
|
||||
#ifdef LED_RUN
|
||||
#define PIN_LED_OUTPUT DDRB |= (1 << DDB5) // Configure PINB5 as output (for LED)
|
||||
#define PIN_LED_ON PORTB |= (1 << PB5) // Set PINB5 high (turn on LED)
|
||||
#define PIN_LED_OFF PORTB &= ~(1 << PB5) // Set PINB5 low (turn off LED)
|
||||
#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)
|
||||
// --- BIOS Patching Configuration ---
|
||||
#if defined(SCPH_102) || \
|
||||
defined(SCPH_100) || \
|
||||
defined(SCPH_7500_9000) || \
|
||||
defined(SCPH_7000) || \
|
||||
defined(SCPH_3500_5500) || \
|
||||
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
|
||||
// Address (AX) and Data (DX) lines for BIOS override
|
||||
#define PIN_DX_INPUT DDRD &= ~(1 << DDD4)
|
||||
#define PIN_DX_OUTPUT DDRD |= (1 << DDD4)
|
||||
#define PIN_DX_SET PORTD |= (1 << PD4)
|
||||
#define PIN_DX_CLEAR PORTD &= ~(1 << PD4)
|
||||
|
||||
// Define input pins for the BIOS patch
|
||||
#define PIN_AX_INPUT DDRD &= ~(1 << DDD2) // Set DDRD register to configure PIND2 as input
|
||||
#define PIN_DX_INPUT DDRD &= ~(1 << DDD4) // Set DDRD register to configure PIND4 as input
|
||||
#define PIN_AX_INPUT DDRD &= ~(1 << DDD2)
|
||||
#define WAIT_AX_RISING (!(PIND & (1 << PIND2))) // Wait for pulse start (Blocking until Rising Edge)
|
||||
#define WAIT_AX_FALLING (PIND & (1 << PIND2)) // Wait for pulse end (Blocking until Falling Edge)
|
||||
#define PIN_AX_READ (!!(PIND & (1 << PIND2)))
|
||||
|
||||
// Define output pins for the BIOS patch
|
||||
#define PIN_DX_OUTPUT DDRD |= (1 << DDD4) // Set DDRD register to configure PIND4 as output
|
||||
// Hardware Interrupt (INT0) for AX pulse counting
|
||||
#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_VECTOR INT0_vect // Interrupt vector for INT0 (external interrupt)
|
||||
#define PIN_AX_INTERRUPT_CLEAR EIFR |= (1 << INTF0)
|
||||
|
||||
// Set pull-ups high on output pins
|
||||
#define PIN_DX_SET PORTD |= (1 << PD4) // Set PORTD register to make PIND4 high
|
||||
|
||||
// Set pull-ups low on output pins
|
||||
#define PIN_DX_CLEAR PORTD &= ~(1 << PD4) // Set PORTD register to make PIND4 low
|
||||
|
||||
// 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 = (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)
|
||||
// Secondary Address line (AY) for multi-stage patching (INT1)
|
||||
#if defined(SCPH_3000) || \
|
||||
defined(SCPH_1000)
|
||||
#define PIN_AY_INPUT DDRD &= ~(1 << DDD3) // Set DDRD register to configure PIND3 as input
|
||||
#define WAIT_AY_RISING (!(PIND & (1 << PIND3)))
|
||||
#define WAIT_AY_FALLING (PIND & (1 << 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 << ISC11) | (1 << ISC10))) | (1 << ISC11) // Configure INT1 for falling edge trigger
|
||||
#define PIN_AY_INTERRUPT_VECTOR INT1_vect // Interrupt vector for INT1 (external interrupt)
|
||||
#define PIN_AY_INTERRUPT_CLEAR EIFR |= (1 << INTF1)
|
||||
#endif
|
||||
// Handle switch input for BIOS patch
|
||||
#if defined(SCPH_7000)
|
||||
#define PIN_SWITCH_INPUT DDRD &= ~(1 << DDD5) // Configure PIND5 as input for switch
|
||||
#define PIN_SWITCH_SET PORTD |= (1 << PD5) // Set PIND5 high (enable pull-up)
|
||||
#define PIN_SWITCH_READ (PIND & (1 << PIND5)) // Read the state of PIND5 (switch input)
|
||||
#endif
|
||||
|
||||
// Hardware Bypass Switch (On-the-fly deactivation)
|
||||
#if defined(SCPH_7000)
|
||||
#define PIN_SWITCH_INPUT DDRD &= ~(1 << DDD5) // Configure PIND5 as input for switch
|
||||
#define PIN_SWITCH_SET PORTD |= (1 << PD5) // Set PIND5 high (enable pull-up)
|
||||
#define PIN_SWITCH_READ (!!(PIND & (1 << PIND5))) // Read the state of PIND5 (switch input)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// #if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
// #define DEBUG_PRINT(x) Serial.print(x)
|
||||
// #define DEBUG_PRINTHEX(x) Serial.print(x, HEX)
|
||||
@@ -343,14 +288,6 @@ static inline void optimizePeripherals(void) {
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
|
||||
#define IS_32U4_FAMILY
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
#define F_CPU 16000000L
|
||||
// #define TIMER_TCNT_CLEAR TCNT0 = 0x00;
|
||||
// #define SET_OCROA_DIV OCR0A = 159;
|
||||
// #define SET_TIMER_TCCROA TCCR0A |= (1 << WGM01);
|
||||
// #define SET_TIMER_TCCROB TCCR0B |= (1 << CS00);
|
||||
// #define CTC_TIMER_VECTOR TIMER0_COMPA_vect
|
||||
=======
|
||||
static inline void OptimizePeripherals(void) {
|
||||
// 1. Global Interrupt Disable during hardware reconfiguration
|
||||
cli();
|
||||
@@ -394,7 +331,6 @@ static inline void optimizePeripherals(void) {
|
||||
TCCR4B = 0;
|
||||
}
|
||||
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@@ -403,103 +339,99 @@ static inline void optimizePeripherals(void) {
|
||||
#include <avr/sfr_defs.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
// Globale interrupt seting
|
||||
// #define GLOBAL_INTERRUPT_ENABLE SREG |= (1 << 7)
|
||||
#define GLOBAL_INTERRUPT_DISABLE SREG &= ~(1 << 7)
|
||||
|
||||
// #define TIMER_INTERRUPT_ENABLE TIMSK0 |= (1 << OCIE0A)
|
||||
// #define TIMER_INTERRUPT_DISABLE TIMSK0 &= ~(1 << OCIE0A)
|
||||
|
||||
// Handling the main pins
|
||||
// --- Main Bus Interface (CD-ROM Controller) ---
|
||||
|
||||
// Main pins
|
||||
#define PIN_DATA_INPUT DDRB &= ~(1 << DDB4)
|
||||
#define PIN_WFCK_INPUT DDRB &= ~(1 << DDB5)
|
||||
#define PIN_SQCK_INPUT DDRD &= ~(1 << DDD7)
|
||||
#define PIN_SUBQ_INPUT DDRE &= ~(1 << DDE6)
|
||||
// Define the main pins as inputs
|
||||
#define PIN_DATA_INPUT DDRB &= ~(1 << DDB4) // DATA line (PB4)
|
||||
#define PIN_WFCK_INPUT DDRB &= ~(1 << DDB5) // WFCK / GATE line (PB5)
|
||||
#define PIN_SQCK_INPUT DDRD &= ~(1 << DDD7) // SQCK Clock (PD7)
|
||||
#define PIN_SUBQ_INPUT DDRE &= ~(1 << DDE6) // SUBQ Data (PE6)
|
||||
|
||||
// Configure lines as outputs (for injection/override)
|
||||
#define PIN_DATA_OUTPUT DDRB |= (1 << DDB4)
|
||||
#define PIN_WFCK_OUTPUT DDRB |= (1 << DDB5)
|
||||
|
||||
// Define pull-ups and set high at the main pin
|
||||
#define PIN_DATA_SET PORTB |= (1 << PB4)
|
||||
// Define pull-ups set down at the main pin
|
||||
#define PIN_DATA_CLEAR PORTB &= ~(1 << PB4)
|
||||
#define PIN_WFCK_CLEAR PORTB &= ~(1 << PB5)
|
||||
// Read the main pins
|
||||
#define PIN_SQCK_READ (PIND & (1 << PIND7))
|
||||
#define PIN_SUBQ_READ (PINE & (1 << PINE6))
|
||||
#define PIN_WFCK_READ (PINB & (1 << PINB5))
|
||||
// Bus line state control (Set High / Clear Low)
|
||||
#define PIN_DATA_SET PORTB |= (1 << PB4) // Enable pull-up or drive HIGH
|
||||
#define PIN_DATA_CLEAR PORTB &= ~(1 << PB4) // Drive line LOW
|
||||
#define PIN_WFCK_CLEAR PORTB &= ~(1 << PB5) // Drive line LOW
|
||||
|
||||
// Handling and use of the LED pin
|
||||
// Direct Register Reading (High-speed polling)
|
||||
#define PIN_SQCK_READ (!!(PIND & (1 << PIND7)))
|
||||
#define PIN_SUBQ_READ (!!(PINE & (1 << PINE6)))
|
||||
#define PIN_WFCK_READ (!!(PINB & (1 << PINB5)))
|
||||
|
||||
// --- Status Indication (LED) ---
|
||||
#ifdef LED_RUN
|
||||
#define PIN_LED_OUTPUT DDRB |= (1 << DDB6)
|
||||
#define PIN_LED_ON PORTB |= (1 << PB6)
|
||||
#define PIN_LED_OFF PORTB &= ~(1 << PB6)
|
||||
#define PIN_LED_OUTPUT DDRB |= (1 << DDB6) // LED on PB6
|
||||
#define PIN_LED_ON PORTB |= (1 << PB6)
|
||||
#define PIN_LED_OFF PORTB &= ~(1 << PB6)
|
||||
#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)
|
||||
// Pins input
|
||||
#define PIN_AX_INPUT DDRD &= ~(1 << DDD1)
|
||||
#define PIN_AY_INPUT DDRD &= ~(1 << DDD0)
|
||||
#define PIN_DX_INPUT DDRD &= ~(1 << DDD4)
|
||||
// Pin output
|
||||
#define PIN_DX_OUTPUT DDRD |= (1 << DDD4)
|
||||
// Define pull-ups set high
|
||||
#define PIN_DX_SET PORTD |= (1 << PD4)
|
||||
// Define pull-ups set down
|
||||
#define PIN_DX_CLEAR PORTD &= ~(1 << PD4)
|
||||
// Read pins for BIOS patch
|
||||
#define PIN_AX_READ (PIND & (1 << PIND1))
|
||||
#define PIN_AY_READ (PIND & (1 << PIND0))
|
||||
// Handling and reading the switch pin for patch BIOS
|
||||
#ifdef PATCH_SWITCH
|
||||
#define PIN_SWITCH_INPUT DDRC &= ~(1 << DDC6)
|
||||
#define PIN_SWITCH_SET PORTC |= (1 << PC6)
|
||||
#define PIN_SWITCH_READ (PINC & (1 << PINC6))
|
||||
// --- BIOS Patching Configuration (32U4 Mapping) ---
|
||||
|
||||
#if defined(SCPH_102) || \
|
||||
defined(SCPH_100) || \
|
||||
defined(SCPH_7500_9000) || \
|
||||
defined(SCPH_7000) || \
|
||||
defined(SCPH_3500_5500) || \
|
||||
defined(SCPH_3000) || \
|
||||
defined(SCPH_1000)
|
||||
|
||||
// Address (AX) and Data (DX) lines for BIOS override
|
||||
|
||||
#define PIN_DX_INPUT DDRD &= ~(1 << DDD4) // DX on PD4
|
||||
#define PIN_DX_OUTPUT DDRD |= (1 << DDD4)
|
||||
#define PIN_DX_SET PORTD |= (1 << PD4)
|
||||
#define PIN_DX_CLEAR PORTD &= ~(1 << PD4)
|
||||
|
||||
#define PIN_AX_INPUT DDRD &= ~(1 << DDD1) // AX on PD1 (INT1)
|
||||
#define WAIT_AX_RISING (!(PIND & (1 << PIND1))) // Wait for pulse start
|
||||
#define WAIT_AX_FALLING (PIND & (1 << PIND1)) // Wait for pulse end
|
||||
#define PIN_AX_READ (PIND & (1 << PIND1))
|
||||
|
||||
// Hardware Interrupt (INT1) for AX pulse counting
|
||||
#define PIN_AX_INTERRUPT_ENABLE EIMSK |= (1 << INT1)
|
||||
#define PIN_AX_INTERRUPT_DISABLE EIMSK &= ~(1 << INT1)
|
||||
#define PIN_AX_INTERRUPT_RISING EICRA |= (1 << ISC11) | (1 << ISC10)
|
||||
#define PIN_AX_INTERRUPT_VECTOR INT1_vect
|
||||
#define PIN_AX_INTERRUPT_CLEAR EIFR |= (1 << INTF1)
|
||||
|
||||
// Secondary Address line (AY) for multi-stage patching (INT0)
|
||||
#if defined(SCPH_3000) || defined(SCPH_1000)
|
||||
|
||||
#define PIN_AY_INPUT DDRD &= ~(1 << DDD0) // AY on PD0 (INT0)
|
||||
#define PIN_AY_READ (PIND & (1 << PIND0))
|
||||
#define WAIT_AY_RISING (!(PIND & (1 << PIND0)))
|
||||
#define WAIT_AY_FALLING (PIND & (1 << PIND0))
|
||||
|
||||
#define PIN_AY_INTERRUPT_ENABLE EIMSK |= (1 << INT0)
|
||||
#define PIN_AY_INTERRUPT_DISABLE EIMSK &= ~(1 << INT0)
|
||||
#define PIN_AY_INTERRUPT_RISING EICRA |= (1 << ISC01) | (1 << ISC00)
|
||||
#define PIN_AY_INTERRUPT_VECTOR INT0_vect
|
||||
#define PIN_AY_INTERRUPT_CLEAR EIFR |= (1 << INTF0)
|
||||
#endif
|
||||
|
||||
// BIOS timer clear
|
||||
#define TIMER_TIFR_CLEAR TIFR0 |= (1 << OCF0A)
|
||||
|
||||
// Handling the external interrupt
|
||||
#define PIN_AX_INTERRUPT_ENABLE EIMSK |= (1 << INT1)
|
||||
#define PIN_AY_INTERRUPT_ENABLE EIMSK |= (1 << INT0)
|
||||
|
||||
#define PIN_AX_INTERRUPT_DISABLE EIMSK &= ~(1 << INT1)
|
||||
#define PIN_AY_INTERRUPT_DISABLE EIMSK &= ~(1 << INT0)
|
||||
|
||||
#define PIN_AX_INTERRUPT_RISING EICRA |= (1 << ISC11) | (1 << ISC10)
|
||||
#define PIN_AY_INTERRUPT_RISING EICRA |= (1 << ISC01) | (1 << ISC00)
|
||||
|
||||
#define PIN_AX_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC10)) | (1 << ISC11))
|
||||
#define PIN_AY_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC00)) | (1 << ISC01))
|
||||
|
||||
#define PIN_AX_INTERRUPT_VECTOR INT1_vect
|
||||
#define PIN_AY_INTERRUPT_VECTOR INT0_vect
|
||||
|
||||
// Hardware Bypass Switch (On-the-fly deactivation)
|
||||
#ifdef SCPH_7000
|
||||
#define PIN_SWITCH_INPUT DDRC &= ~(1 << DDC6) // Bypass on PC6
|
||||
#define PIN_SWITCH_SET PORTC |= (1 << PC6) // Enable pull-up
|
||||
#define PIN_SWITCH_READ (!!(PINC & (1 << PINC6)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
#ifdef ATtiny85_45_25
|
||||
=======
|
||||
|
||||
|
||||
#if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny25__)
|
||||
#define IS_ATTINY_FAMILY
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
#define DF_CPU 8000000L
|
||||
#define TIMER_TCNT_CLEAR TCNT0 = 0x00;
|
||||
#define SET_OCROA_DIV OCR0A = 79; //OCR0A – Output Compare Register A,100KHz
|
||||
#define SET_TIMER_TCCROA TCCR0A |= (1 << WGM01);
|
||||
#define SET_TIMER_TCCROB TCCR0B |= (1 << CS00);
|
||||
#define CTC_TIMER_VECTOR TIMER0_COMPA_vect
|
||||
static inline void OptimizePeripherals(void) {
|
||||
// 1. Global Interrupt Disable during reconfiguration
|
||||
cli();
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
// 2. Analog Modules Shutdown
|
||||
ADCSRA = 0; // Power off ADC completely
|
||||
ACSR |= (1 << ACD); // Disable Analog Comparator
|
||||
@@ -527,7 +459,7 @@ static inline void optimizePeripherals(void) {
|
||||
WDTCR = 0x00;
|
||||
|
||||
}
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -537,58 +469,55 @@ static inline void optimizePeripherals(void) {
|
||||
#include <avr/sfr_defs.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
// Globale interrupt seting
|
||||
#define GLOBAL_INTERRUPT_ENABLE SREG |= (1 << 7)
|
||||
#define GLOBAL_INTERRUPT_DISABLE SREG &= ~(1 << 7)
|
||||
// --- Main Bus Interface (CD-ROM Controller) ---
|
||||
|
||||
// Handling the main pins
|
||||
// Define the main pins as inputs
|
||||
#define PIN_DATA_INPUT DDRB &= ~(1 << DDB2) // DATA line (PB2)
|
||||
#define PIN_WFCK_INPUT DDRB &= ~(1 << DDB4) // WFCK / GATE line (PB4)
|
||||
#define PIN_SQCK_INPUT DDRB &= ~(1 << DDB0) // SQCK Clock (PB0)
|
||||
#define PIN_SUBQ_INPUT DDRB &= ~(1 << DDB1) // SUBQ Data (PB1)
|
||||
|
||||
// Main pins input
|
||||
#define PIN_DATA_INPUT DDRB &= ~(1 << DDB2)
|
||||
#define PIN_WFCK_INPUT DDRB &= ~(1 << DDB4)
|
||||
#define PIN_SQCK_INPUT DDRB &= ~(1 << DDB0)
|
||||
#define PIN_SUBQ_INPUT DDRB &= ~(1 << DDB1)
|
||||
|
||||
// Main pin output
|
||||
// Configure lines as outputs (for injection/override)
|
||||
#define PIN_DATA_OUTPUT DDRB |= (1 << DDB2)
|
||||
#define PIN_WFCK_OUTPUT DDRB |= (1 << DDB4)
|
||||
|
||||
// Define pull-ups and set high at the main pin
|
||||
#define PIN_DATA_SET PORTB |= (1 << PB2)
|
||||
// Bus line state control (Set High / Clear Low)
|
||||
#define PIN_DATA_SET PORTB |= (1 << PB2) // Enable pull-up or drive HIGH
|
||||
#define PIN_DATA_CLEAR PORTB &= ~(1 << PB2) // Drive line LOW
|
||||
#define PIN_WFCK_CLEAR PORTB &= ~(1 << PB4) // Drive line LOW
|
||||
|
||||
// Define pull-ups set down at the main pin
|
||||
#define PIN_DATA_CLEAR PORTB &= ~(1 << PB2)
|
||||
#define PIN_WFCK_CLEAR PORTB &= ~(1 << PB4)
|
||||
// Direct Register Reading (High-speed polling)
|
||||
#define PIN_SQCK_READ (PINB & (1 << PINB0))
|
||||
#define PIN_SUBQ_READ (PINB & (1 << PINB1))
|
||||
#define PIN_WFCK_READ (PINB & (1 << PINB4))
|
||||
|
||||
// Read the main pins
|
||||
#define PIN_SQCK_READ (PINB & (1 << PINB0))
|
||||
#define PIN_SUBQ_READ (PINB & (1 << PINB1))
|
||||
#define PIN_WFCK_READ (PINB & (1 << PINB4))
|
||||
|
||||
#define TIMER_INTERRUPT_ENABLE TIMSK |= (1 << OCIE0A)
|
||||
#define TIMER_INTERRUPT_DISABLE TIMSK &= ~(1 << OCIE0A)
|
||||
|
||||
// Handling and use of the LED pin
|
||||
// --- Status Indication (LED) ---
|
||||
#ifdef LED_RUN
|
||||
#define PIN_LED_OUTPUT DDRB |= (1 << DDB3)
|
||||
#define PIN_LED_ON PORTB |= (1 << PB3)
|
||||
#define PIN_LED_OFF PORTB &= ~(1 << PB3)
|
||||
#endif
|
||||
|
||||
#if defined(SCPH_1000) || defined(SCPH_3000) || defined(SCPH_3500_5000) || defined(SCPH_5500) || defined(SCPH_7000_9000) || defined(SCPH_100) || defined(SCPH_102_legacy) || defined(SCPH_102)
|
||||
#error "ATtiny85_45_25 Not compatible with BIOS patch"
|
||||
#define PIN_LED_OUTPUT DDRB |= (1 << DDB3) // LED on PB3
|
||||
#define PIN_LED_ON PORTB |= (1 << PB3)
|
||||
#define PIN_LED_OFF PORTB &= ~(1 << PB3)
|
||||
#endif
|
||||
|
||||
// --- Debug Serial (Software Serial) ---
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial mySerial(-1, 3); // RX, TX. (RX -1 = off)
|
||||
// SoftwareSerial(RX, TX): RX set to -1 (disabled), TX on PB3
|
||||
// Note: Resource conflict if LED_RUN is also on PB3
|
||||
SoftwareSerial mySerial(-1, 3);
|
||||
#define PIN_TXD_OUTPUT DDRB |= (1 << DDB3)
|
||||
// #define DEBUG_PRINT(x) mySerial.print(x)
|
||||
// #define DEBUG_PRINTHEX(x) mySerial.print(x, HEX)
|
||||
// #define DEBUG_PRINTLN(x) mySerial.println(x)
|
||||
// #define DEBUG_FLUSH mySerial.flush()
|
||||
#endif
|
||||
|
||||
// --- Safety Check: BIOS Patch Compatibility ---
|
||||
#if defined(SCPH_1000) || \
|
||||
defined(SCPH_3000) || \
|
||||
defined(SCPH_3500_5000) || \
|
||||
defined(SCPH_5500) || \
|
||||
defined(SCPH_7000) || \
|
||||
defined(SCPH_7500_9000) || \
|
||||
defined(SCPH_100) || \
|
||||
defined(SCPH_102)
|
||||
#error "ATtiny85/45/25 architecture is not compatible with the BIOS patch feature."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// *****************************************************************************************************************
|
||||
|
||||
756
PSNee/PSNee.ino
756
PSNee/PSNee.ino
@@ -1,19 +1,6 @@
|
||||
// PSNee-8.7
|
||||
// PSNee-V9.0
|
||||
|
||||
/*------------------------------------------------------------------------------------------------
|
||||
<<<<<<< Updated upstream
|
||||
MCU selection
|
||||
------------------------------------------------------------------------------------------------*/
|
||||
|
||||
// MCU // Arduino
|
||||
//------------------------------------------------------------------------------------------------
|
||||
#define ATmega328_168 // Nano, Pro Mini, Uno
|
||||
//#define ATmega32U4_16U4 // Micro, Pro Micro
|
||||
//#define ATtiny85_45_25 // ATtiny
|
||||
|
||||
/*------------------------------------------------------------------------------------------------
|
||||
=======
|
||||
>>>>>>> Stashed changes
|
||||
Console selection
|
||||
--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -22,12 +9,8 @@
|
||||
|
||||
SCPH model number // region code | region
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
<<<<<<< Updated upstream
|
||||
//#define SCPH_xxx1 // NTSC U/C | America.
|
||||
=======
|
||||
//#define SCPH_xxxx // | Universal.
|
||||
|
||||
#define SCPH_xxx1 // NTSC U/C | America.
|
||||
>>>>>>> Stashed changes
|
||||
//#define SCPH_xxx2 // PAL | Europ.
|
||||
//#define SCPH_xxx3 // NTSC J | Asia.
|
||||
//#define SCPH_xxxx // Universal
|
||||
@@ -56,9 +39,7 @@ 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_3500_5500 // DX - D0 | AX - A16 | AX - A15 | 3.0j - CRC FF3EEB8C, 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
|
||||
//#define SCPH_1000 // DX - D5 | AX - A7, AY - A8 | AX - A6, AY - A7 | 1.0j - CRC 3B601FC8
|
||||
|
||||
@@ -81,9 +62,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
/*------------------------------------------------------------------------------------------------
|
||||
Hysteresis
|
||||
------------------------------------------------------------------------------------------------*/
|
||||
#define HYSTERESIS_MAX 15 // All model.
|
||||
//#define HYSTERESIS_MAX 25 // Only FAT! For models with problematic CD players.
|
||||
// Determines the number of times the data in the DATA line must match the filter of the region code injection function to trigger the injection.
|
||||
#define HYSTERESIS_MAX 25 // Coupled with hysteresis-reset post-injection; allows for a
|
||||
// wider tuning range without drifting out of the sweet spot
|
||||
// between hysteresis_max and hysteresis_reset.
|
||||
|
||||
/*------------------------------------------------------------------------------------------------
|
||||
Summary of practical information. Fuses. Pinout
|
||||
@@ -136,28 +117,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
//Flag initializing for automatic console generation selection 0 = old, 1 = pu-22 end ++
|
||||
uint8_t wfck_mode = 0;
|
||||
|
||||
|
||||
// --- Prototypes (Forward declarations) ---
|
||||
// These tell the compiler that the functions exist later in the code.
|
||||
void logic_Standard(uint8_t isDataSector);
|
||||
void logic_SCPH_5903(uint8_t isDataSector);
|
||||
|
||||
// Function pointer type definition for the console detection logic.
|
||||
// This allows switching between 'Standard' and 'SCPH-5903' heuristics dynamically.
|
||||
typedef void (*ConsoleLogicPtr)(uint8_t isDataSector);
|
||||
|
||||
// Global pointer holding the currently active logic function.
|
||||
// Using a function pointer eliminates the need for repetitive 'if/else' checks in the main loop.
|
||||
volatile ConsoleLogicPtr currentLogic = logic_Standard;
|
||||
|
||||
// Variables de contrôle globales
|
||||
uint8_t scbuf[12] = { 0 };
|
||||
// Global buffer to store the 12-byte SUBQ channel data
|
||||
uint8_t subqBuffer[12];
|
||||
uint8_t hysteresis = 0;
|
||||
|
||||
//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.
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------------------------
|
||||
Code section
|
||||
@@ -165,440 +131,386 @@ uint8_t hysteresis = 0;
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function: board_detection
|
||||
* FUNCTION : BoardDetection
|
||||
*
|
||||
* DESCRIPTION :
|
||||
* Distinguishes motherboard generations (PU-7 through PU-22+) by analyzing
|
||||
* the behavior of the WFCK signal.
|
||||
* SIGNAL CHARACTERISTICS:
|
||||
* - Legacy Boards (PU-7 to PU-20): WFCK acts as a static GATE signal.
|
||||
* It remains HIGH (continuous) during the region-check window.
|
||||
* - Modern Boards (PU-22 or newer): WFCK is an oscillating clock signal
|
||||
* (Frequency-based).
|
||||
*
|
||||
* WFCK: __----------------------- // CONTINUOUS (PU-7 .. PU-20)(GATE)
|
||||
*
|
||||
* WFCK: __-_-_-_-_-_-_-_-_-_-_-_- // FREQUENCY (PU-22 or newer)
|
||||
*
|
||||
*
|
||||
* HISTORICAL CONTEXT:
|
||||
* Traditionally, WFCK was referred to as the "GATE" signal. On early models,
|
||||
* modchips functioned as a synchronized gate, pulling the signal LOW
|
||||
* precisely when the region-lock data was being processed.
|
||||
*
|
||||
* FREQUENCY DATA:
|
||||
* - Initial/Protection Phase: ~7.3 kHz.
|
||||
* - Standard Data Reading: ~14.6 kHz.
|
||||
*
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
This function distinguishes motherboard generations by detecting
|
||||
the nature of the WFCK signal:
|
||||
void BoardDetection() {
|
||||
// Default state: 0 (Static/GATE mode for PU-7 to PU-20)
|
||||
wfck_mode = 0;
|
||||
|
||||
WFCK: __----------------------- // CONTINUOUS (PU-7 .. PU-20)(GATE)
|
||||
/**
|
||||
* INITIAL STABILIZATION DELAY (300ms)
|
||||
* - PU-7/20: Voltage ramp-up takes ~54ms before stabilizing at a logic HIGH.
|
||||
* - PU-22+: Clock oscillation (~7.3kHz) typically begins after ~297ms.
|
||||
* This delay ensures all power-up transients and initial noise are bypassed.
|
||||
*/
|
||||
_delay_ms(300);
|
||||
|
||||
WFCK: __-_-_-_-_-_-_-_-_-_-_-_- // FREQUENCY (PU-22 or newer)
|
||||
// Define a sampling window to capture potential oscillations
|
||||
uint16_t detectionWindow = 10000;
|
||||
|
||||
while (--detectionWindow) {
|
||||
/**
|
||||
* DETECTION LOGIC:
|
||||
* On legacy boards (PU-7/20), WFCK is now a steady HIGH.
|
||||
* Detecting a LOW state indicates a potential clock cycle from a newer board.
|
||||
*/
|
||||
if (!PIN_WFCK_READ) {
|
||||
// Software debounce to filter out micro-glitches or parasitic noise
|
||||
uint8_t debounce = 100;
|
||||
while (--debounce);
|
||||
|
||||
Traditionally, the WFCK signal was called GATE. This is because, on early models,
|
||||
modchips acted like a gate that would open to pull the signal down
|
||||
at the exact moment the region code was being passed (which is still the case today).
|
||||
|
||||
During the initialization and region protection zone reading phases,
|
||||
the WFCK clock frequency is approximately 7.3 kHz.
|
||||
During normal data reading, the frequency shifts to 14.6 kHz.
|
||||
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
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);
|
||||
|
||||
pulses++;
|
||||
|
||||
// High count (> 500) oscillating signal (Newer boards)
|
||||
if (pulses > 500) {
|
||||
wfck_mode = 1; // Target: PU-22 or newer
|
||||
/**
|
||||
* VERIFICATION:
|
||||
* If the signal remains LOW after the debounce, we confirm a genuine
|
||||
* clock oscillation (WFCK). Legacy boards never transition to LOW
|
||||
* once stabilized at HIGH during this phase.
|
||||
*/
|
||||
if (!PIN_WFCK_READ) {
|
||||
wfck_mode = 1; // Target confirmed: PU-22 or newer (Frequency mode)
|
||||
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(debounce, 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.
|
||||
//******************************************************************************************************************
|
||||
void captureSubQ(void) {
|
||||
/******************************************************************************************************************
|
||||
* FUNCTION : CaptureSUBQ
|
||||
*
|
||||
* DESCRIPTION :
|
||||
* Captures a complete 12-byte SUBQ frame from the CD controller.
|
||||
* Synchronizes with the SQCK (Sub-Q Clock) pin to shift in serial data from
|
||||
* the SUBQ pin. This implementation follows the standard PlayStation CDIC
|
||||
* protocol (Synchronous Serial, LSB first).
|
||||
******************************************************************************************************************/
|
||||
|
||||
uint8_t scpos = 0;
|
||||
//uint8_t bitbuf = 0;
|
||||
void CaptureSUBQ(void) {
|
||||
uint8_t bytesRemaining = 12; // Total frame size for a complete SUBQ
|
||||
uint8_t* bufferPtr = subqBuffer;
|
||||
|
||||
do {
|
||||
uint8_t bitbuf = 0;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
// Wait for Clock to go LOW then HIGH (Sampling on Rising Edge)
|
||||
while (PIN_SQCK_READ); // Wait for LOW
|
||||
while (! PIN_SQCK_READ); // Wait for HIGH
|
||||
uint8_t currentByte = 0;
|
||||
uint8_t bitsToRead = 8;
|
||||
|
||||
while (bitsToRead--) {
|
||||
/**
|
||||
* PHASE 1: BIT SYNCHRONIZATION (SQCK)
|
||||
* The CD controller signals a new bit by toggling the Clock line.
|
||||
* Data is sampled on the RISING EDGE of SQCK for maximum stability.
|
||||
*/
|
||||
while (PIN_SQCK_READ); // Wait for falling edge
|
||||
while (!PIN_SQCK_READ); // Wait for rising edge
|
||||
|
||||
// Shift buffer and sample the SUBQ pin
|
||||
bitbuf >>= 1;
|
||||
/**
|
||||
* PHASE 2: BIT ACQUISITION & SHIFTING
|
||||
* The PlayStation SUBQ bus transmits data LSB (Least Significant Bit) first.
|
||||
* We shift the current byte right and inject the new bit into the MSB (0x80).
|
||||
*/
|
||||
currentByte >>= 1;
|
||||
if (PIN_SUBQ_READ) {
|
||||
bitbuf |= 0x80;
|
||||
currentByte |= 0x80;
|
||||
}
|
||||
}
|
||||
scbuf[scpos++] = bitbuf;
|
||||
} while (scpos < 12);
|
||||
// Store reconstructed byte and advance pointer
|
||||
*bufferPtr++ = currentByte;
|
||||
|
||||
} while (--bytesRemaining); // Efficient countdown for AVR binary size
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
LogSUBQ(subqBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************************
|
||||
* Processes sector data for the SCPH-5903 (Dual-interface PS1) to differentiate
|
||||
* between PlayStation games and Video CDs (VCD).
|
||||
*
|
||||
* This heuristic uses an 'hysteresis' counter to stabilize disc detection:
|
||||
* - Increases when a PSX Lead-In or valid game sector is identified.
|
||||
* - Remains neutral/ignores VCD-specific Lead-In patterns.
|
||||
* - Decreases (fades out) when the data does not match known patterns.
|
||||
*
|
||||
* isDataSector Boolean flag indicating if the current sector contains data.
|
||||
|
||||
**************************************************************************************/
|
||||
// void logic_SCPH_5903(uint8_t isDataSector) {
|
||||
// // Identify VCD Lead-In: Specific SCBUF patterns (0xA0/A1/A2) with sub-mode 0x02
|
||||
// uint8_t isVcdLeadIn = isDataSector && scbuf[1] == 0x00 && scbuf[6] == 0x00 &&
|
||||
// (scbuf[2] == 0xA0 || scbuf[2] == 0xA1 || scbuf[2] == 0xA2) &&
|
||||
// (scbuf[3] == 0x02);
|
||||
|
||||
// // Identify PSX Lead-In: Same SCBUF patterns but different sub-mode (!= 0x02)
|
||||
// uint8_t isPsxLeadIn = isDataSector && scbuf[1] == 0x00 && scbuf[6] == 0x00 &&
|
||||
// (scbuf[2] == 0xA0 || scbuf[2] == 0xA1 || scbuf[2] == 0xA2) &&
|
||||
// (scbuf[3] != 0x02);
|
||||
|
||||
// if (isPsxLeadIn) {
|
||||
// hysteresis++;
|
||||
// }
|
||||
// else if (hysteresis > 0 && !isVcdLeadIn &&
|
||||
// ((scbuf[0] == 0x01 || isDataSector) && scbuf[1] == 0x00 && scbuf[6] == 0x00)) {
|
||||
// hysteresis++; // Maintain/Increase confidence for valid non-VCD sectors
|
||||
// }
|
||||
// else if (hysteresis > 0) {
|
||||
// hysteresis--; // Patterns stop matching
|
||||
// }
|
||||
// }
|
||||
|
||||
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++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Patterns stop matching or VCD Lead-In detected: decrease confidence
|
||||
if (hysteresis > 0) {
|
||||
hysteresis--;
|
||||
}
|
||||
}
|
||||
/******************************************************************************************
|
||||
* Heuristic logic for standard PlayStation hardware (Non-VCD models).
|
||||
* FUNCTION : Filter_SUBQ_Samples() [SCPH_5903 Dual-Interface Variant]
|
||||
*
|
||||
* This function monitors disc sectors to identify genuine PlayStation discs:
|
||||
* 1. Checks for specific Lead-In markers (Point A0, A1, A2 or Track 01).
|
||||
* 2. Uses an incrementing 'hysteresis' counter to confirm disc validity.
|
||||
* 3. Includes a 'fade-out' mechanism to reduce the counter if valid patterns are lost,
|
||||
* effectively filtering out noise or read errors.
|
||||
*
|
||||
* isDataSector Boolean flag: true if the current sector is a data sector.
|
||||
* DESCRIPTION :
|
||||
* Parses and filters the raw serial data stream from the SUBQ pin specifically
|
||||
* for the SCPH-5903 model to differentiate between Game Discs and Video CDs (VCD).
|
||||
*
|
||||
* 1. VCD EXCLUSION: Specifically filters out VCD Lead-In patterns (sub-mode 0x02)
|
||||
* to prevent incorrect region injection on non-game media.
|
||||
* 2. SUBQ HIT COUNTING: Increments 'hysteresis' for valid PlayStation TOC (A0-A2)
|
||||
* markers or active game tracking.
|
||||
* 3. SIGNAL DECAY: Decrements the counter when SUBQ samples match VCD patterns
|
||||
* or unknown data, ensuring stable disc identification.
|
||||
*
|
||||
* INPUT : isDataSector (bool) - Filtered flag based on raw sector control bits.
|
||||
******************************************************************************************/
|
||||
#ifdef SCPH_5903
|
||||
|
||||
******************************************************************************************/
|
||||
void FilterSUBQSamples(uint8_t isDataSector) {
|
||||
uint8_t currentHysteresis = hysteresis;
|
||||
|
||||
// void logic_Standard(uint8_t isDataSector) {
|
||||
// // Detect specific Lead-In patterns
|
||||
// if ((isDataSector && scbuf[1] == 0x00 && scbuf[6] == 0x00) &&
|
||||
// (scbuf[2] == 0xA0 || scbuf[2] == 0xA1 || scbuf[2] == 0xA2 ||
|
||||
// (scbuf[2] == 0x01 && (scbuf[3] >= 0x98 || scbuf[3] <= 0x02)))) {
|
||||
// hysteresis++;
|
||||
// }
|
||||
// // Maintain confidence if general valid sector markers are found
|
||||
// else if (hysteresis > 0 &&
|
||||
// ((scbuf[0] == 0x01 || isDataSector) && scbuf[1] == 0x00 && scbuf[6] == 0x00)) {
|
||||
// hysteresis++;
|
||||
// }
|
||||
// else if (hysteresis > 0) {
|
||||
// hysteresis--;
|
||||
// }
|
||||
// }
|
||||
// --- STEP 1: SUBQ Frame Synchronization ---
|
||||
// Fast filtering: ignore raw data if sync markers (index 1 and 6) are not 0x00.
|
||||
if (subqBuffer[1] == 0x00 && subqBuffer[6] == 0x00) {
|
||||
uint8_t pointAddress = subqBuffer[2];
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// Maintain confidence if general valid sector markers are found
|
||||
if (hysteresis > 0 && (scbuf[0] == 0x01 || isDataSector)) {
|
||||
hysteresis++;
|
||||
/**
|
||||
* HIT INCREMENT CONDITIONS:
|
||||
* A. VALID PSX LEAD-IN: Data sector AND Point A0-A2 range AND NOT VCD (sub-mode != 0x02).
|
||||
* (uint8_t)(pointAddress - 0xA0) <= 2 is an optimized check for 0xA0, 0xA1, 0xA2.
|
||||
* B. TRACKING MAINTENANCE: Keeps count if already synced and reading Mode 0x01 or Data.
|
||||
*/
|
||||
if ( (isDataSector && (uint8_t)(pointAddress - 0xA0) <= 2 && subqBuffer[3] != 0x02) ||
|
||||
(currentHysteresis > 0 && (subqBuffer[0] == 0x01 || isDataSector)) )
|
||||
{
|
||||
hysteresis = currentHysteresis + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No valid pattern found: decrease confidence
|
||||
if (hysteresis > 0) {
|
||||
hysteresis--;
|
||||
// --- STEP 2: Signal Decay / Pattern Mismatch ---
|
||||
// Decrement the hit counter if no valid PSX pattern is detected in the SUBQ stream.
|
||||
if (currentHysteresis > 0) {
|
||||
hysteresis = currentHysteresis - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
/******************************************************************************************
|
||||
* FUNCTION : Filter_SUBQ_Samples()
|
||||
*
|
||||
* DESCRIPTION :
|
||||
* Parses and filters the raw serial data stream from the SUBQ pin.
|
||||
* Increments a hit counter (hysteresis) when specific patterns are identified
|
||||
* in the SUBQ stream, confirming the laser is reading the region-check area.
|
||||
*
|
||||
* 1. RAW BUS FILTERING: Validates SUBQ framing by checking sync markers (index 1 & 6).
|
||||
* 2. PATTERN MATCHING: Detects Lead-In TOC (A0-A2) or Track 01 at the spiral start.
|
||||
* 3. SIGNAL DECAY: Decrements the counter if the current SUBQ sample does not
|
||||
* match expected PlayStation protection patterns.
|
||||
*
|
||||
* INPUT : isDataSector (bool) - Filtered flag based on raw sector control bits.
|
||||
******************************************************************************************/
|
||||
|
||||
|
||||
void FilterSUBQSamples(uint8_t isDataSector) {
|
||||
uint8_t currentHysteresis = hysteresis;
|
||||
|
||||
// --- STEP 1: SUBQ Frame Synchronization ---
|
||||
// Ignore the raw bitstream unless sync markers (1 & 6) are 0x00.
|
||||
if (subqBuffer[1] == 0x00 && subqBuffer[6] == 0x00) {
|
||||
uint8_t pointAddress = subqBuffer[2];
|
||||
|
||||
/*
|
||||
* HIT INCREMENT CONDITIONS:
|
||||
* A. LEAD-IN PATTERNS: Detects TOC markers (A0-A2) or Track 01 at spiral start.
|
||||
* (uint8_t)(subqBuffer[3] - 0x03) >= 0xF5 handles the 0x98 to 0x02 wrap-around.
|
||||
* B. TRACKING LOCK: Maintains count if already synced and reading valid sectors.
|
||||
*/
|
||||
if ( (isDataSector && (pointAddress >= 0xA0 || (pointAddress == 0x01 && ( (uint8_t)(subqBuffer[3] - 0x03) >= 0xF5)))) ||
|
||||
(currentHysteresis > 0 && (subqBuffer[0] == 0x01 || isDataSector)) )
|
||||
{
|
||||
hysteresis = currentHysteresis + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// --- STEP 2: Signal Decay / Missed Hits ---
|
||||
// Reduce the hit counter if the current SUBQ sample fails validation.
|
||||
if (currentHysteresis > 0) {
|
||||
hysteresis = currentHysteresis - 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*********************************************************************************************
|
||||
* Executes the SCEx signal injection sequence to bypass regional lockout.
|
||||
* Executes the SCEx injection sequence to bypass the CD-ROM regional lockout.
|
||||
*
|
||||
* This function handles the precise timing required to send the 44-bit security
|
||||
* strings. It supports both legacy "Logic Gate" mode and modern "WFCK Modulation"
|
||||
* for compatibility across all console revisions (PU-7 to PM-41).
|
||||
* This function supports two hardware-specific injection methods:
|
||||
* 1. Legacy Gate Mode (PU-7 to PU-20): Modchip acts as a logic gate to pull
|
||||
* the signal down. WFCK is simulated by the chip if necessary.
|
||||
* 2. WFCK Modulation (PU-22+): Modchip modulates the DATA signal in
|
||||
* sync with the console's real WFCK clock.
|
||||
*
|
||||
* injectSCEx 0:NTSC-J SCEI, 1:NTSC-U/C SCEA, 2:PAL SCEE, 3:Universal (Cycles through all).
|
||||
* NOTE: WFCK frequency is approx. 7.3 kHz during initialization/region check,
|
||||
* but doubles to 14.6 kHz during normal data reading. The modulation loop
|
||||
* handles both speeds as it syncs directly to the signal edges.
|
||||
*********************************************************************************************/
|
||||
|
||||
void performInjectionSequence(uint8_t injectSCEx) {
|
||||
// 44-bit SCEx strings for Japan Asia, USA, and Europe
|
||||
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] = {
|
||||
{ 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11011010, 0b00000010 }, // SCEI
|
||||
{ 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11111010, 0b00000010 }, // SCEA
|
||||
{ 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11101010, 0b00000010 } // SCEE
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xDA, 0x02 }, // SCEI
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xFA, 0x02 }, // SCEA
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xEA, 0x02 } // SCEE
|
||||
};
|
||||
|
||||
hysteresis = 11;
|
||||
|
||||
hysteresis = (HYSTERESIS_MAX - 10); // Reset hysteresis to mid-point after triggering
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_ON;
|
||||
#endif
|
||||
|
||||
// Pin initialization
|
||||
// Cache wfck_mode to save CPU cycles during the bit loop
|
||||
uint8_t isWfck = wfck_mode;
|
||||
PIN_DATA_OUTPUT;
|
||||
PIN_DATA_CLEAR;
|
||||
|
||||
if (!wfck_mode) {
|
||||
PIN_WFCK_OUTPUT; PIN_WFCK_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);
|
||||
|
||||
// Injection loop (3 cycles)
|
||||
// Loop through the selected region(s)
|
||||
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];
|
||||
const uint8_t* bytePtr = allRegionsSCEx[regionIndex];
|
||||
|
||||
uint8_t currentByte = *bytePtr++;
|
||||
uint8_t bitIdx = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
// Bit-level extraction: isolate the target bit and prepare next
|
||||
uint8_t currentBit = currentByte & 0x01;
|
||||
currentByte >>= 1;
|
||||
// Process the 44-bit SCEx stream
|
||||
for (uint8_t totalBits = 44; totalBits > 0; totalBits--) {
|
||||
uint8_t currentBit = currentByte & 0x01;
|
||||
currentByte >>= 1;
|
||||
bitIdx++;
|
||||
|
||||
if (!wfck_mode) {
|
||||
// LOGIC GATE MODE (Old boards)
|
||||
if (currentBit == 0) {
|
||||
PIN_DATA_OUTPUT; PIN_DATA_CLEAR;
|
||||
}
|
||||
else {
|
||||
PIN_DATA_INPUT; // High Impedance = 1
|
||||
}
|
||||
// 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 {
|
||||
// WFCK MODULATION (Newer boards / PU-18+)
|
||||
if (currentBit == 0) {
|
||||
PIN_DATA_CLEAR;
|
||||
} 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 {
|
||||
// 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;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Inter-string silence
|
||||
|
||||
/*
|
||||
EXIT CONDITION:
|
||||
If we are NOT in Universal mode (3), we stop after the first
|
||||
successful region injection.
|
||||
*/
|
||||
if (injectSCEx != 3) {
|
||||
|
||||
PIN_DATA_OUTPUT;
|
||||
PIN_DATA_CLEAR;
|
||||
|
||||
if (!isWfck) {
|
||||
PIN_WFCK_INPUT;
|
||||
PIN_DATA_INPUT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Clean up state between region cycles
|
||||
PIN_DATA_OUTPUT;
|
||||
PIN_DATA_CLEAR;
|
||||
_delay_ms(DELAY_BETWEEN_INJECTIONS);
|
||||
_delay_ms(180);
|
||||
|
||||
}
|
||||
|
||||
// Cleanup: Set pins to High-Z (Safe mode)
|
||||
if (!wfck_mode) {
|
||||
PIN_WFCK_INPUT;
|
||||
PIN_DATA_INPUT;
|
||||
// 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;
|
||||
PIN_LED_OFF;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
DebugInject();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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 }, // NTSC-J SCEI SCPH-xxx0 SCPH-xxx3
|
||||
// { 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11111010, 0b00000010 }, // NTSC-U/C SCEA SCPH-xxx1
|
||||
// { 0b01011001, 0b11001001, 0b01001011, 0b01011101, 0b11101010, 0b00000010 } // PAL SCEE SCPH-xxx2
|
||||
// };
|
||||
|
||||
// // if (hysteresis < HYSTERESIS_MAX) return;
|
||||
|
||||
|
||||
// hysteresis = 11;
|
||||
|
||||
// #ifdef LED_RUN
|
||||
// PIN_LED_ON;
|
||||
// #endif
|
||||
|
||||
// // Pin initialization
|
||||
// PIN_DATA_OUTPUT;
|
||||
// PIN_DATA_CLEAR;
|
||||
|
||||
// if (!wfck_mode) {
|
||||
// PIN_WFCK_OUTPUT;
|
||||
// PIN_WFCK_CLEAR;
|
||||
|
||||
// }
|
||||
// _delay_ms(DELAY_BETWEEN_INJECTIONS);
|
||||
|
||||
// // 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];
|
||||
|
||||
// for (uint8_t bit_counter = 0; bit_counter < 44; bit_counter++) {
|
||||
// // Bit-level extraction:
|
||||
// // 1. bit_counter >> 3 identifies the byte index (integer division by 8).
|
||||
// // 2. bit_counter & 0x07 identifies the bit position within that byte (modulo 8).
|
||||
// // 3. Right-shift and mask (& 0x01) isolates the target bit for injection.
|
||||
// uint8_t currentByte = ByteSet[bit_counter >> 3];
|
||||
// uint8_t currentBit = (currentByte >> (bit_counter & 0x07)) & 0x01;
|
||||
|
||||
// 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+)
|
||||
// // PIN_DATA_OUTPUT;
|
||||
// if (currentBit == 0) {
|
||||
// PIN_DATA_CLEAR;
|
||||
// _delay_us(DELAY_BETWEEN_BITS);
|
||||
// }
|
||||
// else {
|
||||
// // Synchronize injection with WFCK clock edges
|
||||
// uint8_t count = 30;
|
||||
// uint8_t last_wfck = PIN_WFCK_READ;
|
||||
// while (count > 0) {
|
||||
// uint8_t current_wfck = PIN_WFCK_READ;
|
||||
// if (current_wfck != last_wfck) {
|
||||
// if (current_wfck) {
|
||||
// PIN_DATA_SET; count--;
|
||||
// }
|
||||
// else {
|
||||
// PIN_DATA_CLEAR;
|
||||
// }
|
||||
// last_wfck = current_wfck;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 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
|
||||
// }
|
||||
|
||||
void Init() {
|
||||
|
||||
#if defined(ATmega328_168)
|
||||
optimizePeripherals();
|
||||
#endif
|
||||
// --- Hardware Power & Peripheral Optimization ---
|
||||
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_OUTPUT;
|
||||
#endif
|
||||
OptimizePeripherals();
|
||||
|
||||
#ifdef BIOS_PATCH
|
||||
uint8_t Flag_Switch = 0;
|
||||
GLOBAL_INTERRUPT_ENABLE;
|
||||
#ifdef SCPH_7000
|
||||
PIN_SWITCH_INPUT;
|
||||
PIN_SWITCH_SET;
|
||||
if (PIN_SWITCH_READ == 0){
|
||||
Flag_Switch =1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LED_RUN
|
||||
//PIN_LED_ON;
|
||||
#endif
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_OUTPUT;
|
||||
#endif
|
||||
|
||||
if (Flag_Switch == 0) {
|
||||
Bios_Patching();
|
||||
}
|
||||
// --- Critical Boot Patching ---
|
||||
#ifdef BIOS_PATCH
|
||||
|
||||
#ifdef LED_RUN
|
||||
//PIN_LED_OFF;
|
||||
#endif
|
||||
// #ifdef LED_RUN
|
||||
// PIN_LED_ON;
|
||||
// #endif
|
||||
|
||||
#endif
|
||||
// Execute BIOS patching
|
||||
Bios_Patching();
|
||||
|
||||
cli();
|
||||
|
||||
// #ifdef LED_RUN
|
||||
// PIN_LED_OFF;
|
||||
// #endif
|
||||
#endif
|
||||
|
||||
GLOBAL_INTERRUPT_DISABLE;
|
||||
|
||||
PIN_SQCK_INPUT;
|
||||
PIN_SUBQ_INPUT;
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
#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
|
||||
}
|
||||
=======
|
||||
// --- Debug Interface Setup ---
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR) && defined(IS_ATTINY_FAMILY)
|
||||
//pinMode(debugtx, OUTPUT); // software serial tx pin
|
||||
@@ -609,60 +521,36 @@ void Init() {
|
||||
|
||||
// --- Console Analysis ---
|
||||
// Identify board revision (PU-7 to PU-22+) to set correct injection timings
|
||||
BoardBetection();
|
||||
BoardDetection();
|
||||
}
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
int main() {
|
||||
|
||||
Init();
|
||||
|
||||
|
||||
#ifdef SCPH_5903
|
||||
currentLogic = logic_SCPH_5903;
|
||||
#else
|
||||
currentLogic = logic_Standard;
|
||||
#endif
|
||||
board_detection();
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
Debug_Log(lows, wfck_mode);
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
|
||||
_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*/
|
||||
captureSubQ();
|
||||
// 1. Timing Sync: Prevent reading the tail end of the previous SUBQ packet
|
||||
_delay_ms(1);
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
Debug_Scbuf(scbuf);
|
||||
#endif
|
||||
// 2. Data Acquisition: Capture 12-byte SUBQ channel stream into buffer
|
||||
CaptureSUBQ();
|
||||
|
||||
/*-------------------------------------------------------------------------------
|
||||
Check if read head is in wobble area
|
||||
We only want to unlock game discs (0x41) and only if the read head is in the outer TOC area.
|
||||
We want to see a TOC sector repeatedly before injecting (helps with timing and marginal lasers).
|
||||
All this logic is because we don't know if the HC-05 is actually processing a getSCEX() command.
|
||||
Hysteresis is used because older drives exhibit more variation in read head positioning.
|
||||
While the laser lens moves to correct for the error, they can pick up a few TOC sectors.
|
||||
-------------------------------------------------------------------------------*/
|
||||
// 3. Sector Validation (Data/TOC check):
|
||||
// Masking bits 7, 6, and 4 simultaneously using 0xD0 (binary 11010000).
|
||||
// This verifies that the "Data/TOC" bit (0x40) is SET, while bits 7 and 4 are CLEARED.
|
||||
// Equivalent to: (bit7 == 0 && bit6 == 1 && bit4 == 0).
|
||||
//uint8_t isDataSector = ((scbuf[0] & 0xD0) == 0x40);
|
||||
uint8_t isDataSector = ((subqBuffer[0] & 0xD0) == 0x40);
|
||||
|
||||
//This variable initialization macro is to replace (0x41) with a filter that will check that only the three most significant bits are correct. 0x001xxxxx
|
||||
uint8_t isDataSector = (((scbuf[0] & 0x40) == 0x40) && (((scbuf[0] & 0x10) == 0) && ((scbuf[0] & 0x80) == 0)));
|
||||
|
||||
// Execute selected logic through function pointer
|
||||
currentLogic(isDataSector);
|
||||
|
||||
|
||||
if (hysteresis >= HYSTERESIS_MAX) {
|
||||
performInjectionSequence(INJECT_SCEx);
|
||||
}
|
||||
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
Debug_Inject();
|
||||
#endif
|
||||
// Execute selected logic
|
||||
FilterSUBQSamples(isDataSector);
|
||||
|
||||
// 5. Execution: Trigger SCEx injection once confidence (hysteresis) is reached
|
||||
if (hysteresis >= HYSTERESIS_MAX) {
|
||||
PerformInjectionSequence(INJECT_SCEx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
456
PSNee/settings.h
456
PSNee/settings.h
@@ -22,8 +22,7 @@
|
||||
|
||||
// Results of the maximum values
|
||||
// tested with an Atmega328P
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
|
||||
#if defined(IS_32U4_FAMILY)
|
||||
|
||||
// ------ SCPH 100 / 102 ------
|
||||
@@ -36,184 +35,179 @@
|
||||
#define BIT_OFFSET_CYCLES 47 //60
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
|
||||
// #ifdef SCPH_102
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_RISING
|
||||
// #define BOOT_OFFSET 83.9
|
||||
// #define PULSE_COUNT 48 !!! -1
|
||||
// #define BIT_OFFSET 2.75
|
||||
// #define OVERRIDE 0.2
|
||||
// #endif
|
||||
// // -------- SCPH 7500 / 9000 --------
|
||||
#ifdef SCPH_7500_9000
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 1100
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 15 //15
|
||||
#define BIT_OFFSET_CYCLES 47 //60
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
|
||||
// #ifdef SCPH_100
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_RISING
|
||||
// #define BOOT_OFFSET 83.9 //83.72 - 84.15
|
||||
// #define PULSE_COUNT 47
|
||||
// #define BIT_OFFSET 2.75 //2.63 - 2.87
|
||||
// #define OVERRIDE 0.2
|
||||
// #endif
|
||||
|
||||
#ifdef SCPH_102
|
||||
#define BIOS_PATCH
|
||||
#define TEST_BIOS
|
||||
#define BOOT_OFFSET 83.9 // Stabilization window (ms)
|
||||
#define BIT_OFFSET 225.6 // Precision data alignment (us)
|
||||
#define OVERRIDE 0.2 // DX injection width (us)
|
||||
// -------- SCPH 7000 --------
|
||||
#ifdef SCPH_7000
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 1100
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 15
|
||||
#define BIT_OFFSET_CYCLES 47
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
|
||||
|
||||
// // ----- SCPH 3500 / 5000 / 5500 -----
|
||||
#ifdef SCPH_3500_5500
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 25000
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 84 //84
|
||||
#define BIT_OFFSET_CYCLES 47 //60
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
|
||||
// // -------- SCPH 3000 --------
|
||||
#ifdef SCPH_3000
|
||||
#define BIOS_PATCH
|
||||
#define PHASE_TWO_PATCH
|
||||
#define SILENCE_THRESHOLD 1100
|
||||
#define CONFIRM_COUNTER_TARGET 9
|
||||
#define PULSE_COUNT 59
|
||||
#define BIT_OFFSET_CYCLES 45
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#define CONFIRM_COUNTER_TARGET_2 206
|
||||
#define PULSE_COUNT_2 42
|
||||
#define BIT_OFFSET_2_CYCLES 48
|
||||
#define OVERRIDE_2_CYCLES 3
|
||||
#endif
|
||||
|
||||
|
||||
// // -------- SCPH 1000 --------
|
||||
#ifdef SCPH_1000
|
||||
#define BIOS_PATCH
|
||||
#define PHASE_TWO_PATCH
|
||||
#define SILENCE_THRESHOLD 1100
|
||||
#define CONFIRM_COUNTER_TARGET 9
|
||||
#define PULSE_COUNT 91
|
||||
#define BIT_OFFSET_CYCLES 45
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#define CONFIRM_COUNTER_TARGET_2 222
|
||||
#define PULSE_COUNT_2 70
|
||||
#define BIT_OFFSET_2_CYCLES 48
|
||||
#define OVERRIDE_2_CYCLES 3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_100
|
||||
#define BIOS_PATCH
|
||||
#define TEST_BIOS
|
||||
#define BOOT_OFFSET 83.9 // Stabilization window (ms)
|
||||
#define BIT_OFFSET 225.6 // Precision data alignment (us)
|
||||
#define OVERRIDE 0.2 // DX injection width (us)
|
||||
#endif
|
||||
#if defined(IS_328_168_FAMILY)
|
||||
|
||||
#ifdef SCPH_7500_9000
|
||||
#define BIOS_PATCH
|
||||
#define TEST_BIOS
|
||||
#define BOOT_OFFSET 75.2
|
||||
#define BIT_OFFSET 71.5
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
// ------ SCPH 100 / 102 ------
|
||||
#if defined(SCPH_100) || \
|
||||
defined(SCPH_102)
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 1500
|
||||
#define CONFIRM_COUNTER_TARGET 8
|
||||
#define PULSE_COUNT 47 //47
|
||||
#define BIT_OFFSET_CYCLES 47 //60
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_7000
|
||||
#define BIOS_PATCH
|
||||
#define TEST_BIOS
|
||||
#define BOOT_OFFSET 75.2
|
||||
#define BIT_OFFSET 71.5
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_5500
|
||||
#define BIOS_PATCH
|
||||
#define TEST_BIOS
|
||||
#define LOW_TRIGGER
|
||||
#define BOOT_OFFSET 76.07 //75.99 - 76.14
|
||||
#define BIT_OFFSET 95.6
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
// // -------- SCPH 7500 / 9000 --------
|
||||
#ifdef SCPH_7500_9000
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 1500
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 15 //15
|
||||
#define BIT_OFFSET_CYCLES 47 //60
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_5000
|
||||
#define BIOS_PATCH
|
||||
#define TEST_BIOS
|
||||
#define LOW_TRIGGER
|
||||
#define BOOT_OFFSET 75.2 //75.12 - 75.27
|
||||
#define BIT_OFFSET 95.65
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_3500
|
||||
#define BIOS_PATCH
|
||||
#define TEST_BIOS
|
||||
#define LOW_TRIGGER
|
||||
#define BOOT_OFFSET 75.2 //75.12 - 75.27
|
||||
#define BIT_OFFSET 95.4
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
// -------- SCPH 7000 --------
|
||||
#ifdef SCPH_7000
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 1500
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 15
|
||||
#define BIT_OFFSET_CYCLES 47
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
|
||||
// #ifdef SCPH_3000
|
||||
// #define BIOS_PATCH
|
||||
// #define HIGH_PATCH_A
|
||||
// #define BOOT_OFFSET 82.9 //82.65 - 83.26
|
||||
// #define BIT_OFFSET 283.25
|
||||
// #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_3000
|
||||
#define BIOS_PATCH
|
||||
#define HIGH_PATCH_B
|
||||
#define BOOT_OFFSET 82.9 //82.65 - 83.26
|
||||
#define BIT_OFFSET 283.25
|
||||
#define OVERRIDE 0.15
|
||||
#define HIGH_PATCH
|
||||
#define FOLLOWUP_OFFSET 253.3
|
||||
#define BIT_OFFSET_2 201.8
|
||||
#define OVERRIDE_2 0.15
|
||||
#endif
|
||||
// // ----- SCPH 3500 / 5000 / 5500 -----
|
||||
#ifdef SCPH_3500_5500
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 32000
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 84 //84
|
||||
#define BIT_OFFSET_CYCLES 47 //60
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#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
|
||||
// // -------- SCPH 3000 --------
|
||||
#ifdef SCPH_3000
|
||||
#define BIOS_PATCH
|
||||
#define PHASE_TWO_PATCH
|
||||
#define SILENCE_THRESHOLD 1500
|
||||
#define CONFIRM_COUNTER_TARGET 9
|
||||
#define PULSE_COUNT 59
|
||||
#define BIT_OFFSET_CYCLES 45
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#define CONFIRM_COUNTER_TARGET_2 206
|
||||
#define PULSE_COUNT_2 42
|
||||
#define BIT_OFFSET_2_CYCLES 48
|
||||
#define OVERRIDE_2_CYCLES 3
|
||||
#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
|
||||
|
||||
// #ifdef SCPH_1000
|
||||
// #define BIOS_PATCH
|
||||
// #define HIGH_PATCH_A
|
||||
// #define BOOT_OFFSET 82.9 // 82.63 - 83.26
|
||||
// #define BIT_OFFSET 437.1 // 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
|
||||
|
||||
#ifdef SCPH_1000
|
||||
#define BIOS_PATCH
|
||||
#define HIGH_PATCH_B
|
||||
#define BOOT_OFFSET 82.9 // 82.63 - 83.26
|
||||
#define BIT_OFFSET 437.1 // 2.58 - 2.75
|
||||
#define OVERRIDE 0.15
|
||||
#define HIGH_PATCH
|
||||
#define FOLLOWUP_OFFSET 272.8
|
||||
#define BIT_OFFSET_2 336.05
|
||||
#define OVERRIDE_2 0.15
|
||||
// // -------- SCPH 1000 --------
|
||||
#ifdef SCPH_1000
|
||||
#define BIOS_PATCH
|
||||
#define PHASE_TWO_PATCH
|
||||
#define SILENCE_THRESHOLD 1500
|
||||
#define CONFIRM_COUNTER_TARGET 9
|
||||
#define PULSE_COUNT 91
|
||||
#define BIT_OFFSET_CYCLES 45
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#define CONFIRM_COUNTER_TARGET_2 222
|
||||
#define PULSE_COUNT_2 70
|
||||
#define BIT_OFFSET_2_CYCLES 48
|
||||
#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_3500_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
|
||||
|
||||
|
||||
@@ -224,14 +218,13 @@
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
|
||||
void Debug_Log (uint16_t Lows, int Wfck_mode){ //Information about the MCU, and old or late console mode.
|
||||
void Debug_Log (uint16_t debounce, int Wfck_mode){ //Information about the MCU, and old or late console mode.
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
#if defined(ATtiny85_45_25)
|
||||
#if defined(IS_ATTINY_FAMILY)
|
||||
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(" debounce: "); Serial.println(debounce);
|
||||
Serial.print(" wfck_mode: "); Serial.println(Wfck_mode);
|
||||
Serial.print(" region: "); Serial.print(region[0]); Serial.print(region[1]); Serial.println(region[2]);
|
||||
#endif
|
||||
@@ -239,12 +232,11 @@ void Debug_Log (uint16_t Lows, int Wfck_mode){ //Information about the
|
||||
|
||||
// log SUBQ packets. We only have 12ms to get the logs written out. Slower MCUs get less formatting.
|
||||
void Debug_Scbuf (uint8_t *Scbuf){ // Data from the DATA bus
|
||||
#if defined(ATtiny85_45_25)
|
||||
#if defined(IS_ATTINY_FAMILY)
|
||||
if (!(Scbuf[0] == 0 && Scbuf[1] == 0 && Scbuf[2] == 0 && Scbuf[3] == 0)) { // a bad sector read is all 0 except for the CRC fields. Don't log it.
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (Scbuf[i] < 0x10) {
|
||||
mySerial.print("0"); // padding
|
||||
=======
|
||||
#if defined(IS_ATTINY_FAMILY)
|
||||
// --- COMPACT SYSTEM LOG (ATtiny) ---
|
||||
// Minimalistic output to save CPU cycles and maintain timing precision.
|
||||
@@ -266,7 +258,7 @@ void Debug_Scbuf (uint8_t *Scbuf){ // Data from the DATA bus
|
||||
Serial.println(region[2]); // Active injection string (e.g., SCEE)
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
/******************************************************************************************
|
||||
* FUNCTION : LogSUBQ
|
||||
*
|
||||
@@ -290,47 +282,41 @@ void LogSUBQ(uint8_t *dataBuffer) {
|
||||
*/
|
||||
if (!(dataBuffer[0] == 0 && dataBuffer[1] == 0 && dataBuffer[2] == 0 && dataBuffer[3] == 0)) {
|
||||
|
||||
#if defined(IS_ATTINY_FAMILY)
|
||||
// --- COMPACT FORMATTING (ATtiny) ---
|
||||
// Minimal formatting to meet the strict 12ms timing constraint on slower MCUs.
|
||||
for (uint8_t i = 0; i < 12; i++) {
|
||||
if (dataBuffer[i] < 0x10) {
|
||||
mySerial.print("0"); // Leading zero padding for hex alignment
|
||||
>>>>>>> Stashed changes
|
||||
#if defined(IS_ATTINY_FAMILY)
|
||||
// --- COMPACT FORMATTING (ATtiny) ---
|
||||
// Minimal formatting to meet the strict 12ms timing constraint on slower MCUs.
|
||||
for (uint8_t i = 0; i < 12; i++) {
|
||||
if (dataBuffer[i] < 0x10) {
|
||||
mySerial.print("0"); // Leading zero padding for hex alignment
|
||||
|
||||
}
|
||||
mySerial.print(Scbuf[i, HEX]);
|
||||
}
|
||||
mySerial.print(Scbuf[i, HEX]);
|
||||
mySerial.println("");
|
||||
}
|
||||
mySerial.println("");
|
||||
}
|
||||
#elif !defined(ATtiny85_45_25)
|
||||
if (!(Scbuf[0] == 0 && Scbuf[1] == 0 && Scbuf[2] == 0 && Scbuf[3] == 0)) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (Scbuf[i] < 0x10) {
|
||||
Serial.print("0"); // padding
|
||||
#elif !defined(IS_ATTINY_FAMILY)
|
||||
if (!(Scbuf[0] == 0 && Scbuf[1] == 0 && Scbuf[2] == 0 && Scbuf[3] == 0)) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (Scbuf[i] < 0x10) {
|
||||
Serial.print("0"); // padding
|
||||
}
|
||||
Serial.print(Scbuf[i], HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.print(Scbuf[i], HEX);
|
||||
Serial.print(" ");
|
||||
Serial.println("");
|
||||
}
|
||||
Serial.println("");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Debug_Inject(){ // Confirmation of region code injection
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
#if defined(ATtiny85_45_25)
|
||||
mySerial.print("!");
|
||||
#elif !defined(ATtiny85_45_25)|| defined(SCPH_102_legacy)
|
||||
=======
|
||||
|
||||
#if defined(IS_ATTINY_FAMILY)
|
||||
// --- MINIMALIST NOTIFICATION (ATtiny) ---
|
||||
mySerial.print("!");
|
||||
|
||||
#else
|
||||
// --- VERBOSE NOTIFICATION (ATmega) ---
|
||||
// Standard visual feedback for debugging and monitoring.
|
||||
>>>>>>> Stashed changes
|
||||
Serial.println(" INJECT ! ");
|
||||
#endif
|
||||
}
|
||||
@@ -341,52 +327,20 @@ 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)
|
||||
#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)
|
||||
#error "May be selected only one console! Please check #define with SCPH model number."
|
||||
#ifdef LED_RUN
|
||||
#pragma message "Feature: Status LED ENABLED"
|
||||
#endif
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
#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)
|
||||
#error "May be selected only one MCU"
|
||||
// SECURITY CHECK: Ensure only one console is selected
|
||||
// If you get "not portable" warnings here, it's only because multiple models are active.
|
||||
#if (defined(SCPH_1000) + defined(SCPH_3000) + defined(SCPH_3500_5500) + \
|
||||
defined(SCPH_7000) + defined(SCPH_7500_9000) + defined(SCPH_100) + \
|
||||
defined(SCPH_102) + defined(SCPH_xxx1) + defined(SCPH_xxx2) + \
|
||||
defined(SCPH_xxx3) + defined(SCPH_5903) + defined(SCPH_xxxx)) > 1
|
||||
#error "Too many consoles selected! Please uncomment ONLY ONE model."
|
||||
#endif
|
||||
|
||||
#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"
|
||||
=======
|
||||
// // --- MCU SELECTION CHECK ---
|
||||
// #if !defined(ATmega328_168) && \
|
||||
// !defined(ATmega328_168PB) && \
|
||||
// !defined(ATmega32U4_16U4) && \
|
||||
// !defined(ATtiny85_45_25)
|
||||
// #error "No MCU selected! Please choose one supported architecture."
|
||||
|
||||
// #elif (defined(ATmega328_168) + \
|
||||
// defined(ATmega328_168PB) + \
|
||||
// defined(ATmega32U4_16U4) + \
|
||||
// defined(ATtiny85_45_25) > 1)
|
||||
// #error "Multiple MCUs selected! Please enable only one architecture."
|
||||
// #endif
|
||||
|
||||
// --- RESOURCE CONFLICT CHECK (ATtiny) ---
|
||||
#if defined(IS_ATTINY_FAMILY) && \
|
||||
defined(LED_RUN) && \
|
||||
defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
#error "Resource conflict: LED_RUN and DEBUG_SERIAL are incompatible on ATtiny."
|
||||
#endif
|
||||
|
||||
// --- Console Model Info ---
|
||||
// Show target console.
|
||||
#if defined(SCPH_1000)
|
||||
#pragma message "Target Console: SCPH-1000 (NTSC-J)"
|
||||
#elif defined(SCPH_3000)
|
||||
@@ -399,29 +353,36 @@ void Debug_Inject(){ // Confirmation of region code injection
|
||||
#pragma message "Target Console: SCPH-7500/9000 (NTSC-J)"
|
||||
#elif defined(SCPH_100)
|
||||
#pragma message "Target Console: SCPH-100 (NTSC-J)"
|
||||
#elif defined(SCPH_101)
|
||||
#pragma message "Target Console: SCPH-101 (NTSC-U/C)"
|
||||
#elif defined(SCPH_102)
|
||||
#pragma message "Target Console: SCPH-102 (PAL)"
|
||||
#elif defined(SCPH_xxx1)
|
||||
#pragma message "Target Console: Generic NTSC-U/C"
|
||||
#pragma message "Target Console: SCPH_xxx1 Generic NTSC-U/C"
|
||||
#elif defined(SCPH_xxx2)
|
||||
#pragma message "Target Console: Generic PAL"
|
||||
#pragma message "Target Console: SCPH_xxx2 Generic PAL"
|
||||
#elif defined(SCPH_xxx3)
|
||||
#pragma message "Target Console: Generic NTSC-J"
|
||||
#pragma message "Target Console: SCPH_xxx3 Generic NTSC-J"
|
||||
#elif defined(SCPH_5903)
|
||||
#pragma message "Target Console: SCPH-5903 (Video CD Dual-Interface)"
|
||||
#elif defined(SCPH_xxxx)
|
||||
#pragma message "Target Console: Universal Region Mode"
|
||||
#pragma message "Target Console: SCPH_xxxx Universal Region Mode"
|
||||
#else
|
||||
// Error if no console is uncommented
|
||||
#error "Console not selected! Please uncomment one SCPH model."
|
||||
#endif
|
||||
|
||||
// --- MCU Architecture Info ---
|
||||
#if defined(IS_328_168_FAMILY)
|
||||
#pragma message "Microcontroller: ATmega328/168 (Arduino Nano/Uno)"
|
||||
#elif defined(IS_32U_FAMILY)
|
||||
#pragma message "Microcontroller: ATmega32U4/16U4 (Leonardo/Pro Micro)"
|
||||
#elif defined(IS_ATTINY_FAMILY)
|
||||
#pragma message "Microcontroller: ATtiny85/45/25"
|
||||
// Show detected microcontroller (e.g. __AVR_atmega328p__)
|
||||
#define STRINGIZE(x) #x
|
||||
#define TO_STR(x) STRINGIZE(x)
|
||||
|
||||
#ifdef __AVR_DEVICE_NAME__
|
||||
#pragma message "Microcontroller: __AVR_" TO_STR(__AVR_DEVICE_NAME__) "__"
|
||||
#endif
|
||||
|
||||
// --- RESOURCE CONFLICT CHECK (ATtiny) ---
|
||||
#if defined(IS_ATTINY_FAMILY) && \
|
||||
defined(LED_RUN) && \
|
||||
defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
#error "Resource conflict: LED_RUN and DEBUG_SERIAL are incompatible on ATtiny."
|
||||
#endif
|
||||
|
||||
// --- Feature Status ---
|
||||
@@ -430,7 +391,4 @@ void Debug_Inject(){ // Confirmation of region code injection
|
||||
#pragma message "Feature: Serial Debug Monitor ENABLED"
|
||||
#endif
|
||||
|
||||
#ifdef LED_RUN
|
||||
#pragma message "Feature: Status LED (PB5) ENABLED"
|
||||
>>>>>>> Stashed changes
|
||||
#endif
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 524 KiB After Width: | Height: | Size: 524 KiB |
Reference in New Issue
Block a user