1 /*
2 ** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)
3 **
4 **
5 ** This program is free software; you can redistribute it and/or
6 ** modify it under the terms of version 2 of the GNU Library General
7 ** Public License as published by the Free Software Foundation.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 ** Library General Public License for more details.  To obtain a
13 ** copy of the GNU Library General Public License, write to the Free
14 ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 **
16 ** Any permitted reproduction of these routines, in whole or in part,
17 ** must bear this legend.
18 **
19 **
20 ** nsf.c
21 **
22 ** NSF loading/saving related functions
23 ** $Id: nsf.c,v 1.3 2003/05/01 22:34:20 benjihan Exp $
24 */
25 
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include "types.h"
30 #include "nsf.h"
31 #include "log.h"
32 #include "nes6502.h"
33 #include "nes_apu.h"
34 #include "vrcvisnd.h"
35 #include "vrc7_snd.h"
36 #include "mmc5_snd.h"
37 #include "fds_snd.h"
38 
39 /* TODO: bleh! should encapsulate in NSF */
40 #define  MAX_ADDRESS_HANDLERS    32
41 static nes6502_memread nsf_readhandler[MAX_ADDRESS_HANDLERS];
42 static nes6502_memwrite nsf_writehandler[MAX_ADDRESS_HANDLERS];
43 
44 static nsf_t *cur_nsf = NULL;
45 
46 static void nsf_setcontext(nsf_t *nsf)
47 {
48    ASSERT(nsf);
49    cur_nsf = nsf;
50 }
51 
52 static uint8 read_mirrored_ram(uint32 address)
53 {
54   nes6502_chk_mem_access(&cur_nsf->cpu->acc_mem_page[0][address & 0x7FF],
55 			 NES6502_READ_ACCESS);
56   return cur_nsf->cpu->mem_page[0][address & 0x7FF];
57 }
58 
59 static void write_mirrored_ram(uint32 address, uint8 value)
60 {
61   nes6502_chk_mem_access(&cur_nsf->cpu->acc_mem_page[0][address & 0x7FF],
62 			 NES6502_WRITE_ACCESS);
63   cur_nsf->cpu->mem_page[0][address & 0x7FF] = value;
64 }
65 
66 /* can be used for both banked and non-bankswitched NSFs */
67 static void nsf_bankswitch(uint32 address, uint8 value)
68 {
69    int cpu_page;
70    int roffset;
71    uint8 *offset;
72 
73    cpu_page = address & 0x0F;
74    roffset = -(cur_nsf->load_addr & 0x0FFF) + ((int)value << 12);
75    offset = cur_nsf->data + roffset;
76 
77    nes6502_getcontext(cur_nsf->cpu);
78    cur_nsf->cpu->mem_page[cpu_page] = offset;
79 #ifdef NES6502_MEM_ACCESS_CTRL
80    cur_nsf->cpu->acc_mem_page[cpu_page] = offset + cur_nsf->length;
81 #endif
82    nes6502_setcontext(cur_nsf->cpu);
83 }
84 
85 static nes6502_memread default_readhandler[] =
86 {
87    { 0x0800, 0x1FFF, read_mirrored_ram },
88    { 0x4000, 0x4017, apu_read },
89    { -1,     -1,     NULL }
90 };
91 
92 static nes6502_memwrite default_writehandler[] =
93 {
94    { 0x0800, 0x1FFF, write_mirrored_ram },
95    { 0x4000, 0x4017, apu_write },
96    { 0x5FF6, 0x5FFF, nsf_bankswitch },
97    { -1,     -1,     NULL}
98 };
99 
100 static uint8 invalid_read(uint32 address)
101 {
102 #ifdef NOFRENDO_DEBUG
103    log_printf("filthy NSF read from $%04X\n", address);
104 #endif /* NOFRENDO_DEBUG */
105 
106    return 0xFF;
107 }
108 
109 static void invalid_write(uint32 address, uint8 value)
110 {
111 #ifdef NOFRENDO_DEBUG
112    log_printf("filthy NSF tried to write $%02X to $%04X\n", value, address);
113 #endif /* NOFRENDO_DEBUG */
114 }
115 
116 /* set up the address handlers that the CPU uses */
117 static void build_address_handlers(nsf_t *nsf)
118 {
119    int count, num_handlers;
120 
121    memset(nsf_readhandler, 0, sizeof(nsf_readhandler));
122    memset(nsf_writehandler, 0, sizeof(nsf_writehandler));
123 
124    num_handlers = 0;
125    for (count = 0; num_handlers < MAX_ADDRESS_HANDLERS; count++, num_handlers++)
126    {
127       if (NULL == default_readhandler[count].read_func)
128          break;
129 
130       memcpy(&nsf_readhandler[num_handlers], &default_readhandler[count],
131              sizeof(nes6502_memread));
132    }
133 
134    if (nsf->apu->ext)
135    {
136       if (NULL != nsf->apu->ext->mem_read)
137       {
138          for (count = 0; num_handlers < MAX_ADDRESS_HANDLERS; count++, num_handlers++)
139          {
140             if (NULL == nsf->apu->ext->mem_read[count].read_func)
141                break;
142 
143             memcpy(&nsf_readhandler[num_handlers], &nsf->apu->ext->mem_read[count],
144                    sizeof(nes6502_memread));
145          }
146       }
147    }
148 
149    /* catch-all for bad reads */
150    nsf_readhandler[num_handlers].min_range = 0x2000; /* min address */
151    nsf_readhandler[num_handlers].max_range = 0x5BFF; /* max address */
152    nsf_readhandler[num_handlers].read_func = invalid_read; /* handler */
153    num_handlers++;
154    nsf_readhandler[num_handlers].min_range = -1;
155    nsf_readhandler[num_handlers].max_range = -1;
156    nsf_readhandler[num_handlers].read_func = NULL;
157    num_handlers++;
158    ASSERT(num_handlers <= MAX_ADDRESS_HANDLERS);
159 
160    num_handlers = 0;
161    for (count = 0; num_handlers < MAX_ADDRESS_HANDLERS; count++, num_handlers++)
162    {
163       if (NULL == default_writehandler[count].write_func)
164          break;
165 
166       memcpy(&nsf_writehandler[num_handlers], &default_writehandler[count],
167              sizeof(nes6502_memwrite));
168    }
169 
170    if (nsf->apu->ext)
171    {
172       if (NULL != nsf->apu->ext->mem_write)
173       {
174          for (count = 0; num_handlers < MAX_ADDRESS_HANDLERS; count++, num_handlers++)
175          {
176             if (NULL == nsf->apu->ext->mem_write[count].write_func)
177                break;
178 
179             memcpy(&nsf_writehandler[num_handlers], &nsf->apu->ext->mem_write[count],
180                    sizeof(nes6502_memwrite));
181          }
182       }
183    }
184 
185    /* catch-all for bad writes */
186    nsf_writehandler[num_handlers].min_range = 0x2000; /* min address */
187    nsf_writehandler[num_handlers].max_range = 0x5BFF; /* max address */
188    nsf_writehandler[num_handlers].write_func = invalid_write; /* handler */
189    num_handlers++;
190    /* protect region at $8000-$FFFF */
191    nsf_writehandler[num_handlers].min_range = 0x8000; /* min address */
192    nsf_writehandler[num_handlers].max_range = 0xFFFF; /* max address */
193    nsf_writehandler[num_handlers].write_func = invalid_write; /* handler */
194    num_handlers++;
195    nsf_writehandler[num_handlers].min_range = -1;
196    nsf_writehandler[num_handlers].max_range = -1;
197    nsf_writehandler[num_handlers].write_func = NULL;
198    num_handlers++;
199    ASSERT(num_handlers <= MAX_ADDRESS_HANDLERS);
200 }
201 
202 #define  NSF_ROUTINE_LOC   0x5000
203 
204 /* sets up a simple loop that calls the desired routine and spins */
205 static void nsf_setup_routine(uint32 address, uint8 a_reg, uint8 x_reg)
206 {
207    uint8 *mem;
208 
209    nes6502_getcontext(cur_nsf->cpu);
210    mem = cur_nsf->cpu->mem_page[NSF_ROUTINE_LOC >> 12] + (NSF_ROUTINE_LOC & 0x0FFF);
211 
212    /* our lovely 4-byte 6502 NSF player */
213    mem[0] = 0x20;            /* JSR address */
214    mem[1] = address & 0xFF;
215    mem[2] = address >> 8;
216    mem[3] = 0xF2;            /* JAM (cpu kill op) */
217 
218    cur_nsf->cpu->pc_reg = NSF_ROUTINE_LOC;
219    cur_nsf->cpu->a_reg = a_reg;
220    cur_nsf->cpu->x_reg = x_reg;
221    cur_nsf->cpu->y_reg = 0;
222    cur_nsf->cpu->s_reg = 0xFF;
223 
224    nes6502_setcontext(cur_nsf->cpu);
225 }
226 
227 /* retrieve any external soundchip driver */
228 static apuext_t *nsf_getext(nsf_t *nsf)
229 {
230    switch (nsf->ext_sound_type)
231    {
232    case EXT_SOUND_VRCVI:
233       return &vrcvi_ext;
234 
235    case EXT_SOUND_VRCVII:
236       return &vrc7_ext;
237 
238    case EXT_SOUND_FDS:
239       return &fds_ext;
240 
241    case EXT_SOUND_MMC5:
242       return &mmc5_ext;
243 
244    case EXT_SOUND_NAMCO106:
245    case EXT_SOUND_SUNSOFT_FME07:
246    case EXT_SOUND_NONE:
247    default:
248       return NULL;
249    }
250 }
251 
252 static void nsf_inittune(nsf_t *nsf)
253 {
254    uint8 bank, x_reg;
255    uint8 start_bank, num_banks;
256 
257    memset(nsf->cpu->mem_page[0], 0, 0x800);
258    memset(nsf->cpu->mem_page[6], 0, 0x1000);
259    memset(nsf->cpu->mem_page[7], 0, 0x1000);
260 
261 #ifdef NES6502_MEM_ACCESS_CTRL
262    memset(nsf->cpu->acc_mem_page[0], 0, 0x800);
263    memset(nsf->cpu->acc_mem_page[6], 0, 0x1000);
264    memset(nsf->cpu->acc_mem_page[7], 0, 0x1000);
265    memset(nsf->data+nsf->length, 0, nsf->length);
266 #endif
267    nsf->cur_frame = 0;
268 /*    nsf->last_access_frame = 0; */
269    nsf->cur_frame_end = !nsf->song_frames
270      ? 0
271      : nsf->song_frames[nsf->current_song];
272 
273    if (nsf->bankswitched)
274    {
275       /* the first hack of the NSF spec! */
276       if (EXT_SOUND_FDS == nsf->ext_sound_type)
277       {
278          nsf_bankswitch(0x5FF6, nsf->bankswitch_info[6]);
279          nsf_bankswitch(0x5FF7, nsf->bankswitch_info[7]);
280       }
281 
282       for (bank = 0; bank < 8; bank++)
283          nsf_bankswitch(0x5FF8 + bank, nsf->bankswitch_info[bank]);
284    }
285    else
286    {
287       /* not bankswitched, just page in our standard stuff */
288       ASSERT(nsf->load_addr + nsf->length <= 0x10000);
289 
290       /* avoid ripper filth */
291       for (bank = 0; bank < 8; bank++)
292          nsf_bankswitch(0x5FF8 + bank, bank);
293 
294       start_bank = nsf->load_addr >> 12;
295       num_banks = ((nsf->load_addr + nsf->length - 1) >> 12) - start_bank + 1;
296 
297       for (bank = 0; bank < num_banks; bank++)
298          nsf_bankswitch(0x5FF0 + start_bank + bank, bank);
299    }
300 
301    /* determine PAL/NTSC compatibility shite */
302    if (nsf->pal_ntsc_bits & NSF_DEDICATED_PAL)
303       x_reg = 1;
304    else
305       x_reg = 0;
306 
307    /* execute 1 frame or so; let init routine run free */
308    nsf_setup_routine(nsf->init_addr, (uint8) (nsf->current_song - 1), x_reg);
309    nes6502_execute((int) NES_FRAME_CYCLES);
310 }
311 
312 void nsf_frame(nsf_t *nsf)
313 {
314    //nsf_setcontext(nsf); /* future expansion =) */
315 
316 
317    /* one frame of NES processing */
318    nsf_setup_routine(nsf->play_addr, 0, 0);
319    nes6502_execute((int) NES_FRAME_CYCLES);
320 
321    ++nsf->cur_frame;
322 #if defined(NES6502_MEM_ACCESS_CTRL) && 0
323    if (nes6502_mem_access) {
324      uint32 sec =
325        (nsf->last_access_frame + nsf->playback_rate - 1) / nsf->playback_rate;
326      nsf->last_access_frame = nsf->cur_frame;
327      fprintf(stderr,"nsf : memory access [%x] at frame #%u [%u:%02u]\n",
328 		nes6502_mem_access,
329 		nsf->last_access_frame,
330 		sec/60, sec%60);
331    }
332 #endif
333 
334 }
335 
336 /* Deallocate memory */
337 void nes_shutdown(nsf_t *nsf)
338 {
339    int i;
340 
341    ASSERT(nsf);
342 
343    if (nsf->cpu)
344    {
345       if (nsf->cpu->mem_page[0])
346 	free(nsf->cpu->mem_page[0]);
347       for (i = 5; i <= 7; i++) {
348 	if (nsf->cpu->mem_page[i])
349 	  free(nsf->cpu->mem_page[i]);
350       }
351 
352 #ifdef NES6502_MEM_ACCESS_CTRL
353       if (nsf->cpu->acc_mem_page[0])
354 	free(nsf->cpu->acc_mem_page[0]);
355       for (i = 5; i <= 7; i++) {
356 	if (nsf->cpu->acc_mem_page[i])
357 	  free(nsf->cpu->acc_mem_page[i]);
358       }
359 #endif
360       free(nsf->cpu);
361    }
362 }
363 
364 int nsf_init(void)
365 {
366    nes6502_init();
367    return 0;
368 }
369 
370 /* Initialize NES CPU, hardware, etc. */
371 static int nsf_cpuinit(nsf_t *nsf)
372 {
373    int i;
374 
375    nsf->cpu = malloc(sizeof(nes6502_context));
376    if (NULL == nsf->cpu)
377       return -1;
378 
379    memset(nsf->cpu, 0, sizeof(nes6502_context));
380 
381    nsf->cpu->mem_page[0] = malloc(0x800);
382    if (NULL == nsf->cpu->mem_page[0])
383       return -1;
384 
385    /* allocate some space for the NSF "player" MMC5 EXRAM, and WRAM */
386    for (i = 5; i <= 7; i++)
387    {
388       nsf->cpu->mem_page[i] = malloc(0x1000);
389       if (NULL == nsf->cpu->mem_page[i])
390          return -1;
391    }
392 
393 #ifdef NES6502_MEM_ACCESS_CTRL
394    nsf->cpu->acc_mem_page[0] = malloc(0x800);
395    if (NULL == nsf->cpu->acc_mem_page[0])
396       return -1;
397    /* allocate some space for the NSF "player" MMC5 EXRAM, and WRAM */
398    for (i = 5; i <= 7; i++)
399    {
400       nsf->cpu->acc_mem_page[i] = malloc(0x1000);
401       if (NULL == nsf->cpu->acc_mem_page[i])
402          return -1;
403    }
404 #endif
405 
406    nsf->cpu->read_handler = nsf_readhandler;
407    nsf->cpu->write_handler = nsf_writehandler;
408 
409    return 0;
410 }
411 
412 static unsigned int nsf_playback_rate(nsf_t *nsf)
413 {
414    if (nsf->pal_ntsc_bits & NSF_DEDICATED_PAL)
415    {
416       if (nsf->pal_speed)
417          nsf->playback_rate = 1000000 / nsf->pal_speed;
418       else
419          nsf->playback_rate = 50; /* 50 Hz */
420    }
421    else
422    {
423       if (nsf->ntsc_speed)
424          nsf->playback_rate = 1000000 / nsf->ntsc_speed;
425       else
426          nsf->playback_rate = 60; /* 60 Hz */
427    }
428 }
429 
430 static void nsf_setup(nsf_t *nsf)
431 {
432    int i;
433 
434    nsf->current_song = nsf->start_song;
435    nsf_playback_rate(nsf);
436 
437    nsf->bankswitched = FALSE;
438    for (i = 0; i < 8; i++)
439    {
440       if (nsf->bankswitch_info[i])
441       {
442          nsf->bankswitched = TRUE;
443          break;
444       }
445    }
446 }
447 
448 #ifdef HOST_LITTLE_ENDIAN
449 #define  SWAP_16(x)  (x)
450 #else /* !HOST_LITTLE_ENDIAN */
451 #define  SWAP_16(x)  (((uint16) x >> 8) | (((uint16) x & 0xFF) << 8))
452 #endif /* !HOST_LITTLE_ENDIAN */
453 
454 /* $$$ ben : find extension. Should be OK with DOS, but not with some
455  * OS like RiscOS ... */
456 static char * find_ext(char *fn)
457 {
458   char * a, * b, * c;
459   a = strrchr(fn,'.');
460   b = strrchr(fn,'/');
461   c = strrchr(fn,'\\');
462   if (a <= b || a <= c) {
463     a = 0;
464   }
465   return a;
466 }
467 
468 /* $$$ ben : FILE loader */
469 struct nsf_file_loader_t {
470   struct nsf_loader_t loader;
471   FILE *fp;
472   char * fname;
473   int name_allocated;
474 };
475 
476 static int nfs_open_file(struct nsf_loader_t *loader)
477 {
478   struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader;
479 
480   floader->name_allocated = 0;
481   floader->fp = 0;
482   if (!floader->fname) {
483     return -1;
484   }
485   floader->fp = fopen(floader->fname,"rb");
486   if (!floader->fp) {
487     char * fname, * ext;
488     ext = find_ext(floader->fname);
489     if (ext) {
490       /* There was an extension, so we do not change it */
491       return -1;
492     }
493     fname = malloc(strlen(floader->fname) + 5);
494     if (!fname) {
495       return -1;
496     }
497     /* try with .nsf extension. */
498     strcpy(fname, floader->fname);
499     strcat(fname, ".nsf");
500     floader->fp = fopen(fname,"rb");
501     if (!floader->fp) {
502       free(fname);
503       return -1;
504     }
505     floader->fname = fname;
506     floader->name_allocated = 1;
507   }
508   return 0;
509 }
510 
511 static void nfs_close_file(struct nsf_loader_t *loader)
512 {
513   struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader;
514   if (floader->fp) {
515     fclose(floader->fp);
516     floader->fp = 0;
517   }
518   if (floader->fname && floader->name_allocated) {
519     free(floader->fname);
520     floader->fname = 0;
521     floader->name_allocated = 0;
522   }
523 }
524 
525 static int nfs_read_file(struct nsf_loader_t *loader, void *data, int n)
526 {
527   struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader;
528   int r = fread(data, 1, n, floader->fp);
529   if (r >= 0) {
530     r = n-r;
531   }
532   return r;
533 }
534 
535 static int nfs_length_file(struct nsf_loader_t *loader)
536 {
537   struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader;
538   long save, pos;
539   save = ftell(floader->fp);
540   fseek(floader->fp, 0, SEEK_END);
541   pos = ftell(floader->fp);
542   fseek(floader->fp, save, SEEK_SET);
543   return pos;
544 }
545 
546 static int nfs_skip_file(struct nsf_loader_t *loader, int n)
547 {
548   struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader;
549   int r;
550   r = fseek(floader->fp, n, SEEK_CUR);
551   return r;
552 }
553 
554 static const char * nfs_fname_file(struct nsf_loader_t *loader)
555 {
556   struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader;
557   return floader->fname ? floader->fname : "<null>";
558 }
559 
560 static struct nsf_file_loader_t nsf_file_loader = {
561   {
562     nfs_open_file,
563     nfs_close_file,
564     nfs_read_file,
565     nfs_length_file,
566     nfs_skip_file,
567     nfs_fname_file
568   },
569   0,0,0
570 };
571 
572 struct nsf_mem_loader_t {
573   struct nsf_loader_t loader;
574   uint8 *data;
575   unsigned long cur;
576   unsigned long len;
577   char fname[32];
578 };
579 
580 static int nfs_open_mem(struct nsf_loader_t *loader)
581 {
582   struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader;
583   if (!mloader->data) {
584     return -1;
585   }
586   mloader->cur = 0;
587   sprintf(mloader->fname,"<mem(%p,%u)>",
588 	  mloader->data, (unsigned int)mloader->len);
589   return 0;
590 }
591 
592 static void nfs_close_mem(struct nsf_loader_t *loader)
593 {
594   struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader;
595   mloader->data = 0;
596   mloader->cur = 0;
597   mloader->len = 0;
598 }
599 
600 static int nfs_read_mem(struct nsf_loader_t *loader, void *data, int n)
601 {
602   struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader;
603   int rem;
604   if (n <= 0) {
605     return n;
606   }
607   if (!mloader->data) {
608     return -1;
609   }
610   rem = mloader->len - mloader->cur;
611   if (rem > n) {
612     rem = n;
613   }
614   memcpy(data, mloader->data + mloader->cur, rem);
615   mloader->cur += rem;
616   return n - rem;
617 }
618 
619 static int nfs_length_mem(struct nsf_loader_t *loader)
620 {
621   struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader;
622   return mloader->len;
623 }
624 
625 static int nfs_skip_mem(struct nsf_loader_t *loader, int n)
626 {
627   struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader;
628   unsigned long goal = mloader->cur + n;
629   mloader->cur = (goal > mloader->len) ? mloader->len : goal;
630   return goal - mloader->cur;
631 }
632 
633 static const char * nfs_fname_mem(struct nsf_loader_t *loader)
634 {
635   struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader;
636   return mloader->fname;
637 }
638 
639 static struct nsf_mem_loader_t nsf_mem_loader = {
640   { nfs_open_mem, nfs_close_mem, nfs_read_mem, nfs_length_mem, nfs_skip_mem },
641   0,0,0
642 };
643 
644 nsf_t * nsf_load_extended(struct nsf_loader_t * loader)
645 {
646   nsf_t *temp_nsf = 0;
647   int length;
648   char id[6];
649 
650   struct {
651     uint8 magic[4]; /* always "NESM" */
652     uint8 type[4];  /* defines extension type */
653     uint8 size[4];  /* extension data size (this struct include) */
654   } nsf_file_ext;
655 
656   /* no loader ! */
657   if (!loader) {
658     return NULL;
659   }
660 
661   /* Open the "file" */
662   if (loader->open(loader) < 0) {
663     return NULL;
664   }
665 
666   /* Get file size, and exit if there is not enought data for NSF header
667    * and more since it does not make sens to have header without data.
668    */
669   length = loader->length(loader);
670   /* For version 2, we do not need file length. just check error later. */
671 #if 0
672   if (length <= NSF_HEADER_SIZE) {
673     log_printf("nsf : [%s] not an NSF format file\n",
674 	       loader->fname(loader));
675     goto error;
676   }
677 #endif
678 
679   /* Read magic */
680   if (loader->read(loader, id, 5)) {
681     log_printf("nsf : [%s] error reading magic number\n",
682 	       loader->fname(loader));
683     goto error;
684   }
685 
686   /* Check magic */
687   if (memcmp(id, NSF_MAGIC, 5)) {
688     log_printf("nsf : [%s] is not an NSF format file\n",
689 	       loader->fname(loader));
690     goto error;
691   }
692 
693   /* $$$ ben : Now the file should be an NSF, we can start allocating.
694    * first : the nsf struct
695    */
696   temp_nsf = malloc(sizeof(nsf_t));
697   if (NULL == temp_nsf) {
698     log_printf("nsf : [%s] error allocating nsf header\n",
699 	       loader->fname(loader));
700     goto error;
701   }
702   /* $$$ ben : safety net */
703   memset(temp_nsf,0,sizeof(nsf_t));
704   /* Copy magic ID */
705   memcpy(temp_nsf,id,5);
706 
707   /* Read header (without MAGIC) */
708   if (loader->read(loader, (int8 *)temp_nsf+5, NSF_HEADER_SIZE - 5)) {
709     log_printf("nsf : [%s] error reading nsf header\n",
710 	       loader->fname(loader));
711     goto error;
712   }
713 
714   /* fixup endianness */
715   temp_nsf->load_addr = SWAP_16(temp_nsf->load_addr);
716   temp_nsf->init_addr = SWAP_16(temp_nsf->init_addr);
717   temp_nsf->play_addr = SWAP_16(temp_nsf->play_addr);
718   temp_nsf->ntsc_speed = SWAP_16(temp_nsf->ntsc_speed);
719   temp_nsf->pal_speed = SWAP_16(temp_nsf->pal_speed);
720 
721   /* we're now at position 80h */
722 
723 
724   /* Here comes the specific codes for spec version 2 */
725 
726   temp_nsf->length = 0;
727 
728   if (temp_nsf->version > 1) {
729     /* Get specified data size in reserved field (3 bytes). */
730     temp_nsf->length = 0
731       + temp_nsf->reserved[0]
732       + (temp_nsf->reserved[1]<<8)
733       + (temp_nsf->reserved[2]<<16);
734 
735   }
736   /* no specified size : try to guess with file length. */
737   if (!temp_nsf->length) {
738     temp_nsf->length = length - NSF_HEADER_SIZE;
739   }
740 
741   if (temp_nsf->length <= 0) {
742     log_printf("nsf : [%s] not an NSF format file (missing data)\n",
743 	       loader->fname(loader));
744     goto error;
745   }
746 
747   /* Allocate NSF space, and load it up! */
748   {
749     int len = temp_nsf->length;
750 #ifdef NES6502_MEM_ACCESS_CTRL
751     /* $$$ twice memory for access control shadow mem. */
752     len <<= 1;
753 #endif
754    temp_nsf->data = malloc(len);
755   }
756   if (NULL == temp_nsf->data) {
757     log_printf("nsf : [%s] error allocating nsf data\n",
758 	       loader->fname(loader));
759     goto error;
760   }
761 
762   /* Read data */
763   if (loader->read(loader, temp_nsf->data, temp_nsf->length)) {
764     log_printf("nsf : [%s] error reading NSF data\n",
765 	       loader->fname(loader));
766     goto error;
767   }
768 
769   /* Here comes the second part of spec > 1 : get extension */
770   while (!loader->read(loader, &nsf_file_ext, sizeof(nsf_file_ext))
771 	 && !memcmp(nsf_file_ext.magic,id,4)) {
772     /* Got a NESM extension here. Checks for known extension type :
773      * right now, the only extension is "TIME" which give songs length.
774      * in frames.
775      */
776     int size;
777     size = 0
778       + nsf_file_ext.size[0]
779       + (nsf_file_ext.size[1] << 8)
780       + (nsf_file_ext.size[2] << 16)
781       + (nsf_file_ext.size[3] << 24);
782 
783     if (size < sizeof(nsf_file_ext)) {
784       log_printf("nsf : [%s] corrupt extension size (%d)\n",
785 		 loader->fname(loader), size);
786       /* Not a fatal error here. Just skip extension loading. */
787       break;
788     }
789     size -= sizeof(nsf_file_ext);
790 
791     if (!temp_nsf->song_frames
792 	&& !memcmp(nsf_file_ext.type,"TIME", 4)
793 	&& !(size & 3)
794 	&& (size >= 2*4)
795 	&& (size <= 256*4)) {
796 
797       uint8 tmp_time[256][4];
798       int tsongs = size >> 2;
799       int i;
800       int songs = temp_nsf->num_songs;
801 
802       /* Add 1 for 0 which contains total time for all songs. */
803       ++songs;
804 
805       if (loader->read(loader, tmp_time, size)) {
806 	log_printf("nsf : [%s] missing extension data\n",
807 		   loader->fname(loader));
808 	/* Not a fatal error here. Just skip extension loading. */
809 	break;
810       }
811       /* Alloc song_frames for songs (not tsongs). */
812       temp_nsf->song_frames = malloc(sizeof(*temp_nsf->song_frames) * songs);
813       if (!temp_nsf->song_frames) {
814 	log_printf("nsf : [%s] extension alloc failed\n",
815 		   loader->fname(loader));
816 	/* Not a fatal error here. Just skip extension loading. */
817 	break;
818       }
819 
820       if (tsongs > songs) {
821 	tsongs = songs;
822       }
823 
824       /* Copy time info. */
825       for (i=0; i<tsongs; ++i) {
826 	temp_nsf->song_frames[i] = 0
827 	  | tmp_time[i][0]
828 	  | (tmp_time[i][1] << 8)
829 	  | (tmp_time[i][2] << 16)
830 	  | (tmp_time[i][2] << 24);
831       }
832       /* Clear missing (safety net). */
833       for (; i<songs; ++i) {
834 	temp_nsf->song_frames[i] = 0;
835       }
836     } else if (loader->skip(loader, size)) {
837 	log_printf("nsf : [%s] extension skip failed\n",
838 		   loader->fname(loader));
839 	/* Not a fatal error here. Just skip extension loading. */
840 	break;
841     }
842   }
843 
844 
845   /* Close "file" */
846   loader->close(loader);
847   loader = 0;
848 
849    /* Set up some variables */
850    nsf_setup(temp_nsf);
851    temp_nsf->apu = NULL; /* just make sure */
852 
853    if (nsf_cpuinit(temp_nsf)) {
854      log_printf("nsf : error cpu init\n");
855      goto error;
856    }
857    return temp_nsf;
858 
859    /* $$$ ben : some people tell that goto are not clean. I am not agree with
860     * them. In most case, it allow to avoid code duplications, which are as
861     * most people know a source of error... Here we are sure of being ckean
862     */
863  error:
864    if (loader) {
865      loader->close(loader);
866    }
867    if (temp_nsf) {
868      nsf_free(&temp_nsf);
869    }
870    return 0;
871 }
872 
873 /* Load a ROM image into memory */
874 nsf_t *nsf_load(const char *filename, void *source, int length)
875 {
876   struct nsf_loader_t * loader = 0;
877 
878   /* $$$ ben : new loader */
879   if (filename) {
880     nsf_file_loader.fname = (char *)filename;
881     loader = &nsf_file_loader.loader;
882   } else {
883     nsf_mem_loader.data = source;
884     nsf_mem_loader.len = length;
885     nsf_mem_loader.fname[0] = 0;
886     loader = &nsf_mem_loader.loader;
887   }
888   return nsf_load_extended(loader);
889 }
890 
891 /* Free an NSF */
892 void nsf_free(nsf_t **pnsf)
893 {
894   nsf_t *nsf;
895 
896   if (!pnsf) {
897     return;
898   }
899 
900   nsf = *pnsf;
901   /* $$$ ben : Don't see why passing a pointer to pointer
902    *  is not to clear it :) */
903   *pnsf = 0;
904 
905   if (nsf) {
906     if (nsf->apu)
907       apu_destroy(nsf->apu);
908 
909     nes_shutdown(nsf);
910 
911     if (nsf->data)
912       free(nsf->data);
913 
914     if (nsf->song_frames) {
915       free (nsf->song_frames);
916     }
917 
918     free(nsf);
919 
920   }
921 }
922 
923 int nsf_setchan(nsf_t *nsf, int chan, boolean enabled)
924 {
925    if (!nsf)
926      return -1;
927 
928    nsf_setcontext(nsf);
929    return apu_setchan(chan, enabled);
930 }
931 
932 int nsf_playtrack(nsf_t *nsf, int track, int sample_rate, int sample_bits,
933 		  boolean stereo)
934 {
935   if (!nsf) {
936     return -1;
937   }
938 
939   /* make this NSF the current context */
940   nsf_setcontext(nsf);
941 
942   /* create the APU */
943   if (nsf->apu) {
944     apu_destroy(nsf->apu);
945   }
946 
947   nsf->apu = apu_create(sample_rate, nsf->playback_rate, sample_bits, stereo);
948   if (NULL == nsf->apu)
949     {
950       /* $$$ ben : from my point of view this is not clean. Function should
951        *	never destroy object it has not created...
952        */
953       /*       nsf_free(&nsf); */
954       return -1;
955     }
956 
957   apu_setext(nsf->apu, nsf_getext(nsf));
958 
959   /* go ahead and init all the read/write handlers */
960   build_address_handlers(nsf);
961 
962   /* convenience? */
963   nsf->process = nsf->apu->process;
964 
965   nes6502_setcontext(nsf->cpu);
966 
967   if (track > nsf->num_songs)
968     track = nsf->num_songs;
969   else if (track < 1)
970     track = 1;
971 
972   nsf->current_song = track;
973 
974   apu_reset();
975 
976   nsf_inittune(nsf);
977 
978   return nsf->current_song;
979 }
980 
981 int nsf_setfilter(nsf_t *nsf, int filter_type)
982 {
983   if (!nsf) {
984     return -1;
985   }
986   nsf_setcontext(nsf);
987   return apu_setfilter(filter_type);
988 }
989 
990 /*
991 ** $Log: nsf.c,v $
992 ** Revision 1.3  2003/05/01 22:34:20  benjihan
993 ** New NSF plugin
994 **
995 ** Revision 1.2  2003/04/09 14:50:32  ben
996 ** Clean NSF api.
997 **
998 ** Revision 1.1  2003/04/08 20:53:00  ben
999 ** Adding more files...
1000 **
1001 ** Revision 1.14  2000/07/05 14:54:45  matt
1002 ** fix for naughty Crystalis rip
1003 **
1004 ** Revision 1.13  2000/07/04 04:59:38  matt
1005 ** removed DOS-specific stuff, fixed bug in address handlers
1006 **
1007 ** Revision 1.12  2000/07/03 02:19:36  matt
1008 ** dynamic address range handlers, cleaner and faster
1009 **
1010 ** Revision 1.11  2000/06/23 03:27:58  matt
1011 ** cleaned up external sound inteface
1012 **
1013 ** Revision 1.10  2000/06/20 20:42:47  matt
1014 ** accuracy changes
1015 **
1016 ** Revision 1.9  2000/06/20 00:05:58  matt
1017 ** changed to driver-based external sound generation
1018 **
1019 ** Revision 1.8  2000/06/13 03:51:54  matt
1020 ** update API to take freq/sample data on nsf_playtrack
1021 **
1022 ** Revision 1.7  2000/06/12 03:57:14  matt
1023 ** more robust checking for winamp plugin
1024 **
1025 ** Revision 1.6  2000/06/12 01:13:00  matt
1026 ** added CPU/APU as members of the nsf struct
1027 **
1028 ** Revision 1.5  2000/06/11 16:09:21  matt
1029 ** nsf_free is more robust
1030 **
1031 ** Revision 1.4  2000/06/09 15:12:26  matt
1032 ** initial revision
1033 **
1034 */
1035