akkera 102
/
apuplay
SPC music playback tools for real snes apu
Diff: main.cpp
- 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