1
0
mirror of https://github.com/kalymos/PsNee.git synced 2026-05-09 16:46:23 +00:00
Files
kalymos.PsNee/PSNee/settings.h
2026-03-20 19:50:31 +01:00

395 lines
12 KiB
C

#pragma once
/*
The _delay_us function uses loops to generate an approximate delay for the specified number of microseconds.
It calculates the number of clock cycles required to achieve the requested delay and loops the corresponding number of times.
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
*/
/*------------------------------------------------------------------------------------------------
Specific parameter section for BIOS patches
------------------------------------------------------------------------------------------------*/
// Results of the maximum values
// tested with an Atmega328P
#if defined(IS_32U4_FAMILY)
// ------ SCPH 100 / 102 ------
#if defined(SCPH_100) || \
defined(SCPH_102)
#define BIOS_PATCH
#define SILENCE_THRESHOLD 1100
#define CONFIRM_COUNTER_TARGET 8
#define PULSE_COUNT 47 //47
#define BIT_OFFSET_CYCLES 47 //60
#define OVERRIDE_CYCLES 3
#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
// -------- 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
#if defined(IS_328_168_FAMILY)
// ------ 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
// // -------- 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
// -------- 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
// // ----- 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
// // -------- 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
// // -------- 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_3500_5500) || \
defined(SCPH_3500) || \
defined(SCPH_3000) || \
defined(SCPH_1000) || \
defined(SCPH_xxx3) || \
defined(SCPH_5903)
#define INJECT_SCEx 0 // NTSC-J
#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
#endif
/*------------------------------------------------------------------------------------------------
serial debug section
------------------------------------------------------------------------------------------------*/
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
void Debug_Log (uint16_t debounce, int Wfck_mode){ //Information about the MCU, and old or late console mode.
#if defined(IS_ATTINY_FAMILY)
mySerial.print("m "); mySerial.println(Wfck_mode);
#else
Serial.print(" MCU frequency: "); Serial.print(F_CPU); Serial.println(" Hz");
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
}
// 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(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.
mySerial.print("m ");
mySerial.println(Wfck_mode); // Mode indicator
#else
// --- VERBOSE DIAGNOSTICS (ATmega) ---
// Detailed system information for standard development and debugging.
Serial.print(" MCU frequency: ");
Serial.print(F_CPU);
Serial.println(" Hz");
Serial.print(" wfck_mode: ");
Serial.println(Wfck_mode); // Board generation (0: Legacy, 1: Modern)
Serial.print(" region: ");
Serial.print(region[0]);
Serial.print(region[1]);
Serial.println(region[2]); // Active injection string (e.g., SCEE)
#endif
}
#endif
/******************************************************************************************
* FUNCTION : LogSUBQ
*
* DESCRIPTION :
* Logs captured SUBQ frames to the serial interface.
* Timing is critical: the entire 12-byte frame must be processed and transmitted
* within the ~12ms window before the next SUBQ packet arrives.
*
* - ATtiny: Uses minimal formatting (no spaces) to stay within the timing budget.
* - Standard MCUs: Includes spaces for better readability.
*
* INPUT : dataBuffer (uint8_t*) - Pointer to the 12-byte SUBQ frame.
******************************************************************************************/
void LogSUBQ(uint8_t *dataBuffer) {
/**
* ERROR FILTERING:
* A failed sector read usually results in zeroed data (excluding CRC).
* Skip logging if the first 4 bytes are null to reduce bus traffic.
*/
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
}
mySerial.print(Scbuf[i, HEX]);
}
mySerial.println("");
}
#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.println("");
}
#endif
}
void Debug_Inject(){ // Confirmation of region code injection
#if defined(IS_ATTINY_FAMILY)
// --- MINIMALIST NOTIFICATION (ATtiny) ---
mySerial.print("!");
#else
// --- VERBOSE NOTIFICATION (ATmega) ---
// Standard visual feedback for debugging and monitoring.
Serial.println(" INJECT ! ");
#endif
}
#endif
/*------------------------------------------------------------------------------------------------
Compilation message
-----------------------------------------------------------------------------------------------*/
#ifdef LED_RUN
#pragma message "Feature: Status LED ENABLED"
#endif
// 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
// Show target console.
#if defined(SCPH_1000)
#pragma message "Target Console: SCPH-1000 (NTSC-J)"
#elif defined(SCPH_3000)
#pragma message "Target Console: SCPH-3000 (NTSC-J)"
#elif defined(SCPH_3500_5500)
#pragma message "Target Console: SCPH-3500/5000/5500 (NTSC-J)"
#elif defined(SCPH_7000)
#pragma message "Target Console: SCPH-7000 (Internal Switch enabled)"
#elif defined(SCPH_7500_9000)
#pragma message "Target Console: SCPH-7500/9000 (NTSC-J)"
#elif defined(SCPH_100)
#pragma message "Target Console: SCPH-100 (NTSC-J)"
#elif defined(SCPH_102)
#pragma message "Target Console: SCPH-102 (PAL)"
#elif defined(SCPH_xxx1)
#pragma message "Target Console: SCPH_xxx1 Generic NTSC-U/C"
#elif defined(SCPH_xxx2)
#pragma message "Target Console: SCPH_xxx2 Generic PAL"
#elif defined(SCPH_xxx3)
#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: SCPH_xxxx Universal Region Mode"
#else
// Error if no console is uncommented
#error "Console not selected! Please uncomment one SCPH model."
#endif
// 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 ---
#ifdef PSNEE_DEBUG_SERIAL_MONITOR
#pragma message "Feature: Serial Debug Monitor ENABLED"
#endif