SPC music playback tools for real snes apu

Dependencies:   mbed

Revision:
0:5bd52e196edb
Child:
2:62e6e22f8be2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Jan 09 13:54:39 2017 +0000
@@ -0,0 +1,361 @@
+/* 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);
+}
\ No newline at end of file