mirror of
https://github.com/kalymos/PsNee.git
synced 2026-05-09 08:37:11 +00:00
Refactor BIOS patching logic and clean up codebase
New 2-phase sync (Stabilization + Silence detection). Refactored GPIO macros for faster execution. Cleaned up SCPH model definitions and fixed backslash warnings. Removed unused global variables to save RAM.
This commit is contained in:
@@ -1,320 +1,152 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#ifdef BIOS_PATCH
|
||||
|
||||
volatile uint8_t pulseCounter = 0;
|
||||
volatile uint8_t patchStep = 0;
|
||||
|
||||
|
||||
#ifdef INTERRUPT_RISING
|
||||
|
||||
ISR(PIN_AX_INTERRUPT_VECTOR) {
|
||||
|
||||
/*
|
||||
* PHASE 3: Pulse Counting (Inside ISR)
|
||||
* The hardware Interrupt Service Routine (ISR) now takes over.
|
||||
* It counts the exact number of incoming pulses on PIN_AX until it
|
||||
* matches the PULSE_COUNT value.
|
||||
*/
|
||||
|
||||
|
||||
//if (--pulseCounter == 0) {
|
||||
pulseCounter++;
|
||||
if (pulseCounter == PULSE_COUNT){ // If pulseCounter reaches the value defined by PULSE_COUNT
|
||||
/*
|
||||
* PHASE 4: Precision Bit Alignment
|
||||
* Once the PULSE_COUNT is reached, a micro-delay (BIT_OFFSET) is applied.
|
||||
* This shifts the timing from the clock edge to the exact bit position
|
||||
* within the data stream that needs modification.
|
||||
*/
|
||||
_delay_us(BIT_OFFSET);
|
||||
/*
|
||||
* PHASE 5: Data Bus Overdrive (The Patch)
|
||||
* Briefly forcing PIN_DX to OUTPUT to pull the line and "nullify" the target bit.
|
||||
* This effectively overwrites the BIOS data on-the-fly
|
||||
* before reverting the pin to INPUT to release the bus.
|
||||
*/
|
||||
PIN_DX_OUTPUT;
|
||||
_delay_us (OVERRIDE);
|
||||
PIN_DX_INPUT;
|
||||
PIN_AX_INTERRUPT_DISABLE;
|
||||
pulseCounter = 0;
|
||||
patchStep = 1; // patchStep is set to 1, indicating that the first patch is completed.
|
||||
}
|
||||
}
|
||||
|
||||
void Bios_Patching(){
|
||||
|
||||
/*
|
||||
* PHASE 1: Signal Stabilization & Alignment
|
||||
* Detects the startup state (Cold Boot vs. Reset).
|
||||
* If the line is already HIGH (Cold Boot), we wait for a full LOW-to-HIGH transition
|
||||
* to ensure we are aligned with the start of a clean clock cycle.
|
||||
*/
|
||||
|
||||
if (PIN_AX_READ != 0) { // Case: Power-on / Line high (---__-_-_)
|
||||
|
||||
while (PIN_AX_READ != 0); // Wait for falling edge
|
||||
while (PIN_AX_READ == 0); // Wait for next rising edge to sync
|
||||
}
|
||||
else { // Case: Reset / Line low (_____-_-_)
|
||||
while (PIN_AX_READ == 0); // Wait for the very first rising edge
|
||||
}
|
||||
/*
|
||||
* PHASE 2: Reaching the Target Memory Window
|
||||
* We introduce a strategic delay (BOOT_OFFSET) to skip initial noise.
|
||||
* This points the execution to a known idle gap in the
|
||||
* address range calls before the critical data appears.
|
||||
* DELAY: |---//-----|
|
||||
* AX: -_-_//-_-_________-_-_-_
|
||||
*/
|
||||
_delay_ms(BOOT_OFFSET);
|
||||
// Armed for hardware detection
|
||||
//pulseCounter = PULSE_COUNT;
|
||||
PIN_AX_INTERRUPT_RISING;
|
||||
PIN_AX_INTERRUPT_ENABLE;
|
||||
while (patchStep != 1); // Wait for the first stage of the patch to complete:
|
||||
PIN_LED_OFF;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef INTERRUPT_FALLING
|
||||
|
||||
ISR(PIN_AX_INTERRUPT_VECTOR) {
|
||||
|
||||
pulseCounter++;
|
||||
if (pulseCounter == PULSE_COUNT){
|
||||
_delay_us (BIT_OFFSET);
|
||||
PIN_DX_OUTPUT;
|
||||
_delay_us (OVERRIDE);
|
||||
PIN_DX_INPUT;
|
||||
|
||||
PIN_AX_INTERRUPT_DISABLE;
|
||||
|
||||
pulseCounter = 0;
|
||||
patchStep = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Bios_Patching(){
|
||||
|
||||
if (PIN_AX_READ != 0) {
|
||||
while (PIN_AX_READ != 0);
|
||||
while (PIN_AX_READ == 0);
|
||||
}
|
||||
else {
|
||||
while (PIN_AX_READ == 0);
|
||||
}
|
||||
|
||||
_delay_ms(BOOT_OFFSET);
|
||||
|
||||
PIN_AX_INTERRUPT_FALLING;
|
||||
PIN_AX_INTERRUPT_ENABLE;
|
||||
|
||||
while (patchStep != 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
ISR(PIN_AX_INTERRUPT_VECTOR) {
|
||||
pulseCounter++;
|
||||
if (pulseCounter == PULSE_COUNT){
|
||||
_delay_us (BIT_OFFSET);
|
||||
PIN_DX_SET;
|
||||
PIN_DX_OUTPUT;
|
||||
_delay_us (OVERRIDE);
|
||||
PIN_DX_CLEAR;
|
||||
PIN_DX_INPUT;
|
||||
PIN_AX_INTERRUPT_DISABLE;
|
||||
pulseCounter = 0;
|
||||
patchStep = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ISR(PIN_AY_INTERRUPT_VECTOR){
|
||||
|
||||
pulseCounter++;
|
||||
|
||||
if (pulseCounter == PULSE_COUNT_2) {
|
||||
_delay_us (BIT_OFFSET_2);
|
||||
PIN_DX_OUTPUT;
|
||||
_delay_us (OVERRIDE_2);
|
||||
PIN_DX_INPUT;
|
||||
PIN_AY_INTERRUPT_DISABLE;
|
||||
patchStep = 2;
|
||||
}
|
||||
}
|
||||
|
||||
void Bios_Patching(){
|
||||
if (PIN_AX_READ != 0) {
|
||||
while (PIN_AX_READ != 0);
|
||||
while (PIN_AX_READ == 0);
|
||||
}
|
||||
else {
|
||||
while (PIN_AX_READ == 0);
|
||||
}
|
||||
|
||||
_delay_ms(BOOT_OFFSET);
|
||||
|
||||
PIN_AX_INTERRUPT_RISING;
|
||||
|
||||
PIN_AX_INTERRUPT_ENABLE;
|
||||
|
||||
while (patchStep != 1);
|
||||
|
||||
while (PIN_AY_READ != 0);
|
||||
|
||||
_delay_ms(FOLLOWUP_OFFSET);
|
||||
|
||||
PIN_AY_INTERRUPT_RISING;
|
||||
PIN_AY_INTERRUPT_ENABLE;
|
||||
while (patchStep != 2);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ======================================================================================
|
||||
* FUNCTION : Bios_Patching()
|
||||
* TARGET : Data Bus (DX) synchronized via Address Bus (AX / AY)
|
||||
*
|
||||
* OPERATIONAL LOGIC:
|
||||
* This function intercepts a specific memory transaction by counting clock cycles
|
||||
* on Address lines (AX/AY) to inject modified data onto the Data line (DX)
|
||||
* in real-time (On-the-fly patching).
|
||||
* Intercepts specific memory transactions by monitoring address lines (AX/AY).
|
||||
* Uses precise pulse counting and timed delays to inject modified data onto
|
||||
* the Data line (DX) in real-time (On-the-fly patching).
|
||||
*
|
||||
* KEY PHASES:
|
||||
* 1. SYNC (AX): Aligns the CPU with the first valid address cycle after boot/reset
|
||||
* to establish a deterministic T0 reference point.
|
||||
* 2. GATING (BOOT_OFFSET): Skips initial BIOS noise/calls to reach the target
|
||||
* memory window.
|
||||
* 3. ADDRESS COUNTING (ISR AX): Hardware-based pulse counting using ultra-fast
|
||||
* decrement-to-zero logic to identify the exact target bit location.
|
||||
* 4. DATA OVERDRIVE (DX): Momentarily forces DX pin to OUTPUT mode to overwrite
|
||||
* the original BIOS bit with a custom logic state.
|
||||
* 5. SEQUENCING (Optional AY): Transitions to a secondary address line (AY) for
|
||||
* multi-stage patching or follow-up verification.
|
||||
* 1. STABILIZATION & ALIGNMENT (AX): Ensures the CPU is synchronized with a
|
||||
* clean rising edge of the AX signal to establish a stable reference point.
|
||||
*
|
||||
* 2. SILENCE DETECTION (GATING): Scans for a specific window of bus inactivity
|
||||
* (SILENCE_THRESHOLD) to identify the correct pre-patching state and
|
||||
* avoid false triggers from boot noise.
|
||||
*
|
||||
* 3. PULSE COUNTING (AX): Implements a high-speed countdown of address pulses.
|
||||
* The code blocks on each edge to maintain cycle-accurate synchronization
|
||||
* with the target memory access.
|
||||
*
|
||||
* 4. DATA OVERDRIVE (DX): At the exact target pulse, triggers a calibrated
|
||||
* delay (BIT_OFFSET) before forcing the DX pin to OUTPUT mode to
|
||||
* overwrite the original BIOS bit for a specific duration (OVERRIDE).
|
||||
*
|
||||
* 5. SECONDARY PATCH (AY): If enabled, repeats the silence detection and
|
||||
* pulse counting logic on a secondary address line (AY) for multi-stage
|
||||
* memory patching.
|
||||
* ======================================================================================
|
||||
*/
|
||||
|
||||
#ifdef BIOS_PATCH_3
|
||||
|
||||
// Shared variables between ISR and main loop
|
||||
volatile uint8_t pulse_counter = 0;
|
||||
volatile uint8_t patch_done = 0;
|
||||
|
||||
|
||||
// --- MAIN INTERRUPT SERVICE ROUTINE (ADDRESS AX) ---
|
||||
ISR(PIN_AX_INTERRUPT_VECTOR) {
|
||||
if (--pulse_counter == 0) {
|
||||
// --- PHASE 4: Precision Bit Alignment ---
|
||||
__builtin_avr_delay_cycles(BIT_OFFSET_CYCLES);
|
||||
|
||||
// --- PHASE 5: Data Bus Overdrive (Patch applied on DX) ---
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
PIN_DX_SET; // Pre-set HIGH if needed for this variant
|
||||
#endif
|
||||
|
||||
PIN_DX_OUTPUT; // Take control of the data bus
|
||||
__builtin_avr_delay_cycles(OVERRIDE_CYCLES);
|
||||
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
PIN_DX_CLEAR; // Release HIGH state
|
||||
#endif
|
||||
|
||||
PIN_DX_INPUT; // Immediately release the data bus
|
||||
PIN_AX_INTERRUPT_DISABLE;
|
||||
PIN_LED_OFF;
|
||||
patch_done = 1; // Signal completion of stage 1
|
||||
}
|
||||
}
|
||||
|
||||
// --- SECONDARY ISR (ADDRESS AY, HIGH_PATCH variant) ---
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
ISR(PIN_AY_INTERRUPT_VECTOR) {
|
||||
if (--pulse_counter == 0) {
|
||||
delay_cycles(BIT_OFFSET_2_CYCLES);
|
||||
PIN_DX_OUTPUT;
|
||||
delay_cycles(OVERRIDE_2_CYCLES);
|
||||
PIN_DX_INPUT;
|
||||
PIN_AY_INTERRUPT_DISABLE;
|
||||
patch_done = 2; // Signal completion of stage 2
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef BIOS_PATCH
|
||||
|
||||
// --- BIOS Patching Main Function ---
|
||||
void Bios_Patching(void) {
|
||||
// --- PHASE 1: Signal Stabilization & Alignment (AX) ---
|
||||
if (PIN_AX_READ != 0) { // Case: Power-on, line is high
|
||||
while (PIN_AX_READ != 0); // Wait for falling edge
|
||||
while (PIN_AX_READ == 0); // Wait for next rising edge to sync
|
||||
} else { // Case: Reset, line is low
|
||||
while (PIN_AX_READ == 0); // Wait for first rising edge
|
||||
}
|
||||
|
||||
//--- PHASE 2: Reaching the Target Memory Window ---
|
||||
//_delay_ms(BOOT_OFFSET_MS);
|
||||
uint8_t pulse_counter = 0;
|
||||
uint8_t current_confirms = 0;
|
||||
|
||||
// --- PHASE 2: Reaching the Target Memory Window (Silence Detection) ---
|
||||
// Replaces the fixed _delay_ms(BOOT_OFFSET_MS)
|
||||
PIN_AX_INPUT;
|
||||
// --- PHASE 1: Signal Stabilization & Alignment (AX) ---
|
||||
if (PIN_AX_READ != 0) {
|
||||
while WAIT_AX_FALLING; // Wait for falling edge
|
||||
while WAIT_AX_RISING; // Wait for next rising edge to sync
|
||||
} else {
|
||||
while WAIT_AX_RISING; // Wait for first rising edge
|
||||
}
|
||||
|
||||
uint8_t current_confirms = 0;
|
||||
// --- PHASE 2: Silence Detection (AX) ---
|
||||
|
||||
while (current_confirms < CONFIRM_COUNTER_TARGET) {
|
||||
uint16_t count = SILENCE_THRESHOLD;
|
||||
while (current_confirms < CONFIRM_COUNTER_TARGET) {
|
||||
uint16_t count = SILENCE_THRESHOLD;
|
||||
|
||||
// --- Scan for ONE continuous block of silence ---
|
||||
while (count > 0) {
|
||||
if (PIN_AX_READ != 0) {
|
||||
while WAIT_AX_FALLING; // Pulse detected: wait for bus to clear
|
||||
break; // Reset and try a new silence block
|
||||
}
|
||||
count--;
|
||||
}
|
||||
|
||||
// If count reaches 0, a silent block is validated
|
||||
if (count == 0) {
|
||||
current_confirms++;
|
||||
}
|
||||
}
|
||||
|
||||
PIN_LED_ON;
|
||||
|
||||
// --- PHASE 3: Pulse Counting & Patch 1 (AX) ---
|
||||
pulse_counter = PULSE_COUNT;
|
||||
|
||||
|
||||
while (pulse_counter > 0) {
|
||||
while WAIT_AX_RISING; // Block here until rising edge
|
||||
|
||||
// --- Attempt to find ONE block of silence ---
|
||||
while (count > 0) {
|
||||
if (PIN_AX_READ != 0) {
|
||||
// Activity detected: current block is invalid
|
||||
// Wait for bus to clear before trying a NEW block
|
||||
while (PIN_AX_READ != 0);
|
||||
break;
|
||||
pulse_counter--;
|
||||
|
||||
if (pulse_counter == 0) {
|
||||
// Precise cycle-accurate delay before triggering
|
||||
__builtin_avr_delay_cycles(BIT_OFFSET_CYCLES);
|
||||
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
PIN_DX_SET;
|
||||
#endif
|
||||
|
||||
PIN_DX_OUTPUT; // Pull the line (Override start)
|
||||
__builtin_avr_delay_cycles(OVERRIDE_CYCLES);
|
||||
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
PIN_DX_CLEAR; // Release the bus (Override end)
|
||||
#endif
|
||||
|
||||
PIN_DX_INPUT;
|
||||
|
||||
PIN_LED_OFF;
|
||||
break;
|
||||
}
|
||||
|
||||
while WAIT_AX_FALLING; // Wait for pulse to clear
|
||||
}
|
||||
|
||||
//PIN_LED_OFF;
|
||||
// -------- Secondary Patch ----------
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
|
||||
current_confirms = 0;
|
||||
while (current_confirms < CONFIRM_COUNTER_TARGET_2) {
|
||||
uint16_t count = SILENCE_THRESHOLD;
|
||||
|
||||
while (count > 0) {
|
||||
if (PIN_AX_READ != 0) {
|
||||
|
||||
while WAIT_AX_FALLING;
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
current_confirms++;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
|
||||
// If count reached 0, we found 500us of silence
|
||||
if (count == 0) {
|
||||
current_confirms++;
|
||||
} else {
|
||||
PIN_LED_ON;
|
||||
pulse_counter = PULSE_COUNT_2;
|
||||
|
||||
}
|
||||
}
|
||||
while (pulse_counter > 0) {
|
||||
while WAIT_AY_RISING;
|
||||
|
||||
pulse_counter--;
|
||||
|
||||
PIN_LED_ON;
|
||||
if (pulse_counter == 0) {
|
||||
__builtin_avr_delay_cycles(BIT_OFFSET_2_CYCLES);
|
||||
|
||||
|
||||
PIN_DX_OUTPUT;
|
||||
__builtin_avr_delay_cycles(OVERRIDE_2_CYCLES);
|
||||
PIN_DX_INPUT;
|
||||
|
||||
PIN_LED_OFF;
|
||||
break;
|
||||
}
|
||||
while WAIT_AY_FALLING;
|
||||
|
||||
// --- Prepare pulse counter and patch status flag ---
|
||||
pulse_counter = PULSE_COUNT;
|
||||
patch_done = 0;
|
||||
|
||||
// --- Dynamic interrupt configuration ---
|
||||
#if defined(INTERRUPT_RISING) || defined(INTERRUPT_RISING_HIGH_PATCH)
|
||||
PIN_AX_INTERRUPT_RISING;
|
||||
#elif defined(INTERRUPT_FALLING)
|
||||
PIN_AX_INTERRUPT_FALLING;
|
||||
#endif
|
||||
|
||||
PIN_AX_INTERRUPT_ENABLE;
|
||||
while (patch_done != 1); // Wait until stage 1 is completed
|
||||
|
||||
// --- Optional secondary patch phase for HIGH_PATCH ---
|
||||
#ifdef INTERRUPT_RISING_HIGH_PATCH
|
||||
while (PIN_AY_READ != 0); // Ensure AY line is low before arming
|
||||
_delay_ms(FOLLOWUP_OFFSET_MS);
|
||||
|
||||
pulse_counter = PULSE_COUNT_2; // Reload counter for AY pulses
|
||||
PIN_AY_INTERRUPT_RISING;
|
||||
PIN_AY_INTERRUPT_ENABLE;
|
||||
while (patch_done != 2); // Wait until stage 2 is completed
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
78
PSNee/MCU.h
78
PSNee/MCU.h
@@ -227,30 +227,38 @@
|
||||
#ifdef ATmega328_168
|
||||
|
||||
static inline void optimizePeripherals(void) {
|
||||
// --- Port C & Digital Input Configuration (A0-A5) ---
|
||||
// 1. Set Port C as inputs (DDRC bits 0-5 to 0)
|
||||
DDRC &= ~((1<<DDC5)|(1<<DDC4)|(1<<DDC3)|(1<<DDC2)|(1<<DDC1)|(1<<DDC0));
|
||||
// 2. Enable Digital Input Buffers by clearing DIDR0 (Required for digital PINC reads)
|
||||
DIDR0 &= ~((1<<ADC5D)|(1<<ADC4D)|(1<<ADC3D)|(1<<ADC2D)|(1<<ADC1D)|(1<<ADC0D));
|
||||
// 1. Disable Interrupts during setup
|
||||
cli();
|
||||
|
||||
// --- Analog Modules Shutdown (Power Saving & Noise Reduction) ---
|
||||
// 1. Disable the ADC module (ADEN = 0)
|
||||
ADCSRA &= ~(1 << ADEN);
|
||||
// 2. Disable the Analog Comparator (ACD = 1) to free resources on PD6/PD7
|
||||
ACSR |= (1 << ACD);
|
||||
// 2. Analog Modules Shutdown (Critical for Power)
|
||||
ADCSRA &= ~(1 << ADEN); // Disable ADC
|
||||
ACSR |= (1 << ACD); // Disable Analog Comparator
|
||||
|
||||
// --- Power Reduction Register (Hard Clock Shut Off) ---
|
||||
// Stops the clock to internal modules: ADC, Timer 0 (millis), and Timer 2
|
||||
PRR |= (1 << PRADC) | (1 << PRTIM0) | (1 << PRTIM2);
|
||||
// 3. Digital Input Disable (Set bits to 1 to DISABLE)
|
||||
// Disconnects digital buffers on analog pins to stop leakage
|
||||
DIDR0 = 0x3F; // Pins A0 to A5
|
||||
|
||||
// --- Timer 0 Specific Shutdown ---
|
||||
// Double security: disconnect clock source and disable interrupts
|
||||
// 4. GPIO Strategy (Unused pins to Pull-up)
|
||||
// PORTx = 0xFF (Pull-ups) | DDRx = 0x00 (Inputs)
|
||||
PORTC |= 0xFF;
|
||||
|
||||
// 5. Power Reduction Register (PRR)
|
||||
// We KEEP PRUSART0 (UART) and shut down EVERYTHING else.
|
||||
// _delay_ms() will still work (it's cycle-based, not timer-based).
|
||||
PRR = (1 << PRTWI) | // I2C Off
|
||||
(1 << PRSPI) | // SPI Off
|
||||
(1 << PRTIM0) | // Timer 0 Off (millis/delay Arduino Off)
|
||||
(1 << PRTIM1) | // Timer 1 Off
|
||||
(1 << PRTIM2) | // Timer 2 Off
|
||||
(1 << PRADC); // ADC Clock Off
|
||||
|
||||
// 6. Double Security for Timer 0
|
||||
TCCR0B = 0;
|
||||
TIMSK0 = 0;
|
||||
}
|
||||
|
||||
// Define the clock speed for the microcontroller
|
||||
//#define F_CPU 16000000L
|
||||
// 7. Restart interrupts if UART uses them (RX/TX ISR)
|
||||
sei();
|
||||
}
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@@ -259,12 +267,6 @@
|
||||
#include <avr/sfr_defs.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
// Global interrupt control settings
|
||||
#define GLOBAL_INTERRUPT_ENABLE sei()
|
||||
#define GLOBAL_INTERRUPT_DISABLE cli()
|
||||
// #define GLOBAL_INTERRUPT_ENABLE SREG |= (1 << 7) // Set the I-bit (bit 7) in the Status Register to enable global interrupts
|
||||
// #define GLOBAL_INTERRUPT_DISABLE SREG &= ~(1 << 7) // Clear the I-bit (bit 7) in the Status Register to disable global interrupts
|
||||
|
||||
// Main pin configuration
|
||||
|
||||
// Define the main pins as inputs
|
||||
@@ -297,10 +299,7 @@
|
||||
#endif
|
||||
|
||||
// Handling the BIOS patch
|
||||
#if defined(SCPH_102) || defined(SCPH_100) || defined(SCPH_7500_9000) || defined(SCPH_7000) || defined(SCPH_5500) || defined(SCPH_5000) || defined(SCPH_3500) || defined(SCPH_3000) || defined(SCPH_1000)
|
||||
|
||||
// Clear the timer interrupt flag
|
||||
//#define TIMER_TIFR_CLEAR TIFR0 |= (1 << OCF0A) // Clear the Timer0 Compare Match A interrupt flag
|
||||
#if defined(SCPH_102) || defined(SCPH_100) || defined(SCPH_7500_9000) || defined(SCPH_7000) || defined(SCPH_5000_5500) || defined(SCPH_3500) || defined(SCPH_3000) || defined(SCPH_1000)
|
||||
|
||||
// Define input pins for the BIOS patch
|
||||
#define PIN_AX_INPUT DDRD &= ~(1 << DDD2) // Set DDRD register to configure PIND2 as input
|
||||
@@ -315,28 +314,19 @@
|
||||
// Set pull-ups low on output pins
|
||||
#define PIN_DX_CLEAR PORTD &= ~(1 << PD4) // Set PORTD register to make PIND4 low
|
||||
|
||||
|
||||
#define WAIT_AX_RISING (!(PIND & (1 << PIND2))) // Attend le début de l'impulsion
|
||||
#define WAIT_AX_FALLING (PIND & (1 << PIND2)) // Attend la fin de l'impulsion
|
||||
|
||||
// Read the input pins for the BIOS patch
|
||||
#define PIN_AX_READ (!!(PIND & (1 << PIND2))) // Read the state of PIND2
|
||||
|
||||
// External interrupt configuration for BIOS patch
|
||||
#define PIN_AX_INTERRUPT_ENABLE EIMSK |= (1 << INT0) // Enable external interrupt on INT0 (PINB2)
|
||||
#define PIN_AX_INTERRUPT_DISABLE EIMSK &= ~(1 << INT0) // Disable external interrupt on INT0
|
||||
#define PIN_AX_INTERRUPT_RISING EICRA |= (1 << ISC01) | (1 << ISC00) // Configure INT0 for rising edge trigger
|
||||
//#define PIN_AX_INTERRUPT_FALLING (EICRA = (1 << ISC01))
|
||||
#define PIN_AX_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC00)) | (1 << ISC01)) // Configure INT0 for falling edge trigger
|
||||
|
||||
// Interrupt vectors for external interrupts
|
||||
#define PIN_AX_INTERRUPT_VECTOR INT0_vect // Interrupt vector for INT0 (external interrupt)
|
||||
|
||||
// Defin PIN_AY for HIGH_PATCH
|
||||
#if defined(SCPH_3000) || defined(SCPH_1000)
|
||||
#define PIN_AY_INPUT DDRD &= ~(1 << DDD3) // Set DDRD register to configure PIND3 as input
|
||||
#define PIN_AY_READ (!!(PIND & (1 << PIND3))) // Read the state of PIND3
|
||||
#define PIN_AY_INTERRUPT_ENABLE EIMSK |= (1 << INT1) // Enable external interrupt on INT1 (PINB3)
|
||||
#define PIN_AY_INTERRUPT_DISABLE EIMSK &= ~(1 << INT1) // Disable external interrupt on INT1
|
||||
#define PIN_AY_INTERRUPT_RISING EICRA |= (1 << ISC11) | (1 << ISC10) // Configure INT1 for rising edge trigger
|
||||
#define PIN_AY_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC10)) | (1 << ISC11)) // Configure INT1 for falling edge trigger
|
||||
#define PIN_AY_INTERRUPT_VECTOR INT1_vect // Interrupt vector for INT1 (external interrupt)
|
||||
#define WAIT_AY_RISING (!(PIND & (1 << PIND3))) // AY est sur PIND3
|
||||
#define WAIT_AY_FALLING (PIND & (1 << PIND3))
|
||||
|
||||
#endif
|
||||
// Handle switch input for BIOS patch
|
||||
#if defined(SCPH_7000)
|
||||
|
||||
319
PSNee/PSNee.ino
319
PSNee/PSNee.ino
@@ -6,7 +6,7 @@
|
||||
|
||||
// MCU // Arduino
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//#define ATmega328_168 // Nano, Pro Mini, Uno
|
||||
#define ATmega328_168 // Nano, Pro Mini, Uno
|
||||
//#define ATmega32U4_16U4 // Micro, Pro Micro
|
||||
//#define ATtiny85_45_25 // ATtiny
|
||||
|
||||
@@ -47,9 +47,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
//#define SCPH_100 // DX - D0 | AX - A7 | | 4.3j - CRC F2AF798B
|
||||
//#define SCPH_7500_9000 // DX - D0 | AX - A7 | | 4.0j - CRC EC541CD0
|
||||
//#define SCPH_7000 // DX - D0 | AX - A7 | | 4.0j - CRC EC541CD0 Enables hardware support for disabling BIOS patching.
|
||||
//#define SCPH_5500 // DX - D0 | AX - A5 | | 3.0j - CRC FF3EEB8C
|
||||
//#define SCPH_5000 // DX - D0 | AX - A5 | AX - A4 | 2.2j - CRC 24FC7E17
|
||||
//#define SCPH_3500 // DX - D0 | AX - A5 | AX - A4 | 2.1j - CRC BC190209
|
||||
//#define SCPH_5000_5500 // DX - D0 | AX - A15 | | 3.0j - CRC FF3EEB8C, 2.2j - CRC 24FC7E17
|
||||
//#define SCPH_3500 // DX - D0 | AX - A15 | AX - A15 | 2.1j - CRC BC190209
|
||||
//#define SCPH_3000 // DX - D5 | AX - A7, AY - A8 | AX - A6, AY - A7 | 1.1j - CRC 3539DEF6
|
||||
//#define SCPH_1000 // DX - D5 | AX - A7, AY - A8 | AX - A6, AY - A7 | 1.0j - CRC 3B601FC8
|
||||
|
||||
@@ -130,28 +129,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
//Flag initializing for automatic console generation selection 0 = old, 1 = pu-22 end ++
|
||||
volatile uint8_t wfck_mode = 0;
|
||||
|
||||
|
||||
// --- Prototypes (Forward declarations) ---
|
||||
// These tell the compiler that the functions exist later in the code.
|
||||
|
||||
|
||||
// Function pointer type definition for the console detection logic.
|
||||
// This allows switching between 'Standard' and 'SCPH-5903' heuristics dynamically.
|
||||
// Définition du type de pointeur de fonction pour la logique de console
|
||||
typedef void (*ConsoleLogicPtr)(uint8_t isDataSector);
|
||||
|
||||
// Déclarations forward des deux fonctions
|
||||
void processStandardLogic(uint8_t isDataSector);
|
||||
void processScph5903Logic(uint8_t isDataSector);
|
||||
|
||||
// Pointeur global vers la fonction active
|
||||
#ifdef SCPH_5903
|
||||
volatile ConsoleLogicPtr currentLogic = processScph5903Logic;
|
||||
#else
|
||||
volatile ConsoleLogicPtr currentLogic = processStandardLogic;
|
||||
#endif
|
||||
|
||||
|
||||
// Variables de contrôle globales
|
||||
// Global buffer to store the 12-byte Sub-Q channel data
|
||||
uint8_t subqBuffer[12];
|
||||
@@ -225,16 +202,11 @@ void board_detection() {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
Debug_Log(wfck_mode);
|
||||
#endif
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
Debug_Log(wfck_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//******************************************************************************************************************
|
||||
// Reads a complete 12-byte SUBQ transmission from the CD drive.
|
||||
// Uses clock-edge synchronization and includes a safety timeout for malformatted streams.
|
||||
@@ -265,9 +237,9 @@ void captureSubQ(void) {
|
||||
*bufferPtr++ = currentByte;
|
||||
} while (--bytesRemaining); // Faster than (bytesRemaining < 12)
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
logSubQ(subqBuffer);
|
||||
#endif
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
logSubQ(subqBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************************
|
||||
@@ -282,8 +254,9 @@ void captureSubQ(void) {
|
||||
* isDataSector Boolean flag indicating if the current sector contains data.
|
||||
|
||||
**************************************************************************************/
|
||||
#ifdef SCPH_5903
|
||||
|
||||
void processScph5903Logic(uint8_t isDataSector) {
|
||||
void processLogic(uint8_t isDataSector) {
|
||||
uint8_t currentHysteresis = hysteresis;
|
||||
|
||||
// Fast filtering: most sectors fail here by checking sync markers (index 1 and 6)
|
||||
@@ -310,8 +283,8 @@ void processScph5903Logic(uint8_t isDataSector) {
|
||||
if (currentHysteresis > 0) {
|
||||
hysteresis = currentHysteresis - 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
/******************************************************************************************
|
||||
* Heuristic logic for standard PlayStation hardware (Non-VCD models).
|
||||
*
|
||||
@@ -325,7 +298,8 @@ void processScph5903Logic(uint8_t isDataSector) {
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
void processStandardLogic(uint8_t isDataSector) {
|
||||
|
||||
void processLogic(uint8_t isDataSector) {
|
||||
uint8_t currentHysteresis = hysteresis;
|
||||
|
||||
// Fast filtering: most sectors fail here by checking sync markers (index 1 and 6)
|
||||
@@ -357,7 +331,9 @@ void processStandardLogic(uint8_t isDataSector) {
|
||||
if (currentHysteresis > 0) {
|
||||
hysteresis = currentHysteresis - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*********************************************************************************************
|
||||
* Executes the SCEx injection sequence to bypass the CD-ROM regional lockout.
|
||||
@@ -374,168 +350,159 @@ void processStandardLogic(uint8_t isDataSector) {
|
||||
*********************************************************************************************/
|
||||
|
||||
void performInjectionSequence(uint8_t injectSCEx) {
|
||||
/*
|
||||
Security strings (44-bit SCEx) for the three main regions:
|
||||
0: NTSC-J (SCEI - Sony Computer Entertainment Inc.)
|
||||
1: NTSC-U/C (SCEA - Sony Computer Entertainment America)
|
||||
2: PAL (SCEE - Sony Computer Entertainment Europe)
|
||||
Stored in 6 bytes (48 bits); only the first 44 bits are used during injection.
|
||||
*/
|
||||
static const uint8_t allRegionsSCEx[3][6] = {
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xDA, 0x02 }, // SCEI
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xFA, 0x02 }, // SCEA
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xEA, 0x02 } // SCEE
|
||||
};
|
||||
/*
|
||||
Security strings (44-bit SCEx) for the three main regions:
|
||||
0: NTSC-J (SCEI - Sony Computer Entertainment Inc.)
|
||||
1: NTSC-U/C (SCEA - Sony Computer Entertainment America)
|
||||
2: PAL (SCEE - Sony Computer Entertainment Europe)
|
||||
Stored in 6 bytes (48 bits); only the first 44 bits are used during injection.
|
||||
*/
|
||||
static const uint8_t allRegionsSCEx[3][6] = {
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xDA, 0x02 }, // SCEI
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xFA, 0x02 }, // SCEA
|
||||
{ 0x59, 0xC9, 0x4B, 0x5D, 0xEA, 0x02 } // SCEE
|
||||
};
|
||||
|
||||
|
||||
hysteresis = 11; // Reset hysteresis to mid-point after triggering
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_ON;
|
||||
#endif
|
||||
hysteresis = 11; // Reset hysteresis to mid-point after triggering
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_ON;
|
||||
#endif
|
||||
|
||||
// Cache wfck_mode to save CPU cycles during the bit loop
|
||||
uint8_t isWfck = wfck_mode;
|
||||
// Cache wfck_mode to save CPU cycles during the bit loop
|
||||
uint8_t isWfck = wfck_mode;
|
||||
PIN_DATA_OUTPUT;
|
||||
PIN_DATA_CLEAR;
|
||||
|
||||
// Legacy boards require the chip to drive the simulated WFCK/Gate
|
||||
if (!isWfck) {
|
||||
PIN_WFCK_OUTPUT;
|
||||
PIN_WFCK_CLEAR;
|
||||
}
|
||||
|
||||
_delay_ms(DELAY_BETWEEN_INJECTIONS);
|
||||
|
||||
// Loop through the selected region(s)
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
uint8_t regionIndex = (injectSCEx == 3) ? i : injectSCEx;
|
||||
const uint8_t* bytePtr = allRegionsSCEx[regionIndex];
|
||||
|
||||
uint8_t currentByte = *bytePtr++;
|
||||
uint8_t bitIdx = 0;
|
||||
|
||||
// Process the 44-bit SCEx stream
|
||||
for (uint8_t totalBits = 44; totalBits > 0; totalBits--) {
|
||||
uint8_t currentBit = currentByte & 0x01;
|
||||
currentByte >>= 1;
|
||||
bitIdx++;
|
||||
|
||||
// Reload next byte every 8 bits (except the last partial one)
|
||||
if (bitIdx == 8 && totalBits > 4) {
|
||||
currentByte = *bytePtr++;
|
||||
bitIdx = 0;
|
||||
}
|
||||
|
||||
if (currentBit == 0) {
|
||||
// BIT 0: Pull DATA low-
|
||||
PIN_DATA_CLEAR;
|
||||
if (!isWfck) PIN_DATA_OUTPUT;
|
||||
_delay_us(DELAY_BETWEEN_BITS);
|
||||
} else {
|
||||
// BIT 1: Handle based on board generation
|
||||
if (!isWfck) {
|
||||
// Legacy Mode: Set DATA to High-Z (floating)
|
||||
PIN_DATA_INPUT;
|
||||
_delay_us(DELAY_BETWEEN_BITS);
|
||||
} else {
|
||||
/*
|
||||
WFCK Modulation Loop: Syncs to 7.3kHz or 14.6kHz.
|
||||
Follows hardware edges to stay bit-perfect with the console.
|
||||
*/
|
||||
uint8_t count = 30;
|
||||
while (count--) {
|
||||
while (PIN_WFCK_READ); // Wait for Falling Edge
|
||||
PIN_DATA_CLEAR;
|
||||
while (!PIN_WFCK_READ); // Wait for Rising Edge
|
||||
PIN_DATA_SET;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up state between region cycles
|
||||
PIN_DATA_OUTPUT;
|
||||
PIN_DATA_CLEAR;
|
||||
|
||||
// Legacy boards require the chip to drive the simulated WFCK/Gate
|
||||
if (!isWfck) {
|
||||
PIN_WFCK_OUTPUT;
|
||||
PIN_WFCK_CLEAR;
|
||||
}
|
||||
|
||||
_delay_ms(DELAY_BETWEEN_INJECTIONS);
|
||||
|
||||
// Loop through the selected region(s)
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
uint8_t regionIndex = (injectSCEx == 3) ? i : injectSCEx;
|
||||
const uint8_t* bytePtr = allRegionsSCEx[regionIndex];
|
||||
|
||||
uint8_t currentByte = *bytePtr++;
|
||||
uint8_t bitIdx = 0;
|
||||
/*
|
||||
EXIT CONDITION:
|
||||
If we are NOT in Universal mode (3), we stop after the first
|
||||
successful region injection.
|
||||
*/
|
||||
if (injectSCEx != 3) break;
|
||||
}
|
||||
|
||||
// Process the 44-bit SCEx stream
|
||||
for (uint8_t totalBits = 44; totalBits > 0; totalBits--) {
|
||||
uint8_t currentBit = currentByte & 0x01;
|
||||
currentByte >>= 1;
|
||||
bitIdx++;
|
||||
// Restore pins to Input/High-Z to avoid signal interference after injection
|
||||
if (!isWfck) {
|
||||
PIN_WFCK_INPUT;
|
||||
PIN_DATA_INPUT;
|
||||
}
|
||||
|
||||
// Reload next byte every 8 bits (except the last partial one)
|
||||
if (bitIdx == 8 && totalBits > 4) {
|
||||
currentByte = *bytePtr++;
|
||||
bitIdx = 0;
|
||||
}
|
||||
|
||||
if (currentBit == 0) {
|
||||
// BIT 0: Pull DATA low-
|
||||
PIN_DATA_CLEAR;
|
||||
if (!isWfck) PIN_DATA_OUTPUT;
|
||||
_delay_us(DELAY_BETWEEN_BITS);
|
||||
} else {
|
||||
// BIT 1: Handle based on board generation
|
||||
if (!isWfck) {
|
||||
// Legacy Mode: Set DATA to High-Z (floating)
|
||||
PIN_DATA_INPUT;
|
||||
_delay_us(DELAY_BETWEEN_BITS);
|
||||
} else {
|
||||
/*
|
||||
WFCK Modulation Loop: Syncs to 7.3kHz or 14.6kHz.
|
||||
Follows hardware edges to stay bit-perfect with the console.
|
||||
*/
|
||||
uint8_t count = 30;
|
||||
while (count--) {
|
||||
while (PIN_WFCK_READ); // Wait for Falling Edge
|
||||
PIN_DATA_CLEAR;
|
||||
while (!PIN_WFCK_READ); // Wait for Rising Edge
|
||||
PIN_DATA_SET;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up state between region cycles
|
||||
PIN_DATA_OUTPUT;
|
||||
PIN_DATA_CLEAR;
|
||||
_delay_ms(DELAY_BETWEEN_INJECTIONS);
|
||||
|
||||
/*
|
||||
EXIT CONDITION:
|
||||
If we are NOT in Universal mode (3), we stop after the first
|
||||
successful region injection.
|
||||
*/
|
||||
if (injectSCEx != 3) break;
|
||||
}
|
||||
|
||||
// Restore pins to Input/High-Z to avoid signal interference after injection
|
||||
if (!isWfck) {
|
||||
PIN_WFCK_INPUT;
|
||||
PIN_DATA_INPUT;
|
||||
}
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_OFF;
|
||||
#endif
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_OFF;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
Debug_Inject();
|
||||
#endif
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
|
||||
Debug_Inject();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Init() {
|
||||
|
||||
#if defined(ATmega328_168)
|
||||
optimizePeripherals();
|
||||
#endif
|
||||
#if defined(ATmega328_168)
|
||||
optimizePeripherals();
|
||||
#endif
|
||||
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_OUTPUT;
|
||||
#endif
|
||||
#ifdef LED_RUN
|
||||
PIN_LED_OUTPUT;
|
||||
#endif
|
||||
|
||||
#ifdef BIOS_PATCH_3
|
||||
uint8_t skipPatch = 0;
|
||||
GLOBAL_INTERRUPT_ENABLE;
|
||||
#ifdef BIOS_PATCH
|
||||
//uint8_t skipPatch = 0;
|
||||
|
||||
#ifdef SCPH_7000
|
||||
// Check hardware switch for SCPH-7000 models
|
||||
PIN_SWITCH_INPUT;
|
||||
PIN_SWITCH_SET;
|
||||
if (PIN_SWITCH_READ == 0){
|
||||
skipPatch =1; // Disable patching if switch is triggered
|
||||
}
|
||||
#endif
|
||||
// #ifdef SCPH_7000
|
||||
// // Check hardware switch for SCPH-7000 models
|
||||
// PIN_SWITCH_INPUT;
|
||||
// PIN_SWITCH_SET;
|
||||
// if (PIN_SWITCH_READ == 0){
|
||||
// skipPatch =1; // Disable patching if switch is triggered
|
||||
// }
|
||||
// #endif
|
||||
|
||||
// #ifdef LED_RUN
|
||||
// PIN_LED_ON;
|
||||
// #endif
|
||||
|
||||
// Execute BIOS patching unless bypassed by switch
|
||||
if (skipPatch == 0) {
|
||||
// if (skipPatch == 0) {
|
||||
Bios_Patching();
|
||||
}
|
||||
// }
|
||||
|
||||
// #ifdef LED_RUN
|
||||
// PIN_LED_OFF;
|
||||
// #endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// Disable interrupts and set CD-ROM interface pins to Input
|
||||
GLOBAL_INTERRUPT_DISABLE;
|
||||
PIN_SQCK_INPUT;
|
||||
PIN_SUBQ_INPUT;
|
||||
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR) && defined(ATtiny85_45_25)
|
||||
//pinMode(debugtx, OUTPUT); // software serial tx pin
|
||||
mySerial.begin(115200); // 13,82 bytes in 12ms, max for softwareserial. (expected data: ~13 bytes / 12ms) // update: this is actually quicker
|
||||
#elif defined(PSNEE_DEBUG_SERIAL_MONITOR) && !defined(ATtiny85_45_25)
|
||||
Serial.begin(500000); // 60 bytes in 12ms (expected data: ~26 bytes / 12ms) // update: this is actually quicker
|
||||
#endif
|
||||
#if defined(PSNEE_DEBUG_SERIAL_MONITOR) && defined(ATtiny85_45_25)
|
||||
//pinMode(debugtx, OUTPUT); // software serial tx pin
|
||||
mySerial.begin(115200); // 13,82 bytes in 12ms, max for softwareserial. (expected data: ~13 bytes / 12ms) // update: this is actually quicker
|
||||
#elif defined(PSNEE_DEBUG_SERIAL_MONITOR) && !defined(ATtiny85_45_25)
|
||||
Serial.begin(500000); // 60 bytes in 12ms (expected data: ~26 bytes / 12ms) // update: this is actually quicker
|
||||
#endif
|
||||
|
||||
// Detect board generation (PU-7 to PU-22+) before starting the main loop
|
||||
board_detection();
|
||||
@@ -545,12 +512,6 @@ int main() {
|
||||
|
||||
Init();
|
||||
|
||||
// #ifdef SCPH_5903
|
||||
// currentLogic = logic_SCPH_5903;
|
||||
// #else
|
||||
// currentLogic = logic_Standard;
|
||||
// #endif
|
||||
|
||||
|
||||
while (1) {
|
||||
|
||||
@@ -569,8 +530,8 @@ int main() {
|
||||
uint8_t isDataSector = ((subqBuffer[0] & 0xD0) == 0x40);
|
||||
|
||||
|
||||
// Execute selected logic through function pointer
|
||||
currentLogic(isDataSector);
|
||||
// Execute selected logic
|
||||
processLogic(isDataSector);
|
||||
|
||||
//Trigger SCEx injection once the confidence threshold is reached
|
||||
if (hysteresis >= HYSTERESIS_MAX) {
|
||||
|
||||
426
PSNee/settings.h
426
PSNee/settings.h
@@ -7,12 +7,6 @@
|
||||
The temporal precision of _delay_us depends on the microcontroller's clock frequency (F_CPU).
|
||||
For the ATmega328 operating at a typical frequency of 16 MHz, here are some details on the precision.
|
||||
|
||||
Clock Frequency: F_CPU must be defined correctly before using the function. For an ATmega328 operating at 16 MHz:
|
||||
1 clock cycle = 1 / 16,000,000 s ≈ 62.5 ns
|
||||
1 µs ≈ 16 clock cycles
|
||||
|
||||
BIT_OFFSET _delay_us(2.75) = 44 clock cycles
|
||||
OVERRIDE _delay_us(0.2) = 3,2 clock cycles
|
||||
|
||||
*/
|
||||
|
||||
@@ -23,304 +17,138 @@
|
||||
|
||||
// tested with an Atmega328P
|
||||
|
||||
#ifdef SCPH_102
|
||||
#define BIOS_PATCH_2
|
||||
#define INTERRUPT_RISING
|
||||
#define BOOT_OFFSET 83.9
|
||||
#define PULSE_COUNT 48
|
||||
//#define BIT_OFFSET 2.75
|
||||
#define BIT_OFFSET 3.25 //BIOS_PATCH_2
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
|
||||
// #ifdef SCPH_100
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_RISING
|
||||
// #define BOOT_OFFSET 83.9 //83.72 - 84.15
|
||||
// #define PULSE_COUNT 48
|
||||
// #define BIT_OFFSET 2.75 //2.63 - 2.87
|
||||
// #define OVERRIDE 0.2
|
||||
// #endif
|
||||
|
||||
// #ifdef SCPH_7500_9000
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_RISING
|
||||
// #define BOOT_OFFSET 75.2 //74.95 - 75.55
|
||||
// #define PULSE_COUNT 16
|
||||
// #define BIT_OFFSET 2.8
|
||||
// #define OVERRIDE 0.2
|
||||
// #endif
|
||||
|
||||
#ifdef SCPH_7000
|
||||
#define BIOS_PATCH
|
||||
#define INTERRUPT_RISING
|
||||
#define BOOT_OFFSET 75.2 //75.3
|
||||
#define PULSE_COUNT 16
|
||||
#define BIT_OFFSET 2.8
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_5500
|
||||
#define BIOS_PATCH
|
||||
#define INTERRUPT_FALLING
|
||||
#define BOOT_OFFSET 76.04 //75.99 - 76.14
|
||||
#define PULSE_COUNT 21
|
||||
#define BIT_OFFSET 2.8
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_5000
|
||||
#define BIOS_PATCH
|
||||
#define INTERRUPT_FALLING
|
||||
#define BOOT_OFFSET 75.2 //75.12 - 75.27
|
||||
#define PULSE_COUNT 21
|
||||
#define BIT_OFFSET 2.8 //2.7 - 2.85
|
||||
#define OVERRIDE 0.1
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_3500
|
||||
#define BIOS_PATCH
|
||||
#define INTERRUPT_FALLING
|
||||
#define BOOT_OFFSET 75.2 //75.12 - 75.27
|
||||
#define PULSE_COUNT 21
|
||||
#define BIT_OFFSET 2.75 //2.65 - 2.85
|
||||
#define OVERRIDE 0.2
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_3000
|
||||
#define BIOS_PATCH
|
||||
#define INTERRUPT_RISING_HIGH_PATCH
|
||||
#define BOOT_OFFSET 82.9 //82.65 - 83.26
|
||||
#define PULSE_COUNT 60
|
||||
#define BIT_OFFSET 2.7 //2.58 - 2.8
|
||||
#define OVERRIDE 0.15
|
||||
#define HIGH_PATCH
|
||||
#define FOLLOWUP_OFFSET 253.3
|
||||
#define PULSE_COUNT_2 43
|
||||
#define BIT_OFFSET_2 2.88
|
||||
#define OVERRIDE_2 0.15
|
||||
#endif
|
||||
|
||||
#ifdef SCPH_1000
|
||||
#define BIOS_PATCH
|
||||
#define INTERRUPT_RISING_HIGH_PATCH
|
||||
#define BOOT_OFFSET 82.9 // 82.63 - 83.26
|
||||
#define PULSE_COUNT 92
|
||||
#define BIT_OFFSET 2.65 // 2.58 - 2.75
|
||||
#define OVERRIDE 0.15
|
||||
#define HIGH_PATCH
|
||||
#define FOLLOWUP_OFFSET 272.8
|
||||
#define PULSE_COUNT_2 71
|
||||
#define BIT_OFFSET_2 2.88
|
||||
#define OVERRIDE_2 0.15
|
||||
#endif
|
||||
|
||||
|
||||
// // -------- SCPH 102 --------
|
||||
// #ifdef SCPH_102
|
||||
// #define BIOS_PATCH_2
|
||||
// #define INTERRUPT_RISING
|
||||
// ------ SCPH 100 / 102 ------
|
||||
#if defined(SCPH_100) || \
|
||||
defined(SCPH_102)
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 84
|
||||
// #define PULSE_COUNT 48
|
||||
// #define BIT_OFFSET_CYCLES 26 // 3.25us / 0.125us ≈ 26 cycles
|
||||
// #define OVERRIDE_CYCLES 2 // 0.2us / 0.125us ≈ 2 cycles
|
||||
// #elif defined(F_CPU_16MHZ)
|
||||
// #define BOOT_OFFSET_MS 84
|
||||
// #define PULSE_COUNT 48
|
||||
// #define BIT_OFFSET_CYCLES 52 // 3.25 / 0.0625 ≈ 52 cycles
|
||||
// #define OVERRIDE_CYCLES 3 // 0.2 / 0.0625 ≈ 3 cycles
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
// -------- SCPH 100 --------
|
||||
#ifdef SCPH_100
|
||||
#define BIOS_PATCH_3
|
||||
#define INTERRUPT_RISING
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 84
|
||||
// #define PULSE_COUNT 48
|
||||
// #define BIT_OFFSET_CYCLES 22 // 2.75 / 0.125 ≈ 22 cycles
|
||||
// #define OVERRIDE_CYCLES 2 // 0.2 / 0.125 ≈ 2 cycles
|
||||
// #elif defined(F_CPU_16MHZ)
|
||||
//#define BOOT_OFFSET_MS 84
|
||||
|
||||
#define SILENCE_THRESHOLD 1428
|
||||
#define CONFIRM_COUNTER_TARGET 8
|
||||
#define PULSE_COUNT 48
|
||||
#define BIT_OFFSET_CYCLES 47 // 2.75 / 0.0625 ≈ 44 cycles +3
|
||||
#define OVERRIDE_CYCLES 3 // 0.2 / 0.0625 ≈ 3 cycles
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 1400
|
||||
#define CONFIRM_COUNTER_TARGET 8
|
||||
#define PULSE_COUNT 47
|
||||
#define BIT_OFFSET_CYCLES 67 //60+7
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
// // -------- SCPH 7500 / 9000 --------
|
||||
#ifdef SCPH_7500_9000
|
||||
#define BIOS_PATCH_3
|
||||
#define INTERRUPT_RISING
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 75
|
||||
// #define PULSE_COUNT 16
|
||||
// #define BIT_OFFSET_CYCLES 22 // 2.8 / 0.125 ≈ 22 cycles
|
||||
// #define OVERRIDE_CYCLES 2 // 0.2 / 0.125 ≈ 2 cycles
|
||||
//#elif defined(F_CPU_16MHZ)
|
||||
//#define BOOT_OFFSET_MS 75
|
||||
|
||||
#define SILENCE_THRESHOLD 1428
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 16
|
||||
#define BIT_OFFSET_CYCLES 47 // 2.8 / 0.0625 ≈ 45 cycles
|
||||
#define OVERRIDE_CYCLES 3 // 0.2 / 0.0625 ≈ 3 cycles
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 1400
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 15
|
||||
#define BIT_OFFSET_CYCLES 66 //60+
|
||||
#define OVERRIDE_CYCLES 4
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
// // -------- SCPH 7000 --------
|
||||
// #ifdef SCPH_7000
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_RISING
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 75
|
||||
// #define PULSE_COUNT 16
|
||||
// #define BIT_OFFSET_CYCLES 22
|
||||
// #define OVERRIDE_CYCLES 2
|
||||
// #elif defined(F_CPU_16MHZ)
|
||||
// #define BOOT_OFFSET_MS 75
|
||||
// #define PULSE_COUNT 16
|
||||
// #define BIT_OFFSET_CYCLES 45
|
||||
// #define OVERRIDE_CYCLES 3
|
||||
// #endif
|
||||
// #endif
|
||||
// -------- SCPH 7000 --------
|
||||
#ifdef SCPH_7000
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 1400
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 15
|
||||
#define BIT_OFFSET_CYCLES 66
|
||||
#define OVERRIDE_CYCLES 4
|
||||
#endif
|
||||
|
||||
// // -------- SCPH 5500 --------
|
||||
// #ifdef SCPH_5500
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_FALLING
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 76
|
||||
// #define PULSE_COUNT 21
|
||||
// #define BIT_OFFSET_CYCLES 22
|
||||
// #define OVERRIDE_CYCLES 2
|
||||
// #elif defined(F_CPU_16MHZ)
|
||||
// #define BOOT_OFFSET_MS 76
|
||||
// #define PULSE_COUNT 21
|
||||
// #define BIT_OFFSET_CYCLES 45
|
||||
// #define OVERRIDE_CYCLES 3
|
||||
// #endif
|
||||
// #endif
|
||||
// // ----- SCPH 5000 / 5500 -----
|
||||
#ifdef SCPH_5000_5500
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 35000
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 84
|
||||
#define BIT_OFFSET_CYCLES 60
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
|
||||
// // -------- SCPH 5000 --------
|
||||
|
||||
// // // -------- SCPH 5000 --------
|
||||
// #ifdef SCPH_5000
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_FALLING
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 75
|
||||
// #define PULSE_COUNT 21
|
||||
// #define BIT_OFFSET_CYCLES 22
|
||||
// #define OVERRIDE_CYCLES 1
|
||||
// #elif defined(F_CPU_16MHZ)
|
||||
// #define BOOT_OFFSET_MS 75
|
||||
// #define PULSE_COUNT 21
|
||||
// #define BIT_OFFSET_CYCLES 45
|
||||
// #define OVERRIDE_CYCLES 2
|
||||
// #endif
|
||||
// #define BIOS_PATCH_3
|
||||
// #define INTERRUPT_RISING
|
||||
// #define SILENCE_THRESHOLD 35000
|
||||
// #define CONFIRM_COUNTER_TARGET 1
|
||||
// #define PULSE_COUNT 84
|
||||
// #define BIT_OFFSET_CYCLES 60
|
||||
// #define OVERRIDE_CYCLES 3
|
||||
// #endif
|
||||
// // #endif
|
||||
|
||||
// // -------- SCPH 3500 --------
|
||||
// #ifdef SCPH_3500
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_FALLING
|
||||
#ifdef SCPH_3500
|
||||
#define BIOS_PATCH
|
||||
#define SILENCE_THRESHOLD 34000
|
||||
#define CONFIRM_COUNTER_TARGET 1
|
||||
#define PULSE_COUNT 85
|
||||
#define BIT_OFFSET_CYCLES 44
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#endif
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 75
|
||||
// #define PULSE_COUNT 21
|
||||
// #define BIT_OFFSET_CYCLES 22
|
||||
// #define OVERRIDE_CYCLES 2
|
||||
// #elif defined(F_CPU_16MHZ)
|
||||
// #define BOOT_OFFSET_MS 75
|
||||
// #define PULSE_COUNT 21
|
||||
// #define BIT_OFFSET_CYCLES 44
|
||||
// #define OVERRIDE_CYCLES 3
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
// // -------- SCPH 3000 --------
|
||||
// #ifdef SCPH_3000
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_RISING_HIGH_PATCH
|
||||
// #define HIGH_PATCH
|
||||
#ifdef SCPH_3000
|
||||
#define BIOS_PATCH
|
||||
#define INTERRUPT_RISING_HIGH_PATCH
|
||||
#define SILENCE_THRESHOLD 1200
|
||||
#define CONFIRM_COUNTER_TARGET 9
|
||||
#define PULSE_COUNT 60
|
||||
#define BIT_OFFSET_CYCLES 46
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#define SILENCE_THRESHOLD_2 1200
|
||||
#define CONFIRM_COUNTER_TARGET_2 206
|
||||
#define PULSE_COUNT_2 43
|
||||
#define BIT_OFFSET_2_CYCLES 54
|
||||
#define OVERRIDE_2_CYCLES 2
|
||||
#endif
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 83
|
||||
// #define PULSE_COUNT 60
|
||||
// #define BIT_OFFSET_CYCLES 22
|
||||
// #define OVERRIDE_CYCLES 1
|
||||
// #define FOLLOWUP_OFFSET_MS 253
|
||||
// #define PULSE_COUNT_2 43
|
||||
// #define BIT_OFFSET_2_CYCLES 23
|
||||
// #define OVERRIDE_2_CYCLES 1
|
||||
// #elif defined(F_CPU_16MHZ)
|
||||
// #define BOOT_OFFSET_MS 83
|
||||
// #define PULSE_COUNT 60
|
||||
// #define BIT_OFFSET_CYCLES 43
|
||||
// #define OVERRIDE_CYCLES 2
|
||||
// #define FOLLOWUP_OFFSET_MS 253
|
||||
// #define PULSE_COUNT_2 43
|
||||
// #define BIT_OFFSET_2_CYCLES 46
|
||||
// #define OVERRIDE_2_CYCLES 2
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
// // -------- SCPH 1000 --------
|
||||
// #ifdef SCPH_1000
|
||||
// #define BIOS_PATCH
|
||||
// #define INTERRUPT_RISING_HIGH_PATCH
|
||||
// #define HIGH_PATCH
|
||||
|
||||
// #ifdef F_CPU_8MHZ
|
||||
// #define BOOT_OFFSET_MS 83
|
||||
// #define PULSE_COUNT 92
|
||||
// #define BIT_OFFSET_CYCLES 21
|
||||
// #define OVERRIDE_CYCLES 1
|
||||
// #define FOLLOWUP_OFFSET_MS 273
|
||||
// #define PULSE_COUNT_2 71
|
||||
// #define BIT_OFFSET_2_CYCLES 23
|
||||
// #define OVERRIDE_2_CYCLES 1
|
||||
// #elif defined(F_CPU_16MHZ)
|
||||
// #define BOOT_OFFSET_MS 83
|
||||
// #define PULSE_COUNT 92
|
||||
// #define BIT_OFFSET_CYCLES 42
|
||||
// #define OVERRIDE_CYCLES 2
|
||||
// #define FOLLOWUP_OFFSET_MS 273
|
||||
// #define PULSE_COUNT_2 71
|
||||
// #define BIT_OFFSET_2_CYCLES 46
|
||||
// #define OVERRIDE_2_CYCLES 2
|
||||
// #endif
|
||||
#ifdef SCPH_1000
|
||||
#define BIOS_PATCH
|
||||
#define INTERRUPT_RISING_HIGH_PATCH
|
||||
#define SILENCE_THRESHOLD 1300
|
||||
#define CONFIRM_COUNTER_TARGET 9
|
||||
#define PULSE_COUNT 91
|
||||
#define BIT_OFFSET_CYCLES 58
|
||||
#define OVERRIDE_CYCLES 3
|
||||
#define CONFIRM_COUNTER_TARGET_2 222
|
||||
#define PULSE_COUNT_2 71
|
||||
#define BIT_OFFSET_2_CYCLES 54
|
||||
#define OVERRIDE_2_CYCLES 3
|
||||
#endif
|
||||
// #endif
|
||||
/*------------------------------------------------------------------------------------------------
|
||||
Region Settings Section
|
||||
------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(SCPH_100) || defined(SCPH_7500_9000) || defined(SCPH_7000) || \
|
||||
defined(SCPH_5500) || defined(SCPH_5000) ||defined(SCPH_3500) || defined(SCPH_3000) || \
|
||||
defined(SCPH_1000) || defined(SCPH_xxx3) || defined(SCPH_5903)
|
||||
#define INJECT_SCEx 0 // NTSC-J
|
||||
#endif
|
||||
#if defined(SCPH_100) || \
|
||||
defined(SCPH_7500_9000) || \
|
||||
defined(SCPH_7000) || \
|
||||
defined(SCPH_5000_5500) || \
|
||||
defined(SCPH_3500) || \
|
||||
defined(SCPH_3000) || \
|
||||
defined(SCPH_1000) || \
|
||||
defined(SCPH_xxx3) || \
|
||||
defined(SCPH_5903)
|
||||
|
||||
#if defined(SCPH_xxx1)
|
||||
#define INJECT_SCEx 1 // NTSC-U/C
|
||||
#endif
|
||||
#define INJECT_SCEx 0 // NTSC-J
|
||||
|
||||
#if defined(SCPH_xxx2) || defined(SCPH_102)
|
||||
#define INJECT_SCEx 2 // PAL
|
||||
#endif
|
||||
#elif defined(SCPH_xxx1)
|
||||
|
||||
#define INJECT_SCEx 1 // NTSC-U/C
|
||||
|
||||
#elif defined(SCPH_xxx2) || \
|
||||
defined(SCPH_102)
|
||||
|
||||
#define INJECT_SCEx 2 // PAL
|
||||
|
||||
#elif defined(SCPH_xxxx)
|
||||
|
||||
#define INJECT_SCEx 3 // Universal: NTSC-J -> NTSC-U/C -> PAL
|
||||
|
||||
#if defined(SCPH_xxxx)
|
||||
#define INJECT_SCEx 3 // Universal: NTSC-J -> NTSC-U/C -> PAL
|
||||
#endif
|
||||
|
||||
|
||||
@@ -335,7 +163,7 @@ void Debug_Log (int Wfck_mode){ //Information about the MCU, and old or
|
||||
|
||||
#if defined(ATtiny85_45_25)
|
||||
mySerial.print("m "); mySerial.println(Wfck_mode);
|
||||
#elif !defined(ATtiny85_45_25)
|
||||
#else
|
||||
Serial.print(" MCU frequency: "); Serial.print(F_CPU); Serial.println(" Hz");
|
||||
//Serial.print(" lows: "); Serial.println(Lows);
|
||||
Serial.print(" wfck_mode: "); Serial.println(Wfck_mode);
|
||||
@@ -380,7 +208,7 @@ void Debug_Inject(){ // Confirmation of region code injection
|
||||
|
||||
#if defined(ATtiny85_45_25)
|
||||
mySerial.print("!");
|
||||
#elif !defined(ATtiny85_45_25)|| defined(SCPH_102_legacy)
|
||||
#else
|
||||
Serial.println(" INJECT ! ");
|
||||
#endif
|
||||
}
|
||||
@@ -391,26 +219,50 @@ void Debug_Inject(){ // Confirmation of region code injection
|
||||
Compilation message
|
||||
-----------------------------------------------------------------------------------------------*/
|
||||
|
||||
#if !defined(SCPH_xxx3) && \
|
||||
!defined(SCPH_102) && !defined(SCPH_101) && !defined(SCPH_100) && !defined(SCPH_7500_9000) && \
|
||||
!defined(SCPH_7000) && !defined(SCPH_5500) && !defined(SCPH_5000) && !defined(SCPH_3500) && !defined(SCPH_3000) && \
|
||||
!defined(SCPH_1000) && !defined(SCPH_5903) &&\
|
||||
!defined(SCPH_xxx1) && !defined(SCPH_xxx2) && !defined(SCPH_xxxx)
|
||||
#if !defined(SCPH_xxx3) && \
|
||||
!defined(SCPH_102) && \
|
||||
!defined(SCPH_101) && \
|
||||
!defined(SCPH_100) && \
|
||||
!defined(SCPH_7500_9000) && \
|
||||
!defined(SCPH_7000) && \
|
||||
!defined(SCPH_5000_5500) && \
|
||||
!defined(SCPH_3500) && \
|
||||
!defined(SCPH_3000) && \
|
||||
!defined(SCPH_1000) && \
|
||||
!defined(SCPH_5903) && \
|
||||
!defined(SCPH_xxx1) && \
|
||||
!defined(SCPH_xxx2) && \
|
||||
!defined(SCPH_xxxx)
|
||||
#error "Console not selected! Please uncoment #define with SCPH model number."
|
||||
#elif !defined(SCPH_xxx3) ^ \
|
||||
defined(SCPH_102) ^ defined(SCPH_101) ^ defined(SCPH_100) ^ defined(SCPH_7500_9000) ^ \
|
||||
defined(SCPH_7000) ^ defined(SCPH_5500) ^ defined(SCPH_5000) ^ defined(SCPH_3500) ^ defined(SCPH_3000) ^ \
|
||||
defined(SCPH_1000) ^ defined(SCPH_xxxx) ^ defined(SCPH_5903) ^ \
|
||||
defined(SCPH_xxx1) ^ defined(SCPH_xxx2)
|
||||
#elif !defined(SCPH_xxx3) ^ \
|
||||
defined(SCPH_102) ^ \
|
||||
defined(SCPH_101) ^ \
|
||||
defined(SCPH_100) ^ \
|
||||
defined(SCPH_7500_9000) ^ \
|
||||
defined(SCPH_7000) ^ \
|
||||
defined(SCPH_5000_5500) ^ \
|
||||
defined(SCPH_3500) ^ \
|
||||
defined(SCPH_3000) ^ \
|
||||
defined(SCPH_1000) ^ \
|
||||
defined(SCPH_xxxx) ^ \
|
||||
defined(SCPH_5903) ^ \
|
||||
defined(SCPH_xxx1) ^ \
|
||||
defined(SCPH_xxx2)
|
||||
#error "May be selected only one console! Please check #define with SCPH model number."
|
||||
#endif
|
||||
|
||||
#if !defined(ATmega328_168) && !defined(ATmega32U4_16U4) && !defined(ATtiny85_45_25)
|
||||
#if !defined(ATmega328_168) && \
|
||||
!defined(ATmega32U4_16U4) && \
|
||||
!defined(ATtiny85_45_25)
|
||||
#error "MCU not selected! Please choose one"
|
||||
#elif !defined(ATmega328_168) ^ defined(ATmega32U4_16U4 ) ^ defined(ATtiny85_45_25)
|
||||
#elif !defined(ATmega328_168) ^ \
|
||||
defined(ATmega32U4_16U4 ) ^ \
|
||||
defined(ATtiny85_45_25)
|
||||
#error "May be selected only one MCU"
|
||||
#endif
|
||||
|
||||
#if defined(LED_RUN) && defined(PSNEE_DEBUG_SERIAL_MONITOR) && defined(ATtiny85_45_25)
|
||||
#if defined(LED_RUN) && \
|
||||
defined(PSNEE_DEBUG_SERIAL_MONITOR) && \
|
||||
defined(ATtiny85_45_25)
|
||||
#error"Compilation options LED_RUN and PSNEE_DEBUG_SERIAL_MONITOR are not simultaneously compatible with ATtiny85_45_25"
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user