//
// Rotate V1
//
// K.Wilkins July97
//
// V1 - Creation
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <system.h>
#include <machine.h>
#include <mikie.h>

#include <gccore.h>

#include <zlib.h>
#include <unzip.h>

#include "wii_main.h"
#include "wii_util.h"

BOOL cart_is_valid_header( LYNX_HEADER *header )
{
    if( header->magic[0] != 'L' || 
        header->magic[1] != 'Y' || 
        header->magic[2] != 'N' || 
        header->magic[3] != 'X' )
    {
        return FALSE;
    }

    return TRUE;
}

BOOL cart_write_rotatation( char *cartridge, UBYTE rotation, char *message, int message_len )
{
    FILE *filein,*fileout;
    LYNX_HEADER header;
    UBYTE data=0;
    char infile[256];
    char outfile[256];

    strcpy( infile, cartridge );

    char tmp_file[WII_MAX_PATH];
    wii_get_app_relative( "rotate.tmp", tmp_file );
    strcpy( outfile, tmp_file );

    if( ( filein = fopen( infile, "rb" ) ) == NULL )
    {
        snprintf(message, message_len, "ERROR: Couldn't open cartridge for reading" );
        return FALSE;
    }

    if( !fread( &header, sizeof( LYNX_HEADER ), 1, filein ) )
    {
        snprintf(message, message_len, "ERROR: Couldn't read header" );
        fclose(filein);
        return FALSE;
    }

#ifdef MSB_FIRST
    header.page_size_bank0 = ((header.page_size_bank0>>8) | (header.page_size_bank0<<8));
    header.page_size_bank1 = ((header.page_size_bank1>>8) | (header.page_size_bank1<<8));
    header.version         = ((header.version>>8) | (header.version<<8));
#endif

    if( !cart_is_valid_header( &header ) )
    {
        snprintf(message, message_len, "ERROR: Not a LNX format file" );
        fclose(filein);
        return FALSE;
    }

    switch( rotation )
    {
    case MIKIE_NO_ROTATE:
        rotation = CART_NO_ROTATE;
        break;
    case MIKIE_ROTATE_L:
        rotation = CART_ROTATE_LEFT;
        break;
    case MIKIE_ROTATE_R:
        rotation = CART_ROTATE_RIGHT;
        break;
    default:
        rotation = CART_NO_ROTATE;
        break;
    }

    header.rotation=rotation;

    if( ( fileout=fopen( outfile, "wb" ) ) ==NULL )
    {
        snprintf(message, message_len, "ERROR: Couldn't open for writing" );
        fclose(filein);
        return FALSE;
    }

#ifdef MSB_FIRST
    header.page_size_bank0 = ((header.page_size_bank0<<8) | (header.page_size_bank0>>8));
    header.page_size_bank1 = ((header.page_size_bank1<<8) | (header.page_size_bank1>>8));
    header.version         = ((header.version<<8) | (header.version>>8));
#endif

    if( !fwrite( &header,sizeof( LYNX_HEADER ), 1, fileout ) )
    {
        snprintf(message, message_len, "ERROR: Couldn't write header" );
        fclose( filein );
        fclose( fileout );
        remove( outfile );
        return FALSE;
    }

    while( fread( &data, sizeof(UBYTE), 1, filein ) )
    {
        fwrite( &data, sizeof(UBYTE), 1, fileout);
    }

    fclose( filein );
    fclose( fileout );

    remove( infile );
    rename( outfile, infile );

    return TRUE;
}

BOOL cart_is_zip( char *cartridge )
{
    BOOL success = FALSE;
    UBYTE buf[2];
    FILE *fp;

    if( ( fp = fopen( cartridge, "rb" ) ) != NULL )
    {
        fread( buf, 2, 1, fp );
        success = ( memcmp( buf, "PK", 2 ) == 0 );
    }

    if ( fp ) fclose( fp );

    return success;
}

BOOL cart_read_header( char *cartridge, LYNX_HEADER *header )
{
    BOOL success = FALSE;

    if( !cart_is_zip( cartridge ) )
    {
        FILE *filein;
        if( ( filein = fopen( cartridge, "rb" ) ) != NULL )
        {        
            if( fread( header, sizeof( LYNX_HEADER ), 1, filein ) )
            {
                success = TRUE;
            }
        }

        if( filein ) fclose( filein );
    }
    else
    {
        // Try and find a file in the zip
        unzFile *fp;
        
        if( ( fp = (unzFile*)unzOpen( cartridge ) ) != NULL )
        {
            if( unzGoToFirstFile( fp ) == UNZ_OK )
            {
                unz_file_info info;
                char filename_buf[0x100], *ptr;
                BOOL gotIt = FALSE;

                for( ;; )
                {
                    // Get file descriptor and analyse
                    if( unzGetCurrentFileInfo( 
                        fp, &info, filename_buf, 0x100, NULL, 0, NULL, 0 ) 
                            != UNZ_OK )
                    {
                        break;
                    }
                    else
                    {
                        char ext[0x100];
                        Util_getextension( filename_buf, ext );

                        if( !strcmp( ext, "lnx" ) || 
                            !strcmp( ext, "com" ) || 
                            !strcmp( ext, "ext" ) )
                        {
                            // Found a likely file so signal
                            gotIt = TRUE;
                            break;						    
                        }

                        // No match so lets try the next file
                        if( unzGoToNextFile( fp ) != UNZ_OK )	
                            break;
                    }
                }
            
                // Did we strike gold ?
                if( gotIt )
                {
                    if( unzOpenCurrentFile( fp ) == UNZ_OK )
                    {
                        // Read the header
                        if( unzReadCurrentFile( fp, header, 
                            sizeof( LYNX_HEADER ) ) == sizeof( LYNX_HEADER ) )
                        {
                            success = TRUE;
                        }

                        unzCloseCurrentFile( fp );					
                    }
                }                  				
            }
        }

        if( fp ) unzClose( fp );
    }

    if( success )
    {
#ifdef MSB_FIRST
        header->page_size_bank0 = ((header->page_size_bank0>>8) | (header->page_size_bank0<<8));
        header->page_size_bank1 = ((header->page_size_bank1>>8) | (header->page_size_bank1<<8));
        header->version         = ((header->version>>8) | (header->version<<8));
#endif

        if( !cart_is_valid_header( header ) )
        {
            success = FALSE;
        }
    }

    return success;
}
