SPC music playback tools for real snes apu

Dependencies:   mbed

main.cpp

Committer:
akkera102
Date:
2017-01-09
Revision:
0:5bd52e196edb
Child:
2:62e6e22f8be2

File content as of revision 0:5bd52e196edb:

/* hwapu - SPC music playback tools for real snes apu
 * Copyright (C) 2004-2005  Raphael Assenat <raph@raphnet.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include <stdio.h>
// #include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
// #include <sys/time.h>
// #include "parport.h"
#include "apuplay.h"
#include "apu.h"
#include "id666.h"

#include "apu_ppio.h"
// #include "apu_ppdev.h"
#include "mbed.h"

#ifdef DJGPP
/* todo: use conio */
#define BOLD()
#define NORMAL()

#else
/* use ansi codes */
#define BOLD() printf("%c[36m", 27);
#define NORMAL() printf("%c[0m", 27);
#endif

Serial pc(USBTX, USBRX);
LocalFileSystem local("local");

int g_verbose = 1;
int g_playing = 1;
int g_progress = 1;
int g_debug = 0;
int g_exit_now = 0;
int g_use_embedded = 1;

static void printTime(int seconds);

static APU_ops *apu_ops;

// struct timeval last_int = {0, 0};
Timer last_int;

void signal_handler(int sig)
{
//    struct timeval tv_now;
    int elaps_milli;
    static int first=1;
    
    g_playing = 0;

//    gettimeofday(&tv_now, NULL);    

    if (first)
    {
        last_int.start();
        first = 0;
    }
    else
    {
//        elaps_milli = (tv_now.tv_sec - last_int.tv_sec)*1000;
//        elaps_milli += (tv_now.tv_usec - last_int.tv_usec)/1000;
          elaps_milli = last_int.read_ms();

        if (elaps_milli < 1500) {
            g_exit_now = 1;
        }
    }
    
//    memcpy(&last_int, &tv_now, sizeof(struct timeval));
}

void printhelp(void)
{
    printf("apuplay version %s\n\n", VERSION_STR);
    printf("Usage: ./apuplay [options] spc_file\n\n");
    printf("Supported options:\n\n");
    printf("  -v       Verbose\n");
    printf("  -l       Endless loop mode. Ignore ID666 tag time\n");
    printf("  -s       Display a status line\n");
    printf("  -x       Send the song to the APU and exit. Use -r to stop\n");
    printf("  -r       Just reset the APU and exit. This will stop\n");
    printf("           the current tune.\n");
    printf("  -e       Use a different apu loading algorithm (embedded version)\n");
    printf("           which needs less memory but does more file io. (not\n");
    printf("           significant on a PC. It was used to develop the code\n");
    printf("           which I use on the portable APU player.\n");
    printf("  -d       Debug mode. Adds a lot of verbose output.\n");
#ifdef PPDEV_SUPPORTED
    printf("  -p dev   Use ppdev instead of direct I/O\n");
#endif
#ifdef PPIO_SUPPORTED
    printf("  -i addr  Use direct io with parallel port at given address\n");
#endif
    printf("  -h       Prints this info\n");
}

int main(int argc, char **argv)
{
//    int res, i;
//    int use_ppdev=0;
    int use_ppio=0;
    int io_specified=0;
    int reset_and_exit=0, status_line=1, loop=0, play_and_exit=0;
    char *filename = "/local/test.spc";
    FILE *fptr=NULL;
    id666_tag tag;
//    struct timeval tv_before, tv_now;
    
    signal(SIGINT, signal_handler);

/*
    while((res =getopt(argc, argv, 

                    "rslvhxed"
#ifdef PPDEV_SUPPORTED
                    "p"
#endif
#ifdef PPIO_SUPPORTED
                    "i"
#endif
                    ))>=0)
    {
        switch(res)
        {
            case 'd':
                g_debug = 1;
                break;
            case 'e':
                g_use_embedded = 1;
                break;
            case 'v':
                g_verbose = 1;
                break;
            case 's':
                status_line = 0;
                break;
            case 'l':
                loop = 1;
                break;
            case 'r':
                reset_and_exit = 1;
                break;
            case 'h':
                printhelp();
                return 0;
            case 'x':
                play_and_exit = 1;
                break;
#ifdef PPDEV_SUPPORTED
            case 'p':
                use_ppdev = 1;
                io_specified = 1;
                break;
#endif
#ifdef PPIO_SUPPORTED
            case 'i':
                use_ppio = 1;
                io_specified = 1;
                break;
#endif
            case '?':
                fprintf(stderr, "Unknown argument. try -h\n");
                return -1;
        }
    }

    
    if (argc-optind<=0 && !reset_and_exit) {
        fprintf(stderr, "No file specified. Try -h\n");
        return -2;
    }
*/
#ifdef PPDEV_SUPPORTED
    if (!io_specified) {
        use_ppdev = 1;
        io_specified = 1;
    }
#endif

#ifdef PPIO_SUPPORTED
    if (!io_specified) {
        use_ppio = 1;
        io_specified = 1;
    }
#endif

    if (!io_specified) {
        fprintf(stderr, "No io layer for apu compiled\n");
        return -3;
    }
    
#ifdef PPDEV_SUPPORTED
    if (use_ppdev) {
        apu_ops = apu_ppdev_getOps();
    } 
    else 
#endif

#ifdef PPIO_SUPPORTED
    if (use_ppio)
    {
        apu_ops = apu_ppio_getOps();
    }
#endif


    apu_setOps(apu_ops);

    /* initialize the interface with the module.
     * (Open device, get io permissions, etc...) */
    if (apu_ops->init("")<0) {
        return 1;
    }
    
    if (reset_and_exit) 
    {
        if (g_verbose) { printf("Resetting APU\n"); }                   
        apu_reset();

        return 0;
    }



//    for (i = optind; i<argc; i++)
    for(;;)
    {
        if (g_exit_now) { break; }

//        filename = argv[i];
            
        fptr = fopen(filename, "rb");
        if (fptr==NULL) { perror("fopen"); return 1; }

        read_id666(fptr, &tag);
    
        g_playing = 1;
        printf("Now loading '%s'", filename);
        if (g_use_embedded) {
            printf(" using 'embedded' algo\n");
            if (LoadAPU_embedded(fptr)<0) { break; }
        } else  {
            printf("  \n");
            if (LoadAPU(fptr)<0) { break; }
        }
        if (!g_playing) { continue; } // next
        if (g_exit_now) { break; }

        BOLD(); printf("Title: "); NORMAL();
        printf("%s\n", tag.title);
        BOLD(); printf("Game Title: "); NORMAL();
        printf("%s\n", tag.game_title);
        BOLD(); printf("Dumper: "); NORMAL();
        printf("%s\n", tag.name_of_dumper);
        BOLD(); printf("Comments: "); NORMAL();
        printf("%s\n", tag.comments);
        BOLD(); printf("Seconds: "); NORMAL();
        printf("%s\n", tag.seconds_til_fadeout);

        fclose(fptr);

        if (play_and_exit) {
            return 0;
        }

 //       gettimeofday(&tv_before, NULL);
        
        {
            int elaps_sec;
            int num_sec = atoi(tag.seconds_til_fadeout);
            int last_elaps_sec=-1;
    
            if (num_sec<1 || num_sec>999) {
                num_sec = 150;
            }
            if (strlen(tag.title)==0) {
                strncpy(tag.title, filename, 32);
            }
            
            if (g_exit_now) { break; }
            while (g_playing)
            {
   //             gettimeofday(&tv_now, NULL);
 //               elaps_sec = tv_now.tv_sec - tv_before.tv_sec;
                elaps_sec = last_int.read();
                if ((!loop) && (elaps_sec > num_sec)) { break; }
                
                if (status_line)
                {
                    if (last_elaps_sec != elaps_sec)
                    {
                        if (!loop) {
                            BOLD(); printf("Time: "); NORMAL();
                            printTime(elaps_sec);
                            printf(" [");
                            printTime(num_sec - elaps_sec);
                            printf("] of ");
                            printTime(num_sec);
                            printf(" \r");
                        }
                        else {
                            BOLD(); printf("Time: "); NORMAL();
                            printTime(elaps_sec);
                            printf(" \r");
                        }
                    }
                    last_elaps_sec = elaps_sec;
                    fflush(stdout);
                }
                        
                // usleep(7500); // update every 75 ms
                wait_ms(75);
            }
            if (g_playing)
                printf("\nFinished playing.\n");
            
            apu_reset();
            if (g_exit_now) { break; }
        }
        
    }
    
    apu_reset();

    return 0;
}

static void printTime(int seconds)
{
    int hour=0, min=0, sec=0;

    if (seconds>=3600) {
        hour = seconds/3600;
        seconds -= hour*3600;;
    }
    if (seconds>=60) {
        min = seconds/60;
        seconds -= min*60;
    }
    sec = seconds;

    printf("%02d:%02d:%02d", hour, min, sec);
}