/************************************************************************************************************

AVR code to emulate Playstation game controller protocol
        
date:        October 12, 2009
compiler:    gcc-avr compiler
AVR:        ATmega324p
clock source:    8 MHz external crystal

*************************************************************************************************************/

#include <avr/io.h>
#include "def.h"
#include "other.h"

#define F_CPU    8000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <inttypes.h>
#include <util/twi.h>

int main(void){

    uint8_t final_data[18];            // array stores final formatted data that is sent to ps2
    uint8_t dsc_data[6];            // array stores raw data acquired from ps controller
    uint8_t chuck_data[6];            // array stores raw data acquired from nunchuck
    uint8_t command[6];            // array stores commands sent from ps2 in order they are received
    uint8_t saturn_data[2];            // array stores raw data acquired from saturn controller
    uint8_t nes_data[2];            // array stores raw data acquired from NES controller
    uint8_t DSC_mode_ID = 0x00;        // mode ID given by controller connected to ps controller port
    uint8_t DSC_config_counter = 0x00;    // counter used to increment ps controller config sequence 
    uint8_t remapped_x;            // stores nunchuck x-axis tilt value in remapped 8-bit range
    uint8_t remapped_y;            // stores nunchuck y-axis tilt value in remapped 8-bit range
    uint8_t CSR0 = 0x00;            // command status register 0
    uint8_t MSR0 = 0x00;            // macro status register 0
    uint8_t TSR0 = 0x00;            // turbo status register 0
    uint8_t GCSR0 = 0x00;            // game controller status register 0
    uint8_t display_tracker = 0x00;        // keeps track of displayed message on LCD
    uint8_t katamari_counter = 0x01;    // counter for katamari mode macro
    uint8_t turbo_counter = 0x00;        // counter for turbo mode macro
    uint8_t reader = 0x00;

    char welcome[] =     "Welcome DSC Emu v2.5";
    char date[] =        "Compiled 10/12/2009";
    char katamari[] =     "Katamari";
    char racing[] =     "Racing";
    char arcade[] =        "Arcade";
    char standard[] =    "Default";
    char turbo[] =         "Turbo";
    char serial_in[] =    "Serial Input";
    char mode[] =        " Mode";

    final_data[0] = 0xFF;            // Initialise data variables with neutral values
    final_data[1] = 0xFF;
    final_data[2] = 0x80;
    final_data[3] = 0x80;
    final_data[4] = 0x80;
    final_data[5] = 0x80;
    command[0] = 0x00;
    command[1] = 0x00;
    command[2] = 0x00;
    command[3] = 0x00;
    command[4] = 0x00;

    init();                    // configure all AVR registers and interrupts 
    lcd_init();                // initialise LCD
    lcd_string_print(welcome);        // print top line welcome message
    lcd_move_to_address(SECOND_LINE);
    lcd_string_print(date);
    lcd_instruction_write(RETURN_HOME);
    
    /* Infinite while loop*/
    while(1){
    
    
/*PS-AVR SPI SECTION*******************************************************************************************/

        if(~SPI_PIN & _BV(SS)){    // If attention line (SS/PB2) is brought low, enter transmission mode
            
            reader = SPSR;        // Read SPI status register to clear SPIF flag
            SPDR = ~0xFF;        // Write SPI data register with initial dummy byte
            START_TIMER_AT(1);    // setup 1ms timer

            // loop while timer counts up, SS remains low, and SPI transmission flag not set
            while((!(TIFR2 & _BV(TOV2))) && (~SPI_PIN & _BV(SS)) && (!(SPSR & _BV(SPIF))));

            // If these two remain true it means SPI hardware has received a byte and communication continues
            if((!(TIFR2 & _BV(TOV2))) && (~SPI_PIN &_BV(SS))){

                command[0] = SPDR;    // Read first command byte from SPI buffer

            if(command[0] == 0x01){    // If PS is not addressing controller, abandon communication

                    _delay_us(4);    // delay before ACK necessary for Ps1 compatibility
                    ACKNOWLEDGE;    // ACK pulse sent following every byte except final byte
                                
            if((CSR0 & _BV(ANALOG_MODE_BIT)) && (!(CSR0 & _BV(CONFIG_MODE_BIT)))){ // if analog mode is active and config mode is inactive...
                    PS_AVR_COMM(0x73, command[1]);}        // ...send 0x73, analog mode ID
            else if((!(CSR0 & _BV(ANALOG_MODE_BIT))) && (!(CSR0 & _BV(CONFIG_MODE_BIT)))){ // if neither config mode nor analog mode active...
                    PS_AVR_COMM(0x41, command[1]);}        // ...send 0x41, digital mode ID
            else if(CSR0 & _BV(CONFIG_MODE_BIT)){            // if config mode is active...
                    PS_AVR_COMM(0xF3, command[1]);}        // ...send 0xF3, config mode ID

        // tests for known commands which the adapter will reply to, commands not listed will terminate communication for the current packet
        // 0x42 = main polling command used to get control data from adapter
        // 0x43 = enter/exit config mode command
        // 0x44 = switch between analog/digital modes and lock/unlock controller in specified mode
        // 0x45 = command to retrieve status/ID info from adapter
        // 0x46 = command to retrieve 10 bytes of mystery data from adapter over two packets
        // 0x47 = command to retrieve 5 bytes of mystery data from adapter
        // 0x4C = command to retrieve 10 bytes of mystery data from adapter over two packets
        // 0x4D = maps rumble motor commands to command bytes 3 and 4 in 0x42 polling packet
        if((command[1] == 0x42) || (command[1] == 0x43) || (command[1] == 0x44) || (command[1] == 0x45) || (command[1] == 0x46) || (command[1] == 0x47) || (command[1] == 0x4C) || (command[1] == 0x4D)){

                        _delay_us(4);
                        ACKNOWLEDGE;

                    PS_AVR_COMM(0x5A, command[2]);        // filler byte, always 0x5A

            if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x45)){    // if adapter is in config mode and 0x45 command is received
                final_data[0] = 0x01;        // meaning of these bytes is unknown, copied from analysis of a real Ps1 controller response
                final_data[1] = 0x02;
                (CSR0 & _BV(ANALOG_MODE_BIT)) ? (final_data[2] = 0x01) : (final_data[2] = 0x00); // 1 if in analog mode, otherwise 0
                final_data[3] = 0x02;
                final_data[4] = 0x01;
                final_data[5] = 0x00;
                }

            // sets up first two data bytes for a 0x4D command, these bytes report the current rumble motor mapping 
            if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x4D)){
                if(CSR0 & _BV(FIRST_MOTOR_BYTE_SMALL))
                    final_data[0] = 0x00;
                else if(CSR0 & _BV(FIRST_MOTOR_BYTE_LARGE))
                    final_data[0] = 0x01;
                else
                    final_data[0] = 0xFF;

                if(CSR0 & _BV(SECOND_MOTOR_BYTE_SMALL))
                    final_data[1] = 0x00;
                else if(CSR0 & _BV(SECOND_MOTOR_BYTE_LARGE))
                    final_data[1] = 0x01;
                else
                    final_data[1] = 0xFF;
                }

            // ps1 will reject data in the 0x46, 0x47, and 0x4C packets if final_data[0] is not 0x00 
            if((CSR0 & _BV(CONFIG_MODE_BIT)) && ((command[1] == 0x46) || (command[1] == 0x47) || (command[1] == 0x4C))){
                    final_data[0] = 0x00;
                }

                        _delay_us(4);
                        ACKNOWLEDGE;

                    PS_AVR_COMM(final_data[0], command[3]);    // first data byte (8 buttons)

            if(command[1] == 0x43){
                // command[3] tells the adapter to enter or exit config mode when command[1] is 0x43
                (command[3] == 0x00) ? (CSR0 &= ~_BV(CONFIG_MODE_BIT)) : (CSR0 |= _BV(CONFIG_MODE_BIT));
                }

            if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x46)){
                if(command[3] == 0x00){
                    final_data[1] = 0x00;    // meaning of these bytes is unknown, copied from analysis of a real Ps1 controller response
                    final_data[2] = 0x01;
                    final_data[3] = 0x02;
                    final_data[4] = 0x00;
                    final_data[5] = 0x0A;
                    }
                else if(command[3] == 0x01){
                    final_data[1] = 0x00;
                    final_data[2] = 0x01;
                    final_data[3] = 0x01;
                    final_data[4] = 0x01;
                    final_data[5] = 0x14;
                    }
                }

            if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x47)){
                final_data[1] = 0x00;    // meaning of these bytes is unknown, copied from analysis of a real Ps1 controller response
                final_data[2] = 0x02;
                final_data[3] = 0x00;
                final_data[4] = 0x01;
                final_data[5] = 0x00;
                }

            if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x4C)){
                if(command[3] == 0x00){
                    final_data[1] = 0x00;    // meaning of these bytes is unknown, copied from analysis of a real Ps1 controller response
                    final_data[2] = 0x00;
                    final_data[3] = 0x04;
                    final_data[4] = 0x00;
                    final_data[5] = 0x00;
                    }
                else if(command[3] == 0x01){
                    final_data[1] = 0x00;
                    final_data[2] = 0x00;
                    final_data[3] = 0x07;
                    final_data[4] = 0x00;
                    final_data[5] = 0x00;
                    }
                }

                        _delay_us(4);
                        ACKNOWLEDGE;

                    PS_AVR_COMM(final_data[1], command[4]);    // second data byte (8 buttons)

            if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x44)){
                // command[3] turns analog mode on or off, command[4] locks controller in specified mode
                (command[3] == 0x00) ? (CSR0 &= ~_BV(ANALOG_MODE_BIT)) : (CSR0 |= _BV(ANALOG_MODE_BIT));
                (command[4] == 0x03) ? (CSR0 |= _BV(LOCK_BIT)) : (CSR0 &= ~_BV(LOCK_BIT));
                }

            if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x4D)){
                if(command[3] == 0){
                    CSR0 |= _BV(FIRST_MOTOR_BYTE_SMALL);
                    CSR0 &= ~_BV(FIRST_MOTOR_BYTE_LARGE);}
                else if(command[3] == 1){
                    CSR0 |= _BV(FIRST_MOTOR_BYTE_LARGE);
                    CSR0 &= ~_BV(FIRST_MOTOR_BYTE_SMALL);}
                else{
                    CSR0 &= ~_BV(FIRST_MOTOR_BYTE_SMALL);
                    CSR0 &= ~_BV(FIRST_MOTOR_BYTE_LARGE);}

                if(command[4] == 0){
                    CSR0 |= _BV(SECOND_MOTOR_BYTE_SMALL);
                    CSR0 &= ~_BV(SECOND_MOTOR_BYTE_LARGE);}
                else if(command[4] == 1){
                    CSR0 |= _BV(SECOND_MOTOR_BYTE_LARGE);
                    CSR0 &= ~_BV(SECOND_MOTOR_BYTE_SMALL);}
                else{
                    CSR0 &= ~_BV(SECOND_MOTOR_BYTE_SMALL);
                    CSR0 &= ~_BV(SECOND_MOTOR_BYTE_LARGE);}
                }
                    
            START_TIMER_AT(253);
            // loop while timer counts up, and SS remains low, timeout skips ACK and remaining bytes if Ps cuts off communication early
            while((!(TIFR2 & _BV(TOV2))) && (~SPI_PIN & _BV(SS)));
            // continue with transmission of the final 4 bytes if adapter is in analog mode, config mode, or if command[1] is 0x43
            if(((CSR0 & _BV(ANALOG_MODE_BIT)) || (CSR0 & _BV(CONFIG_MODE_BIT)) || (command[1] == 0x43)) && (~SPI_PIN & _BV(SS))){

                        _delay_us(4);
                        ACKNOWLEDGE;

                    PS_AVR_COMM(final_data[2], command[5]);    // Right analog X data Byte
                        
                        _delay_us(4);
                        ACKNOWLEDGE;

                    PS_AVR_COMM(final_data[3], command[5]);    // Right analog Y data byte

                        _delay_us(4);
                        ACKNOWLEDGE;

                    PS_AVR_COMM(final_data[4], command[5]);    // Left analog X data byte

                        _delay_us(4);
                        ACKNOWLEDGE;

                    PS_AVR_COMM(final_data[5], command[5]);    // Left analog Y data byte

            }// if analog mode or config mode

            }// if command[1] == one of the recognised commands

            }// 0x01 controller address check

            else{    SPI_PORT &= ~_BV(MISO);    // Clear data output
                DISABLE_SPI;    // Disable SPI hardware to avoid conflict with mem-card comm
                }

            }// timer overflow and SS line check

            }// if SS is low
            
            SPI_PORT &= ~_BV(MISO);        // Clear data output

            while(~SPI_PIN & _BV(SS));    // Loop until SS returns high after communication is complete


/*CONTROLLER POLLING SECTION*****************************************************************************************/

    ENABLE_TWI;                    // re-enable TWI hardware
    ENABLE_SPI;                    // re-enable SPI hardware
    START_TIMER_AT(64);

    while((!(TIFR2 & _BV(TOV2))) && (SPI_PIN & _BV(SS)));    // Loop while timer counts up and SS pin remains high

    if(SPI_PIN & _BV(SS)){                // if SS line is high, SPI communication is not being requested

    final_data[0] = 0xFF;                    // Clear data bytes before controller polling
    final_data[1] = 0xFF;
    final_data[2] = 0x80;
    final_data[3] = 0x80;
    final_data[4] = 0x80;
    final_data[5] = 0x80;
    chuck_data[0] = 0x80;
    chuck_data[1] = 0x80;
    chuck_data[2] = 0x80;
    chuck_data[3] = 0x80;
    chuck_data[4] = 0x80;
    chuck_data[5] = 0xFF;        // byte containing unused LSBs of accelerometer data and two digital button states 

    if(!(CONFIG_CYCLE_PIN & _BV(CONFIG_CYCLE))){

        if(!(GCSR0 & _BV(BUTTON1_LOW_STATUS_BIT))){    // BUTTON1_LOW_STATUS_BIT indicates whether or not the button is already being pressed

            lcd_instruction_write(CLEAR_SCREEN);
            _delay_ms(2);
            switch(display_tracker){
                case    STANDARD_MODE:        lcd_string_print(katamari); lcd_string_print(mode); display_tracker++; break;
                case    KATAMARI_MODE:        lcd_string_print(racing); lcd_string_print(mode); display_tracker++; break;
                case    RACING_MODE:        lcd_string_print(arcade); lcd_string_print(mode); display_tracker++; break;
                case    ARCADE_MODE:        lcd_string_print(turbo); lcd_string_print(mode); display_tracker++; break;
                case    TURBO_MODE:        lcd_string_print(serial_in); lcd_string_print(mode); display_tracker++; break;
                case    SERIAL_IN_MODE:        lcd_string_print(standard); lcd_string_print(mode); display_tracker = 0;
            }
                lcd_instruction_write(RETURN_HOME);
                GCSR0 |= _BV(BUTTON1_LOW_STATUS_BIT) | _BV(SKIP_POLLING_BIT);// set BUTTON1_LOW_STATUS_BIT and SKIP_POLLING_BIT flags
        }
    }

    if(CONFIG_CYCLE_PIN & _BV(CONFIG_CYCLE))        // if the button is high (default state)...
        GCSR0 &= ~_BV(BUTTON1_LOW_STATUS_BIT);        // ...reset BUTTON0_LOW_STATUS_BIT to wait for next press

    // controller polling and data formatting is skipped to save time for remainder of main loop after strings are written to LCD, may not be necessary
    if(!(GCSR0 & _BV(SKIP_POLLING_BIT))){
    // if bit is set in game controller status register this means controller is connecteed, configured, and ready for polling
    if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){

        BB_PORT &= ~_BV(ATTENTION);        // Begin communication with DSC
        _delay_us(16);                // Delay between ATTENTION dropping low and data transmission


        ps2_comm(0x01);                // byte 0; standard header, packets addressing the controller always start with 0x01
        DSC_mode_ID = ps2_comm(0x42);        // byte 1; standard header, controller replies with mode ID, 0x41 = digital, 0x73 = analog
        if(ps2_comm(0x00) == 0x5A){        // byte 2; standard header, data reply should always be 0x5A, used to test connection status
        // checks motor command configuration set by Ps and passes motor commands sent in 0x42 packet to the corresponding small motor in DSC
        if((CSR0 & _BV(FIRST_MOTOR_BYTE_SMALL)) && (command[1] == 0x42) && (command[3] != 0x00)){ dsc_data[0] = ps2_comm(command[3]);}
        else if((CSR0 & _BV(SECOND_MOTOR_BYTE_SMALL)) && (command[1] == 0x42) && (command[4] != 0x00)){ dsc_data[0] = ps2_comm(command[4]);}
        else{ dsc_data[0] = ps2_comm(0x00);}
        // checks motor command configuration set by Ps and passes motor commands sent in 0x42 packet to the corresponding large motor in DSC
        if((CSR0 & _BV(FIRST_MOTOR_BYTE_LARGE)) && (command[1] == 0x42) && (command[3] != 0x00)){ dsc_data[1] = ps2_comm(command[3]);}
        else if((CSR0 & _BV(SECOND_MOTOR_BYTE_LARGE)) && (command[1] == 0x42) && (command[4] != 0x00)){ dsc_data[1] = ps2_comm(command[4]);}
        else{ dsc_data[1] = ps2_comm(0x00);}

        for(uint8_t x = 2; x < ((DSC_mode_ID & 0x0F) << 1); x++)    // Loop loads data array with mode specific byte count
            dsc_data[x] = ps2_comm(0x00);
                
        _delay_us(16);                // Delay following data transmission before ATTENTION returns high
        BB_PORT |= _BV(ATTENTION);        // End communication with DSC
        LED_PORT &= ~_BV(STATUS_LED_GREEN);    // Green status LED on (controller connected)
        }
        else{
        GCSR0 &= ~_BV(DSC_CONNECT_STATUS_BIT);    // if 0x5A not received in command byte 2, controller != connected; set status register accordingly
        LED_PORT |= _BV(STATUS_LED_GREEN);    // Green status LED off
        }
    }

    if(!(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT))){
        // this switch handles the configuration commands to send over six main loops when the DSC is first plugged in
        switch(DSC_config_counter){
            case    0:    DSC_mode_ID = config_comm(0x42, 0x00, 0x00, 0x00, 0x00); DSC_config_counter = 1; break; // standard initial polling request, 5 bytes total
            case    1:    DSC_mode_ID = config_comm(0x43, 0x01, 0x00, 0x00, 0x00); DSC_config_counter = 2; break;    // enter config mode, 5 bytes total
            case    2:    DSC_mode_ID = config_comm(0x44, 0x01, 0x03, 0x00, 0x04); DSC_config_counter = 3; break;    // enable analog mode and lock controller, 9 bytes total
            case    3:    DSC_mode_ID = config_comm(0x4D, 0x00, 0x01, 0xFF, 0x04); DSC_config_counter = 4; break;    // vibration motor control byte mapping, command[3] = small motor, command[4] = large motor
            case    4:    DSC_mode_ID = config_comm(0x43, 0x00, 0x5A, 0x5A, 0x04); DSC_config_counter = 5; break; // exit config mode
            case    5:    DSC_mode_ID = config_comm(0x42, 0x00, 0x00, 0x00, 0x04); GCSR0 |= _BV(DSC_CONNECT_STATUS_BIT); DSC_config_counter = 0; break;
            }
        // test will reset configuration switch if a communication error occurs or controller is disconnected before full configuration is complete
        if((DSC_mode_ID == 0x00) || (DSC_mode_ID == 0xFF)){ DSC_config_counter = 0; GCSR0 &= ~_BV(DSC_CONNECT_STATUS_BIT);}
    }

    if(!(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT))){    // if no nunchuck is connected (default first time through)

        twi_start();
        twi_send_slaw(NUNCHUCK_ADDRESS);    // send 7 bit slave address (0x52) plus LSB R/W bit (0)

        if(TWI_STATUS_CHECK(TW_MT_SLA_ACK)){    // if TWI status register shows that SLA+R was sent and ack'd
            GCSR0 |= _BV(CHUCK_CONNECT_STATUS_BIT);
            twi_write_data(0x40);        // sending 0x40 followed by 0x00 is necessary to initialise nunchuck
            twi_write_data(0x00);
            SEND_TWI_STOP;
        }
        else{
            GCSR0 &= ~_BV(CHUCK_CONNECT_STATUS_BIT);
            SEND_TWI_STOP;            // important to send stop condition to recover from bus errors
        }
        }
        _delay_us(10);

    if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){    // if nunchuck is connected as detected by TWI_STATUS_CHECK

        twi_start();
        twi_send_slaw(NUNCHUCK_ADDRESS);

        if(TWI_STATUS_CHECK(TW_MT_SLA_ACK)){    // TW_MT_SLA_ACK defined in <util/twi.h>

            GCSR0 |= _BV(CHUCK_CONNECT_STATUS_BIT);
            twi_write_data(0x00);        // 0x00 must be sent to nunchuck before each data packet request
            SEND_TWI_STOP;

            _delay_us(10);

            twi_start();
            twi_send_slar(NUNCHUCK_ADDRESS);
            chuck_data[0] = twi_read_data(1);
            chuck_data[1] = twi_read_data(1);
            chuck_data[2] = twi_read_data(1);
            chuck_data[3] = twi_read_data(1);
            chuck_data[4] = twi_read_data(1);
            chuck_data[5] = twi_read_data(0);
            SEND_TWI_STOP;
            
        }// if(TWI_STATUS_CHECK(TW_MT_SLA_ACK))
        else{
            GCSR0 &= ~_BV(CHUCK_CONNECT_STATUS_BIT);
            SEND_TWI_STOP;
            }

        }// if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT))
        
    NES_GET_DATA(nes_data[0], nes_data[1]);        // get data from player1 and player2 NES ports

    saturn_data[0] = saturn_get_first_byte();    // get first byte of button data from saturn controller
    saturn_data[1] = saturn_get_second_byte();    // get second byte of data from saturn controller


/*DATA FORMATTING SECTION********************************************************************************************/

    if(display_tracker == STANDARD_MODE){

        if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){    // if the playstation controller is connected, map the buttons accordingly

            OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP);
            OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN);
            OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT);
            OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT);
            OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT);
            OR_map(dsc_data[0], &final_data[0], PS_START, PS_START);
            OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3);
            OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3);
            OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS);
            OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE);
            OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE);
            OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE);
            OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1);
            OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1);
            OR_map(dsc_data[1], &final_data[1], PS_R2, PS_R2);
            OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2);

            // if the playstation controller is in analog mode, map the analog sticks as well
            if(DSC_mode_ID == 0x73){ FINAL_RJOY_X = DSC_RJOY_X; FINAL_RJOY_Y = DSC_RJOY_Y; FINAL_LJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y;}
        }

        if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){    // if the Wii nunchuck is connected, map some more stuff

            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_Z, PS_CROSS);
            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_SQUARE);

            remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210);
            remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200);
            FINAL_LJOY_X = remapped_x;
            FINAL_LJOY_Y = remapped_y;

            map_a2d_if_less(NUNCHUCK_JOY_X, &final_data[0], 0x6F, PS_LEFT);
            map_a2d_if_greater(NUNCHUCK_JOY_X, &final_data[0], 0xC0, PS_RIGHT);
            map_a2d_if_less(NUNCHUCK_JOY_Y, &final_data[0], 0x5F, PS_DOWN);
            map_a2d_if_greater(NUNCHUCK_JOY_Y, &final_data[0], 0xC0, PS_UP);
        }

        OR_map(nes_data[0], &final_data[0], NES_UP, PS_UP);
        OR_map(nes_data[0], &final_data[0], NES_DOWN, PS_DOWN);
        OR_map(nes_data[0], &final_data[0], NES_LEFT, PS_LEFT);
        OR_map(nes_data[0], &final_data[0], NES_RIGHT, PS_RIGHT);
        OR_map(nes_data[0], &final_data[0], NES_START, PS_START);
        OR_map(nes_data[0], &final_data[0], NES_SELECT, PS_SELECT);
        OR_map(nes_data[0], &final_data[1], NES_A, PS_CROSS);
        OR_map(nes_data[0], &final_data[1], NES_B, PS_SQUARE);
        OR_map(nes_data[1], &final_data[0], NES_UP, PS_UP);
        OR_map(nes_data[1], &final_data[0], NES_DOWN, PS_DOWN);
        OR_map(nes_data[1], &final_data[0], NES_LEFT, PS_LEFT);
        OR_map(nes_data[1], &final_data[0], NES_RIGHT, PS_RIGHT);
        OR_map(nes_data[1], &final_data[0], NES_START, PS_R3);
        OR_map(nes_data[1], &final_data[1], NES_A, PS_CROSS);
        OR_map(nes_data[1], &final_data[1], NES_B, PS_CIRCLE);

        OR_map(saturn_data[1], &final_data[0], SAT_UP, PS_UP);
        OR_map(saturn_data[1], &final_data[0], SAT_DOWN, PS_DOWN);
        OR_map(saturn_data[1], &final_data[0], SAT_LEFT, PS_LEFT);
        OR_map(saturn_data[1], &final_data[0], SAT_RIGHT, PS_RIGHT);
        OR_map(saturn_data[1], &final_data[1], SAT_L, PS_L2);
        OR_map(saturn_data[0], &final_data[0], SAT_START, PS_START);
        OR_map(saturn_data[0], &final_data[1], SAT_B, PS_CROSS);
        OR_map(saturn_data[0], &final_data[1], SAT_A, PS_SQUARE);
        OR_map(saturn_data[0], &final_data[1], SAT_Y, PS_TRIANGLE);
        OR_map(saturn_data[0], &final_data[1], SAT_C, PS_CIRCLE);
        OR_map(saturn_data[0], &final_data[1], SAT_Z, PS_R1);
        OR_map(saturn_data[0], &final_data[1], SAT_X, PS_L1);
        OR_map(saturn_data[0], &final_data[1], SAT_R, PS_R2);

        // NES pad button combo for player2 port (select + down) to expand controller functionality, simulates PS_R2 button
        if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_DOWN))){ final_data[1] &= ~_BV(PS_R2);}

        // NES pad button combo for player2 port (select + up) to expand controller functionality, simulates PS_L2 button
        if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_UP))){ final_data[1] &= ~_BV(PS_L2);}
    }
    
    // special mode for Ps2 game "Katamari Damacy" 
    else if(display_tracker == KATAMARI_MODE){
        
        if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){    // if the playstation controller is connected, map the buttons accordingly

            OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP);
            OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN);
            OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT);
            OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT);
            OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT);
            OR_map(dsc_data[0], &final_data[0], PS_START, PS_START);
            OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3);
            OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3);
            OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS);
            OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE);
            OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE);
            OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE);
            OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1);
            OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1);
            OR_map(dsc_data[1], &final_data[0], PS_R2, PS_R3);
            OR_map(dsc_data[1], &final_data[0], PS_R2, PS_L3);
            //OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2);

            // if the playstation controller is in analog mode, map the analog sticks as well
            if(DSC_mode_ID == 0x73){
                FINAL_LJOY_X = DSC_LJOY_X;
                FINAL_RJOY_X = DSC_LJOY_X;
                FINAL_LJOY_Y = DSC_LJOY_Y;
                FINAL_RJOY_Y = DSC_LJOY_Y;
                if((DSC_RJOY_X < 0x64) && (DSC_RJOY_X >= 0x3C)){ FINAL_RJOY_Y = 0x00; FINAL_RJOY_X = 0x80; FINAL_LJOY_Y = 0x80; FINAL_LJOY_X = 0x80;}
                if(DSC_RJOY_X < 0x3C){ FINAL_RJOY_Y = DSC_RJOY_X; FINAL_RJOY_X = 0x80; FINAL_LJOY_Y = (0xFF - DSC_RJOY_X); FINAL_LJOY_X = 0x80;}
                if((DSC_RJOY_X > 0x9C) && (DSC_RJOY_X <= 0xC4)){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_X = 0x80; FINAL_RJOY_Y = 0x80; FINAL_LJOY_X = 0x80;}
                if(DSC_RJOY_X > 0xC4){ FINAL_LJOY_Y = (0xFF - DSC_RJOY_X); FINAL_RJOY_X = 0x80; FINAL_RJOY_Y = DSC_RJOY_X; FINAL_LJOY_X = 0x80;}
            }

            // "katamari roll" macro for L2 button
            if(~dsc_data[1] & _BV(PS_L2)){                        // if L2 button on controller is pressed
                if(!(MSR0 & _BV(MACRO0_ACTIVE))){                // if the macro is not already active
                    MSR0 |= _BV(MACRO0_ACTIVE) | _BV(MACRO0_TOGGLE);    // set the macro active flag
                }
                else if(MSR0 & _BV(MACRO0_ACTIVE)){
                    if((MSR0 & _BV(MACRO0_TOGGLE)) && (katamari_counter < 255)){ FINAL_LJOY_Y = katamari_counter; FINAL_RJOY_Y = (~FINAL_LJOY_Y); katamari_counter = (katamari_counter + 51);}
                    else{ MSR0 &= ~_BV(MACRO0_TOGGLE);}

                    if((~MSR0 & _BV(MACRO0_TOGGLE)) && (katamari_counter > 0)){ FINAL_LJOY_Y = katamari_counter; FINAL_RJOY_Y = (~FINAL_LJOY_Y); katamari_counter = (katamari_counter - 51);}
                    else{ MSR0 |= _BV(MACRO0_TOGGLE);}
                }
            }
            if(dsc_data[1] & _BV(PS_L2)){ MSR0 &= ~_BV(MACRO0_ACTIVE); MSR0 &= ~_BV(MACRO0_TOGGLE); katamari_counter = 0x00;}            
        }

        if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){    // if the Wii nunchuck is connected, map some more stuff

            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[0], NUNCHUCK_Z, PS_R3);
            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[0], NUNCHUCK_Z, PS_L3);
            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_R1);

            remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210);
            remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200);
            FINAL_LJOY_X = remapped_x;
            FINAL_RJOY_X = remapped_x;
            FINAL_LJOY_Y = remapped_y;
            FINAL_RJOY_Y = remapped_y;

            if(remapped_y < 100){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_Y = 0x00;}
            if(remapped_y > 150){ FINAL_LJOY_Y = 0xFF; FINAL_RJOY_Y = 0xFF;}        
            if(NUNCHUCK_JOY_X < 0x6F){ FINAL_LJOY_Y = 0xFF; FINAL_RJOY_Y = 0x00;}
            if(NUNCHUCK_JOY_X > 0xC0){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_Y = 0xFF;}
        }

        if(~saturn_data[1] & _BV(SAT_DOWN)){ FINAL_LJOY_Y = 0xFF; FINAL_RJOY_Y = 0xFF;}
        if(~saturn_data[1] & _BV(SAT_UP)){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_Y = 0x00;}
        if(~saturn_data[1] & _BV(SAT_RIGHT)){ FINAL_LJOY_X = 0xFF; FINAL_RJOY_X = 0xFF;}
        if(~saturn_data[1] & _BV(SAT_LEFT)){ FINAL_LJOY_X = 0x00; FINAL_RJOY_X = 0x00;}
        if(~saturn_data[0] & _BV(SAT_X)){ FINAL_LJOY_Y = 0xFF; FINAL_RJOY_Y = 0x00;}
        if(~saturn_data[0] & _BV(SAT_Z)){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_Y = 0xFF;}
        OR_map(saturn_data[1], &final_data[1], SAT_L, PS_L1);
        OR_map(saturn_data[0], &final_data[0], SAT_START, PS_START);
        OR_map(saturn_data[0], &final_data[1], SAT_B, PS_CROSS);
        OR_map(saturn_data[0], &final_data[1], SAT_A, PS_SQUARE);
        OR_map(saturn_data[0], &final_data[1], SAT_C, PS_CIRCLE);
        OR_map(saturn_data[0], &final_data[1], SAT_R, PS_R1);
        OR_map(saturn_data[0], &final_data[0], SAT_Y, PS_L3);
        OR_map(saturn_data[0], &final_data[0], SAT_Y, PS_R3);
    }

    else if(display_tracker == RACING_MODE){

        if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){    // if the playstation controller is connected, map the buttons accordingly

            OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP);
            OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN);
            OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT);
            OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT);
            OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT);
            OR_map(dsc_data[0], &final_data[0], PS_START, PS_START);
            OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3);
            OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3);
            OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS);
            OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE);
            OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE);
            OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE);
            OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1);
            OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1);
            OR_map(dsc_data[1], &final_data[1], PS_R2, PS_R2);
            OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2);

            // if the playstation controller is in analog mode, map the analog sticks as well
            if(DSC_mode_ID == 0x73){ FINAL_RJOY_X = DSC_RJOY_X; FINAL_RJOY_Y = DSC_RJOY_Y; FINAL_LJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y;}
        }

        if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){    // if the Wii nunchuck is connected, map some more stuff

            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_Z, PS_CROSS);
            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_SQUARE);

            remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210);
            remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200);
            FINAL_LJOY_X = remapped_x;
            FINAL_LJOY_Y = remapped_y;

            map_a2d_if_less(NUNCHUCK_JOY_X, &final_data[0], 0x6F, PS_LEFT);
            map_a2d_if_greater(NUNCHUCK_JOY_X, &final_data[0], 0xC0, PS_RIGHT);
            map_a2d_if_less(NUNCHUCK_JOY_Y, &final_data[0], 0x5F, PS_DOWN);
            map_a2d_if_greater(NUNCHUCK_JOY_Y, &final_data[0], 0xC0, PS_UP);
        }

        OR_map(nes_data[0], &final_data[0], NES_UP, PS_UP);
        OR_map(nes_data[0], &final_data[0], NES_DOWN, PS_DOWN);
        OR_map(nes_data[0], &final_data[0], NES_LEFT, PS_LEFT);
        OR_map(nes_data[0], &final_data[0], NES_RIGHT, PS_RIGHT);
        OR_map(nes_data[0], &final_data[0], NES_START, PS_START);
        OR_map(nes_data[0], &final_data[0], NES_SELECT, PS_SELECT);
        OR_map(nes_data[0], &final_data[1], NES_A, PS_CROSS);
        OR_map(nes_data[0], &final_data[1], NES_B, PS_SQUARE);
        OR_map(nes_data[1], &final_data[0], NES_UP, PS_UP);
        OR_map(nes_data[1], &final_data[0], NES_DOWN, PS_DOWN);
        OR_map(nes_data[1], &final_data[0], NES_LEFT, PS_LEFT);
        OR_map(nes_data[1], &final_data[0], NES_RIGHT, PS_RIGHT);
        OR_map(nes_data[1], &final_data[0], NES_START, PS_R3);
        OR_map(nes_data[1], &final_data[1], NES_A, PS_CROSS);
        OR_map(nes_data[1], &final_data[1], NES_B, PS_CIRCLE);

        OR_map(saturn_data[1], &final_data[0], SAT_UP, PS_UP);
        OR_map(saturn_data[1], &final_data[0], SAT_DOWN, PS_DOWN);
        OR_map(saturn_data[1], &final_data[0], SAT_LEFT, PS_LEFT);
        OR_map(saturn_data[1], &final_data[0], SAT_RIGHT, PS_RIGHT);
        OR_map(saturn_data[0], &final_data[1], SAT_X, PS_L2);
        OR_map(saturn_data[0], &final_data[0], SAT_START, PS_START);
        OR_map(saturn_data[0], &final_data[1], SAT_B, PS_TRIANGLE);
        OR_map(saturn_data[0], &final_data[1], SAT_A, PS_SQUARE);
        OR_map(saturn_data[0], &final_data[1], SAT_Y, PS_CROSS);
        OR_map(saturn_data[0], &final_data[1], SAT_C, PS_CIRCLE);
        OR_map(saturn_data[0], &final_data[1], SAT_R, PS_R1);
        OR_map(saturn_data[1], &final_data[1], SAT_L, PS_L1);
        OR_map(saturn_data[0], &final_data[1], SAT_Z, PS_R2);

        // NES pad button combo for player2 port (select + down) to expand controller functionality, simulates PS_R2 button
        if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_DOWN))){ final_data[1] &= ~_BV(PS_R2);}

        // NES pad button combo for player2 port (select + up) to expand controller functionality, simulates PS_L2 button
        if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_UP))){ final_data[1] &= ~_BV(PS_L2);}
    }

    if(display_tracker == ARCADE_MODE){

        if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){    // if the playstation controller is connected, map the buttons accordingly

            OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP);
            OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN);
            OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT);
            OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT);
            OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT);
            OR_map(dsc_data[0], &final_data[0], PS_START, PS_START);
            OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3);
            OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3);
            OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS);
            OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE);
            OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE);
            OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE);
            OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1);
            OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1);
            OR_map(dsc_data[1], &final_data[1], PS_R2, PS_R2);
            OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2);

            // Ps2 button combo to expand controller functionality simulates PS_R3 button
            if((~dsc_data[1] & _BV(PS_L2)) && (~dsc_data[1] & _BV(PS_R2)) && (~dsc_data[1] & _BV(PS_TRIANGLE)) && (~dsc_data[1] & _BV(PS_CIRCLE)) && (~dsc_data[0] & _BV(PS_UP)) && (~dsc_data[0] & _BV(PS_LEFT))){ final_data[0] &= ~_BV(PS_R3);}

            // if the playstation controller is in analog mode, map the analog sticks as well
            if(DSC_mode_ID == 0x73){ FINAL_RJOY_X = DSC_RJOY_X; FINAL_RJOY_Y = DSC_RJOY_Y; FINAL_LJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y;}
        }

        if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){    // if the Wii nunchuck is connected, map some more stuff

            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_Z, PS_CROSS);
            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_SQUARE);

            remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210);
            remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200);
            FINAL_LJOY_X = remapped_x;
            FINAL_LJOY_Y = remapped_y;

            map_a2d_if_less(NUNCHUCK_JOY_X, &final_data[0], 0x6F, PS_LEFT);
            map_a2d_if_greater(NUNCHUCK_JOY_X, &final_data[0], 0xC0, PS_RIGHT);
            map_a2d_if_less(NUNCHUCK_JOY_Y, &final_data[0], 0x5F, PS_DOWN);
            map_a2d_if_greater(NUNCHUCK_JOY_Y, &final_data[0], 0xC0, PS_UP);
        }

        OR_map(nes_data[0], &final_data[0], NES_UP, PS_UP);
        OR_map(nes_data[0], &final_data[0], NES_DOWN, PS_DOWN);
        OR_map(nes_data[0], &final_data[0], NES_LEFT, PS_LEFT);
        OR_map(nes_data[0], &final_data[0], NES_RIGHT, PS_RIGHT);
        OR_map(nes_data[0], &final_data[0], NES_START, PS_START);
        OR_map(nes_data[0], &final_data[0], NES_SELECT, PS_SELECT);
        OR_map(nes_data[0], &final_data[1], NES_A, PS_CROSS);
        OR_map(nes_data[0], &final_data[1], NES_B, PS_SQUARE);
        OR_map(nes_data[1], &final_data[0], NES_UP, PS_UP);
        OR_map(nes_data[1], &final_data[0], NES_DOWN, PS_DOWN);
        OR_map(nes_data[1], &final_data[0], NES_LEFT, PS_LEFT);
        OR_map(nes_data[1], &final_data[0], NES_RIGHT, PS_RIGHT);
        OR_map(nes_data[1], &final_data[0], NES_START, PS_R3);
        OR_map(nes_data[1], &final_data[1], NES_A, PS_CROSS);
        OR_map(nes_data[1], &final_data[1], NES_B, PS_CIRCLE);

        OR_map(saturn_data[1], &final_data[0], SAT_UP, PS_UP);
        OR_map(saturn_data[1], &final_data[0], SAT_DOWN, PS_DOWN);
        OR_map(saturn_data[1], &final_data[0], SAT_LEFT, PS_LEFT);
        OR_map(saturn_data[1], &final_data[0], SAT_RIGHT, PS_RIGHT);
        OR_map(saturn_data[1], &final_data[0], SAT_L, PS_SELECT);
        OR_map(saturn_data[0], &final_data[0], SAT_START, PS_START);
        OR_map(saturn_data[0], &final_data[1], SAT_B, PS_CROSS);
        OR_map(saturn_data[0], &final_data[1], SAT_A, PS_SQUARE);
        OR_map(saturn_data[0], &final_data[1], SAT_Y, PS_TRIANGLE);
        OR_map(saturn_data[0], &final_data[1], SAT_C, PS_CIRCLE);
        OR_map(saturn_data[0], &final_data[1], SAT_Z, PS_R1);
        OR_map(saturn_data[0], &final_data[1], SAT_X, PS_L1);
        OR_map(saturn_data[0], &final_data[0], SAT_R, PS_R3);

        // NES pad button combo for player2 port (select + down) to expand controller functionality, simulates PS_R2 button
        if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_DOWN))){ final_data[1] &= ~_BV(PS_R2);}

        // NES pad button combo for player2 port (select + up) to expand controller functionality, simulates PS_L2 button
        if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_UP))){ final_data[1] &= ~_BV(PS_L2);}

        // saturn pad button combo to expand controller functionality, simulates PS_R2 button
        if((~saturn_data[1] & _BV(SAT_L)) && (~saturn_data[1] & _BV(SAT_DOWN))){ final_data[1] &= ~_BV(PS_R2);}

        // saturn pad button combo to expand controller functionality, simulates PS_L2 button
        if((~saturn_data[1] & _BV(SAT_L)) && (~saturn_data[1] & _BV(SAT_UP))){ final_data[1] &= ~_BV(PS_L2);}
    }

    else if(display_tracker == TURBO_MODE){

        (turbo_counter < TURBO_RATE) ? (turbo_counter++): (turbo_counter = 0); 

        if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){    // if the playstation controller is connected, map the buttons accordingly

            OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP);
            OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN);
            OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT);
            OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT);
            OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT);
            OR_map(dsc_data[0], &final_data[0], PS_START, PS_START);
            OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3);
            OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3);
            OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS);
            //OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE);
            OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE);
            OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE);
            //OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1);
            OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1);
            OR_map(dsc_data[1], &final_data[1], PS_R2, PS_R2);
            OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2);

            TURBO_MAP(dsc_data[1], final_data[1], PS_SQUARE, PS_SQUARE, TSR0, TURBO0_ACTIVE, TURBO0_TOGGLE);
            TURBO_MAP(dsc_data[1], final_data[1], PS_R1, PS_R1, TSR0, TURBO1_ACTIVE, TURBO1_TOGGLE);

            // if the playstation controller is in analog mode, map the analog sticks as well
            if(DSC_mode_ID == 0x73){ FINAL_RJOY_X = DSC_RJOY_X; FINAL_RJOY_Y = DSC_RJOY_Y; FINAL_LJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y;}
        }

        if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){    // if the Wii nunchuck is connected, map some more stuff

            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_Z, PS_CROSS);
            OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_SQUARE);

            remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210);
            remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200);
            FINAL_LJOY_X = remapped_x;
            FINAL_LJOY_Y = remapped_y;

            map_a2d_if_less(NUNCHUCK_JOY_X, &final_data[0], 0x6F, PS_LEFT);
            map_a2d_if_greater(NUNCHUCK_JOY_X, &final_data[0], 0xC0, PS_RIGHT);
            map_a2d_if_less(NUNCHUCK_JOY_Y, &final_data[0], 0x5F, PS_DOWN);
            map_a2d_if_greater(NUNCHUCK_JOY_Y, &final_data[0], 0xC0, PS_UP);
        }
    }

    else if(display_tracker == SERIAL_IN_MODE){    // Serial input is not yet implimented, currently this is a placeholder
    }


/*END DATA FORMATTING************************************************************************************************/


    }// if skip polling flag is set
    GCSR0 &= ~_BV(SKIP_POLLING_BIT);            // reset skip polling flag to default 0

    // the following checks for a single press of the analog/digital select button and toggles the adapters state accordingly
    if(~ANA_DIG_SELECT_PIN & _BV(ANA_DIG_SELECT)){

        if(!(GCSR0 & _BV(BUTTON0_LOW_STATUS_BIT))){    // BUTTON0_LOW_STATUS_BIT indicates whether or not the button is already being pressed
            if(!(CSR0 & _BV(LOCK_BIT))){        // check if the adapter is already locked in analog mode
                if(CSR0 & _BV(ANALOG_MODE_BIT))            // if analog mode is already active...
                    CSR0 &= ~_BV(ANALOG_MODE_BIT);        // ...turn off analog mode
                else if(!(CSR0 & _BV(ANALOG_MODE_BIT)))        // if analog mode is not active...
                    CSR0 |= _BV(ANALOG_MODE_BIT);        // ...turn on analog mode
            }
        GCSR0 |= _BV(BUTTON0_LOW_STATUS_BIT);        // set BUTTON0_LOW_STATUS_BIT flag so we know the button press has been recognized
        }
    }

    if(ANA_DIG_SELECT_PIN & _BV(ANA_DIG_SELECT))        // if the button is high (default state)...
        GCSR0 &= ~_BV(BUTTON0_LOW_STATUS_BIT);        // ...reset BUTTON0_LOW_STATUS_BIT to wait for next press 

    DISABLE_TWI;            // disable TWI hardware to restart in case of errors on bus

    if(command[1] == 0x42){        // command 0x42 is the main polling command sent continually once the adapter is configured
            LED_PORT |= _BV(STATUS_LED_RED2);        // Red status LED off
            LED_PORT &= ~_BV(STATUS_LED_GREEN2);        // Green status LED on to indicate that everything is cool

            LED_PORT |= _BV(STATUS_LED_GREEN2);    // FOR DEBUGGING
            _delay_us(4);                // FOR DEBUGGING
            LED_PORT &= ~_BV(STATUS_LED_GREEN2);    // FOR DEBUGGING
    }
    else{
            LED_PORT |= _BV(STATUS_LED_GREEN2);        // Green status LED off
            LED_PORT &= ~_BV(STATUS_LED_RED2);        // Red status LED on to indicate that something might be wrong

            LED_PORT |= _BV(STATUS_LED_RED2);    // FOR DEBUGGING
            _delay_us(4);                // FOR DEBUGGING
            LED_PORT &= ~_BV(STATUS_LED_RED2);    // FOR DEBUGGING
    }

    // turns on an LED whenever a command is received to turn on the vibration motors
    if((CSR0 & 0xF0) && (command[1] == 0x42) && ((command[3] != 0x00) || (command[4] != 0x00))){ LED_PORT &= ~_BV(STATUS_LED_MOTOR);}            
    else{ LED_PORT |= _BV(STATUS_LED_MOTOR);}        

    command[1] = 0x00;
    command[3] = 0x00;
    command[4] = 0x00;

    }// if SS line is still high after timeout

    COMM_IS_OK;        // set flag in "CSR0" to allow SPI communication

    // loop waits for call from spi master, if not called in 20ms loop to top to keep everything else going
    for(uint8_t x = 0; ((x < 18) && (SPI_PIN & _BV(SS))); x++){
        START_TIMER_AT(1);
        while((!(TIFR2 & _BV(TOV2))) && (SPI_PIN & _BV(SS)));
        }
        
    }// infinite while(1) loop

    return 0;


}// main loop