SPC music playback tools for real snes apu

Dependencies:   mbed

Committer:
akkera102
Date:
Mon Jan 09 13:54:39 2017 +0000
Revision:
0:5bd52e196edb
Child:
2:62e6e22f8be2
first

Who changed what in which revision?

UserRevisionLine numberNew contents of line
akkera102 0:5bd52e196edb 1 /* hwapu - SPC music playback tools for real snes apu
akkera102 0:5bd52e196edb 2 * Copyright (C) 2004-2005 Raphael Assenat <raph@raphnet.net>
akkera102 0:5bd52e196edb 3 *
akkera102 0:5bd52e196edb 4 * This program is free software; you can redistribute it and/or modify
akkera102 0:5bd52e196edb 5 * it under the terms of the GNU General Public License as published by
akkera102 0:5bd52e196edb 6 * the Free Software Foundation; either version 2 of the License, or
akkera102 0:5bd52e196edb 7 * (at your option) any later version.
akkera102 0:5bd52e196edb 8 *
akkera102 0:5bd52e196edb 9 * This program is distributed in the hope that it will be useful,
akkera102 0:5bd52e196edb 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
akkera102 0:5bd52e196edb 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
akkera102 0:5bd52e196edb 12 * GNU General Public License for more details.
akkera102 0:5bd52e196edb 13 *
akkera102 0:5bd52e196edb 14 * You should have received a copy of the GNU General Public License
akkera102 0:5bd52e196edb 15 * along with this program; if not, write to the Free Software
akkera102 0:5bd52e196edb 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
akkera102 0:5bd52e196edb 17 */
akkera102 0:5bd52e196edb 18 #include <stdio.h>
akkera102 0:5bd52e196edb 19 // #include <unistd.h>
akkera102 0:5bd52e196edb 20 #include <stdlib.h>
akkera102 0:5bd52e196edb 21 #include <string.h>
akkera102 0:5bd52e196edb 22 #include <signal.h>
akkera102 0:5bd52e196edb 23 // #include <sys/time.h>
akkera102 0:5bd52e196edb 24 // #include "parport.h"
akkera102 0:5bd52e196edb 25 #include "apuplay.h"
akkera102 0:5bd52e196edb 26 #include "apu.h"
akkera102 0:5bd52e196edb 27 #include "id666.h"
akkera102 0:5bd52e196edb 28
akkera102 0:5bd52e196edb 29 #include "apu_ppio.h"
akkera102 0:5bd52e196edb 30 // #include "apu_ppdev.h"
akkera102 0:5bd52e196edb 31 #include "mbed.h"
akkera102 0:5bd52e196edb 32
akkera102 0:5bd52e196edb 33 #ifdef DJGPP
akkera102 0:5bd52e196edb 34 /* todo: use conio */
akkera102 0:5bd52e196edb 35 #define BOLD()
akkera102 0:5bd52e196edb 36 #define NORMAL()
akkera102 0:5bd52e196edb 37
akkera102 0:5bd52e196edb 38 #else
akkera102 0:5bd52e196edb 39 /* use ansi codes */
akkera102 0:5bd52e196edb 40 #define BOLD() printf("%c[36m", 27);
akkera102 0:5bd52e196edb 41 #define NORMAL() printf("%c[0m", 27);
akkera102 0:5bd52e196edb 42 #endif
akkera102 0:5bd52e196edb 43
akkera102 0:5bd52e196edb 44 Serial pc(USBTX, USBRX);
akkera102 0:5bd52e196edb 45 LocalFileSystem local("local");
akkera102 0:5bd52e196edb 46
akkera102 0:5bd52e196edb 47 int g_verbose = 1;
akkera102 0:5bd52e196edb 48 int g_playing = 1;
akkera102 0:5bd52e196edb 49 int g_progress = 1;
akkera102 0:5bd52e196edb 50 int g_debug = 0;
akkera102 0:5bd52e196edb 51 int g_exit_now = 0;
akkera102 0:5bd52e196edb 52 int g_use_embedded = 1;
akkera102 0:5bd52e196edb 53
akkera102 0:5bd52e196edb 54 static void printTime(int seconds);
akkera102 0:5bd52e196edb 55
akkera102 0:5bd52e196edb 56 static APU_ops *apu_ops;
akkera102 0:5bd52e196edb 57
akkera102 0:5bd52e196edb 58 // struct timeval last_int = {0, 0};
akkera102 0:5bd52e196edb 59 Timer last_int;
akkera102 0:5bd52e196edb 60
akkera102 0:5bd52e196edb 61 void signal_handler(int sig)
akkera102 0:5bd52e196edb 62 {
akkera102 0:5bd52e196edb 63 // struct timeval tv_now;
akkera102 0:5bd52e196edb 64 int elaps_milli;
akkera102 0:5bd52e196edb 65 static int first=1;
akkera102 0:5bd52e196edb 66
akkera102 0:5bd52e196edb 67 g_playing = 0;
akkera102 0:5bd52e196edb 68
akkera102 0:5bd52e196edb 69 // gettimeofday(&tv_now, NULL);
akkera102 0:5bd52e196edb 70
akkera102 0:5bd52e196edb 71 if (first)
akkera102 0:5bd52e196edb 72 {
akkera102 0:5bd52e196edb 73 last_int.start();
akkera102 0:5bd52e196edb 74 first = 0;
akkera102 0:5bd52e196edb 75 }
akkera102 0:5bd52e196edb 76 else
akkera102 0:5bd52e196edb 77 {
akkera102 0:5bd52e196edb 78 // elaps_milli = (tv_now.tv_sec - last_int.tv_sec)*1000;
akkera102 0:5bd52e196edb 79 // elaps_milli += (tv_now.tv_usec - last_int.tv_usec)/1000;
akkera102 0:5bd52e196edb 80 elaps_milli = last_int.read_ms();
akkera102 0:5bd52e196edb 81
akkera102 0:5bd52e196edb 82 if (elaps_milli < 1500) {
akkera102 0:5bd52e196edb 83 g_exit_now = 1;
akkera102 0:5bd52e196edb 84 }
akkera102 0:5bd52e196edb 85 }
akkera102 0:5bd52e196edb 86
akkera102 0:5bd52e196edb 87 // memcpy(&last_int, &tv_now, sizeof(struct timeval));
akkera102 0:5bd52e196edb 88 }
akkera102 0:5bd52e196edb 89
akkera102 0:5bd52e196edb 90 void printhelp(void)
akkera102 0:5bd52e196edb 91 {
akkera102 0:5bd52e196edb 92 printf("apuplay version %s\n\n", VERSION_STR);
akkera102 0:5bd52e196edb 93 printf("Usage: ./apuplay [options] spc_file\n\n");
akkera102 0:5bd52e196edb 94 printf("Supported options:\n\n");
akkera102 0:5bd52e196edb 95 printf(" -v Verbose\n");
akkera102 0:5bd52e196edb 96 printf(" -l Endless loop mode. Ignore ID666 tag time\n");
akkera102 0:5bd52e196edb 97 printf(" -s Display a status line\n");
akkera102 0:5bd52e196edb 98 printf(" -x Send the song to the APU and exit. Use -r to stop\n");
akkera102 0:5bd52e196edb 99 printf(" -r Just reset the APU and exit. This will stop\n");
akkera102 0:5bd52e196edb 100 printf(" the current tune.\n");
akkera102 0:5bd52e196edb 101 printf(" -e Use a different apu loading algorithm (embedded version)\n");
akkera102 0:5bd52e196edb 102 printf(" which needs less memory but does more file io. (not\n");
akkera102 0:5bd52e196edb 103 printf(" significant on a PC. It was used to develop the code\n");
akkera102 0:5bd52e196edb 104 printf(" which I use on the portable APU player.\n");
akkera102 0:5bd52e196edb 105 printf(" -d Debug mode. Adds a lot of verbose output.\n");
akkera102 0:5bd52e196edb 106 #ifdef PPDEV_SUPPORTED
akkera102 0:5bd52e196edb 107 printf(" -p dev Use ppdev instead of direct I/O\n");
akkera102 0:5bd52e196edb 108 #endif
akkera102 0:5bd52e196edb 109 #ifdef PPIO_SUPPORTED
akkera102 0:5bd52e196edb 110 printf(" -i addr Use direct io with parallel port at given address\n");
akkera102 0:5bd52e196edb 111 #endif
akkera102 0:5bd52e196edb 112 printf(" -h Prints this info\n");
akkera102 0:5bd52e196edb 113 }
akkera102 0:5bd52e196edb 114
akkera102 0:5bd52e196edb 115 int main(int argc, char **argv)
akkera102 0:5bd52e196edb 116 {
akkera102 0:5bd52e196edb 117 // int res, i;
akkera102 0:5bd52e196edb 118 // int use_ppdev=0;
akkera102 0:5bd52e196edb 119 int use_ppio=0;
akkera102 0:5bd52e196edb 120 int io_specified=0;
akkera102 0:5bd52e196edb 121 int reset_and_exit=0, status_line=1, loop=0, play_and_exit=0;
akkera102 0:5bd52e196edb 122 char *filename = "/local/test.spc";
akkera102 0:5bd52e196edb 123 FILE *fptr=NULL;
akkera102 0:5bd52e196edb 124 id666_tag tag;
akkera102 0:5bd52e196edb 125 // struct timeval tv_before, tv_now;
akkera102 0:5bd52e196edb 126
akkera102 0:5bd52e196edb 127 signal(SIGINT, signal_handler);
akkera102 0:5bd52e196edb 128
akkera102 0:5bd52e196edb 129 /*
akkera102 0:5bd52e196edb 130 while((res =getopt(argc, argv,
akkera102 0:5bd52e196edb 131
akkera102 0:5bd52e196edb 132 "rslvhxed"
akkera102 0:5bd52e196edb 133 #ifdef PPDEV_SUPPORTED
akkera102 0:5bd52e196edb 134 "p"
akkera102 0:5bd52e196edb 135 #endif
akkera102 0:5bd52e196edb 136 #ifdef PPIO_SUPPORTED
akkera102 0:5bd52e196edb 137 "i"
akkera102 0:5bd52e196edb 138 #endif
akkera102 0:5bd52e196edb 139 ))>=0)
akkera102 0:5bd52e196edb 140 {
akkera102 0:5bd52e196edb 141 switch(res)
akkera102 0:5bd52e196edb 142 {
akkera102 0:5bd52e196edb 143 case 'd':
akkera102 0:5bd52e196edb 144 g_debug = 1;
akkera102 0:5bd52e196edb 145 break;
akkera102 0:5bd52e196edb 146 case 'e':
akkera102 0:5bd52e196edb 147 g_use_embedded = 1;
akkera102 0:5bd52e196edb 148 break;
akkera102 0:5bd52e196edb 149 case 'v':
akkera102 0:5bd52e196edb 150 g_verbose = 1;
akkera102 0:5bd52e196edb 151 break;
akkera102 0:5bd52e196edb 152 case 's':
akkera102 0:5bd52e196edb 153 status_line = 0;
akkera102 0:5bd52e196edb 154 break;
akkera102 0:5bd52e196edb 155 case 'l':
akkera102 0:5bd52e196edb 156 loop = 1;
akkera102 0:5bd52e196edb 157 break;
akkera102 0:5bd52e196edb 158 case 'r':
akkera102 0:5bd52e196edb 159 reset_and_exit = 1;
akkera102 0:5bd52e196edb 160 break;
akkera102 0:5bd52e196edb 161 case 'h':
akkera102 0:5bd52e196edb 162 printhelp();
akkera102 0:5bd52e196edb 163 return 0;
akkera102 0:5bd52e196edb 164 case 'x':
akkera102 0:5bd52e196edb 165 play_and_exit = 1;
akkera102 0:5bd52e196edb 166 break;
akkera102 0:5bd52e196edb 167 #ifdef PPDEV_SUPPORTED
akkera102 0:5bd52e196edb 168 case 'p':
akkera102 0:5bd52e196edb 169 use_ppdev = 1;
akkera102 0:5bd52e196edb 170 io_specified = 1;
akkera102 0:5bd52e196edb 171 break;
akkera102 0:5bd52e196edb 172 #endif
akkera102 0:5bd52e196edb 173 #ifdef PPIO_SUPPORTED
akkera102 0:5bd52e196edb 174 case 'i':
akkera102 0:5bd52e196edb 175 use_ppio = 1;
akkera102 0:5bd52e196edb 176 io_specified = 1;
akkera102 0:5bd52e196edb 177 break;
akkera102 0:5bd52e196edb 178 #endif
akkera102 0:5bd52e196edb 179 case '?':
akkera102 0:5bd52e196edb 180 fprintf(stderr, "Unknown argument. try -h\n");
akkera102 0:5bd52e196edb 181 return -1;
akkera102 0:5bd52e196edb 182 }
akkera102 0:5bd52e196edb 183 }
akkera102 0:5bd52e196edb 184
akkera102 0:5bd52e196edb 185
akkera102 0:5bd52e196edb 186 if (argc-optind<=0 && !reset_and_exit) {
akkera102 0:5bd52e196edb 187 fprintf(stderr, "No file specified. Try -h\n");
akkera102 0:5bd52e196edb 188 return -2;
akkera102 0:5bd52e196edb 189 }
akkera102 0:5bd52e196edb 190 */
akkera102 0:5bd52e196edb 191 #ifdef PPDEV_SUPPORTED
akkera102 0:5bd52e196edb 192 if (!io_specified) {
akkera102 0:5bd52e196edb 193 use_ppdev = 1;
akkera102 0:5bd52e196edb 194 io_specified = 1;
akkera102 0:5bd52e196edb 195 }
akkera102 0:5bd52e196edb 196 #endif
akkera102 0:5bd52e196edb 197
akkera102 0:5bd52e196edb 198 #ifdef PPIO_SUPPORTED
akkera102 0:5bd52e196edb 199 if (!io_specified) {
akkera102 0:5bd52e196edb 200 use_ppio = 1;
akkera102 0:5bd52e196edb 201 io_specified = 1;
akkera102 0:5bd52e196edb 202 }
akkera102 0:5bd52e196edb 203 #endif
akkera102 0:5bd52e196edb 204
akkera102 0:5bd52e196edb 205 if (!io_specified) {
akkera102 0:5bd52e196edb 206 fprintf(stderr, "No io layer for apu compiled\n");
akkera102 0:5bd52e196edb 207 return -3;
akkera102 0:5bd52e196edb 208 }
akkera102 0:5bd52e196edb 209
akkera102 0:5bd52e196edb 210 #ifdef PPDEV_SUPPORTED
akkera102 0:5bd52e196edb 211 if (use_ppdev) {
akkera102 0:5bd52e196edb 212 apu_ops = apu_ppdev_getOps();
akkera102 0:5bd52e196edb 213 }
akkera102 0:5bd52e196edb 214 else
akkera102 0:5bd52e196edb 215 #endif
akkera102 0:5bd52e196edb 216
akkera102 0:5bd52e196edb 217 #ifdef PPIO_SUPPORTED
akkera102 0:5bd52e196edb 218 if (use_ppio)
akkera102 0:5bd52e196edb 219 {
akkera102 0:5bd52e196edb 220 apu_ops = apu_ppio_getOps();
akkera102 0:5bd52e196edb 221 }
akkera102 0:5bd52e196edb 222 #endif
akkera102 0:5bd52e196edb 223
akkera102 0:5bd52e196edb 224
akkera102 0:5bd52e196edb 225 apu_setOps(apu_ops);
akkera102 0:5bd52e196edb 226
akkera102 0:5bd52e196edb 227 /* initialize the interface with the module.
akkera102 0:5bd52e196edb 228 * (Open device, get io permissions, etc...) */
akkera102 0:5bd52e196edb 229 if (apu_ops->init("")<0) {
akkera102 0:5bd52e196edb 230 return 1;
akkera102 0:5bd52e196edb 231 }
akkera102 0:5bd52e196edb 232
akkera102 0:5bd52e196edb 233 if (reset_and_exit)
akkera102 0:5bd52e196edb 234 {
akkera102 0:5bd52e196edb 235 if (g_verbose) { printf("Resetting APU\n"); }
akkera102 0:5bd52e196edb 236 apu_reset();
akkera102 0:5bd52e196edb 237
akkera102 0:5bd52e196edb 238 return 0;
akkera102 0:5bd52e196edb 239 }
akkera102 0:5bd52e196edb 240
akkera102 0:5bd52e196edb 241
akkera102 0:5bd52e196edb 242
akkera102 0:5bd52e196edb 243 // for (i = optind; i<argc; i++)
akkera102 0:5bd52e196edb 244 for(;;)
akkera102 0:5bd52e196edb 245 {
akkera102 0:5bd52e196edb 246 if (g_exit_now) { break; }
akkera102 0:5bd52e196edb 247
akkera102 0:5bd52e196edb 248 // filename = argv[i];
akkera102 0:5bd52e196edb 249
akkera102 0:5bd52e196edb 250 fptr = fopen(filename, "rb");
akkera102 0:5bd52e196edb 251 if (fptr==NULL) { perror("fopen"); return 1; }
akkera102 0:5bd52e196edb 252
akkera102 0:5bd52e196edb 253 read_id666(fptr, &tag);
akkera102 0:5bd52e196edb 254
akkera102 0:5bd52e196edb 255 g_playing = 1;
akkera102 0:5bd52e196edb 256 printf("Now loading '%s'", filename);
akkera102 0:5bd52e196edb 257 if (g_use_embedded) {
akkera102 0:5bd52e196edb 258 printf(" using 'embedded' algo\n");
akkera102 0:5bd52e196edb 259 if (LoadAPU_embedded(fptr)<0) { break; }
akkera102 0:5bd52e196edb 260 } else {
akkera102 0:5bd52e196edb 261 printf(" \n");
akkera102 0:5bd52e196edb 262 if (LoadAPU(fptr)<0) { break; }
akkera102 0:5bd52e196edb 263 }
akkera102 0:5bd52e196edb 264 if (!g_playing) { continue; } // next
akkera102 0:5bd52e196edb 265 if (g_exit_now) { break; }
akkera102 0:5bd52e196edb 266
akkera102 0:5bd52e196edb 267 BOLD(); printf("Title: "); NORMAL();
akkera102 0:5bd52e196edb 268 printf("%s\n", tag.title);
akkera102 0:5bd52e196edb 269 BOLD(); printf("Game Title: "); NORMAL();
akkera102 0:5bd52e196edb 270 printf("%s\n", tag.game_title);
akkera102 0:5bd52e196edb 271 BOLD(); printf("Dumper: "); NORMAL();
akkera102 0:5bd52e196edb 272 printf("%s\n", tag.name_of_dumper);
akkera102 0:5bd52e196edb 273 BOLD(); printf("Comments: "); NORMAL();
akkera102 0:5bd52e196edb 274 printf("%s\n", tag.comments);
akkera102 0:5bd52e196edb 275 BOLD(); printf("Seconds: "); NORMAL();
akkera102 0:5bd52e196edb 276 printf("%s\n", tag.seconds_til_fadeout);
akkera102 0:5bd52e196edb 277
akkera102 0:5bd52e196edb 278 fclose(fptr);
akkera102 0:5bd52e196edb 279
akkera102 0:5bd52e196edb 280 if (play_and_exit) {
akkera102 0:5bd52e196edb 281 return 0;
akkera102 0:5bd52e196edb 282 }
akkera102 0:5bd52e196edb 283
akkera102 0:5bd52e196edb 284 // gettimeofday(&tv_before, NULL);
akkera102 0:5bd52e196edb 285
akkera102 0:5bd52e196edb 286 {
akkera102 0:5bd52e196edb 287 int elaps_sec;
akkera102 0:5bd52e196edb 288 int num_sec = atoi(tag.seconds_til_fadeout);
akkera102 0:5bd52e196edb 289 int last_elaps_sec=-1;
akkera102 0:5bd52e196edb 290
akkera102 0:5bd52e196edb 291 if (num_sec<1 || num_sec>999) {
akkera102 0:5bd52e196edb 292 num_sec = 150;
akkera102 0:5bd52e196edb 293 }
akkera102 0:5bd52e196edb 294 if (strlen(tag.title)==0) {
akkera102 0:5bd52e196edb 295 strncpy(tag.title, filename, 32);
akkera102 0:5bd52e196edb 296 }
akkera102 0:5bd52e196edb 297
akkera102 0:5bd52e196edb 298 if (g_exit_now) { break; }
akkera102 0:5bd52e196edb 299 while (g_playing)
akkera102 0:5bd52e196edb 300 {
akkera102 0:5bd52e196edb 301 // gettimeofday(&tv_now, NULL);
akkera102 0:5bd52e196edb 302 // elaps_sec = tv_now.tv_sec - tv_before.tv_sec;
akkera102 0:5bd52e196edb 303 elaps_sec = last_int.read();
akkera102 0:5bd52e196edb 304 if ((!loop) && (elaps_sec > num_sec)) { break; }
akkera102 0:5bd52e196edb 305
akkera102 0:5bd52e196edb 306 if (status_line)
akkera102 0:5bd52e196edb 307 {
akkera102 0:5bd52e196edb 308 if (last_elaps_sec != elaps_sec)
akkera102 0:5bd52e196edb 309 {
akkera102 0:5bd52e196edb 310 if (!loop) {
akkera102 0:5bd52e196edb 311 BOLD(); printf("Time: "); NORMAL();
akkera102 0:5bd52e196edb 312 printTime(elaps_sec);
akkera102 0:5bd52e196edb 313 printf(" [");
akkera102 0:5bd52e196edb 314 printTime(num_sec - elaps_sec);
akkera102 0:5bd52e196edb 315 printf("] of ");
akkera102 0:5bd52e196edb 316 printTime(num_sec);
akkera102 0:5bd52e196edb 317 printf(" \r");
akkera102 0:5bd52e196edb 318 }
akkera102 0:5bd52e196edb 319 else {
akkera102 0:5bd52e196edb 320 BOLD(); printf("Time: "); NORMAL();
akkera102 0:5bd52e196edb 321 printTime(elaps_sec);
akkera102 0:5bd52e196edb 322 printf(" \r");
akkera102 0:5bd52e196edb 323 }
akkera102 0:5bd52e196edb 324 }
akkera102 0:5bd52e196edb 325 last_elaps_sec = elaps_sec;
akkera102 0:5bd52e196edb 326 fflush(stdout);
akkera102 0:5bd52e196edb 327 }
akkera102 0:5bd52e196edb 328
akkera102 0:5bd52e196edb 329 // usleep(7500); // update every 75 ms
akkera102 0:5bd52e196edb 330 wait_ms(75);
akkera102 0:5bd52e196edb 331 }
akkera102 0:5bd52e196edb 332 if (g_playing)
akkera102 0:5bd52e196edb 333 printf("\nFinished playing.\n");
akkera102 0:5bd52e196edb 334
akkera102 0:5bd52e196edb 335 apu_reset();
akkera102 0:5bd52e196edb 336 if (g_exit_now) { break; }
akkera102 0:5bd52e196edb 337 }
akkera102 0:5bd52e196edb 338
akkera102 0:5bd52e196edb 339 }
akkera102 0:5bd52e196edb 340
akkera102 0:5bd52e196edb 341 apu_reset();
akkera102 0:5bd52e196edb 342
akkera102 0:5bd52e196edb 343 return 0;
akkera102 0:5bd52e196edb 344 }
akkera102 0:5bd52e196edb 345
akkera102 0:5bd52e196edb 346 static void printTime(int seconds)
akkera102 0:5bd52e196edb 347 {
akkera102 0:5bd52e196edb 348 int hour=0, min=0, sec=0;
akkera102 0:5bd52e196edb 349
akkera102 0:5bd52e196edb 350 if (seconds>=3600) {
akkera102 0:5bd52e196edb 351 hour = seconds/3600;
akkera102 0:5bd52e196edb 352 seconds -= hour*3600;;
akkera102 0:5bd52e196edb 353 }
akkera102 0:5bd52e196edb 354 if (seconds>=60) {
akkera102 0:5bd52e196edb 355 min = seconds/60;
akkera102 0:5bd52e196edb 356 seconds -= min*60;
akkera102 0:5bd52e196edb 357 }
akkera102 0:5bd52e196edb 358 sec = seconds;
akkera102 0:5bd52e196edb 359
akkera102 0:5bd52e196edb 360 printf("%02d:%02d:%02d", hour, min, sec);
akkera102 0:5bd52e196edb 361 }