📄 nsf.c
字号:
void nsf_init(void){ nes6502_init();}/* Initialize NES CPU, hardware, etc. */static int nsf_cpuinit(nsf_t *nsf){ int i; nsf->cpu = malloc(sizeof(nes6502_context)); if (NULL == nsf->cpu) return -1; memset(nsf->cpu, 0, sizeof(nes6502_context)); nsf->cpu->mem_page[0] = malloc(0x800); if (NULL == nsf->cpu->mem_page[0]) return -1; /* allocate some space for the NSF "player" MMC5 EXRAM, and WRAM */ for (i = 5; i <= 7; i++) { nsf->cpu->mem_page[i] = malloc(0x1000); if (NULL == nsf->cpu->mem_page[i]) return -1; } nsf->cpu->read_handler = nsf_readhandler; nsf->cpu->write_handler = nsf_writehandler; return 0;}static void nsf_setup(nsf_t *nsf){ int i; nsf->current_song = nsf->start_song; if (nsf->pal_ntsc_bits & NSF_DEDICATED_PAL) { if (nsf->pal_speed) nsf->playback_rate = 1000000 / nsf->pal_speed; else nsf->playback_rate = 50; /* 50 Hz */ } else { if (nsf->ntsc_speed) nsf->playback_rate = 1000000 / nsf->ntsc_speed; else nsf->playback_rate = 60; /* 60 Hz */ } nsf->bankswitched = FALSE; for (i = 0; i < 8; i++) { if (nsf->bankswitch_info[i]) { nsf->bankswitched = TRUE; break; } }}#ifdef HOST_LITTLE_ENDIAN#define SWAP_16(x) (x)#else /* !HOST_LITTLE_ENDIAN */#define SWAP_16(x) (((uint16) x >> 8) | (((uint16) x & 0xFF) << 8))#endif /* !HOST_LITTLE_ENDIAN *//* Load a ROM image into memory */nsf_t *nsf_load(char *filename, void *source, int length){ FILE *fp = NULL; char *new_fn = NULL; nsf_t *temp_nsf; if (NULL == filename && NULL == source) return NULL; if (NULL == source) { fp = fopen(filename, "rb"); /* Didn't find the file? Maybe the .NSF extension was omitted */ if (NULL == fp) { new_fn = malloc(strlen(filename) + 5); if (NULL == new_fn) return NULL; strcpy(new_fn, filename); if (NULL == strrchr(new_fn, '.')) strcat(new_fn, ".nsf"); fp = fopen(new_fn, "rb"); if (NULL == fp) { log_printf("could not find file '%s'\n", new_fn); free(new_fn); return NULL; } } } temp_nsf = malloc(sizeof(nsf_t)); if (NULL == temp_nsf) { fclose(fp); free(new_fn); return NULL; } /* Read in the header */ if (NULL == source) fread(temp_nsf, 1, NSF_HEADER_SIZE, fp); else memcpy(temp_nsf, source, NSF_HEADER_SIZE); if (memcmp(temp_nsf->id, NSF_MAGIC, 5)) { if (NULL == source) { log_printf("%s is not an NSF format file\n", new_fn); fclose(fp); free(new_fn); } nsf_free(&temp_nsf); return NULL; } /* fixup endianness */ temp_nsf->load_addr = SWAP_16(temp_nsf->load_addr); temp_nsf->init_addr = SWAP_16(temp_nsf->init_addr); temp_nsf->play_addr = SWAP_16(temp_nsf->play_addr); temp_nsf->ntsc_speed = SWAP_16(temp_nsf->ntsc_speed); temp_nsf->pal_speed = SWAP_16(temp_nsf->pal_speed); /* we're now at position 80h */ if (NULL == source) { fseek(fp, 0, SEEK_END); temp_nsf->length = ftell(fp) - NSF_HEADER_SIZE; } else { temp_nsf->length = length - NSF_HEADER_SIZE; } /* Allocate NSF space, and load it up! */ temp_nsf->data = malloc(temp_nsf->length); if (NULL == temp_nsf->data) { log_printf("error allocating memory for NSF data\n"); nsf_free(&temp_nsf); return NULL; } /* seek to end of header, read in data */ if (NULL == source) { fseek(fp, NSF_HEADER_SIZE, SEEK_SET); fread(temp_nsf->data, temp_nsf->length, 1, fp); fclose(fp); if (new_fn) free(new_fn); } else memcpy(temp_nsf->data, (uint8 *) source + NSF_HEADER_SIZE, length - NSF_HEADER_SIZE); /* Set up some variables */ nsf_setup(temp_nsf); temp_nsf->apu = NULL; /* just make sure */ if (nsf_cpuinit(temp_nsf)) { nsf_free(&temp_nsf); return NULL; } return temp_nsf;}/* Free an NSF */void nsf_free(nsf_t **nsf){ if (*nsf) { if ((*nsf)->apu) apu_destroy((*nsf)->apu); nes_shutdown(*nsf); if ((*nsf)->data) free((*nsf)->data); free(*nsf); }}void nsf_setchan(nsf_t *nsf, int chan, boolean enabled){ if (nsf) { nsf_setcontext(nsf); apu_setchan(chan, enabled); }}void nsf_playtrack(nsf_t *nsf, int track, int sample_rate, int sample_bits, boolean stereo){ ASSERT(nsf); /* make this NSF the current context */ nsf_setcontext(nsf); /* create the APU */ if (nsf->apu) apu_destroy(nsf->apu); nsf->apu = apu_create(sample_rate, nsf->playback_rate, sample_bits, stereo); if (NULL == nsf->apu) { nsf_free(&nsf); return; } apu_setext(nsf->apu, nsf_getext(nsf)); /* go ahead and init all the read/write handlers */ build_address_handlers(nsf); /* convenience? */ nsf->process = nsf->apu->process; nes6502_setcontext(nsf->cpu); if (track > nsf->num_songs) track = nsf->num_songs; else if (track < 1) track = 1; nsf->current_song = track; apu_reset(); nsf_inittune(nsf);}void nsf_setfilter(nsf_t *nsf, int filter_type){ if (nsf) { nsf_setcontext(nsf); apu_setfilter(filter_type); }}/*** $Log: nsf.c,v $** Revision 1.4 2006/09/26 00:52:17 dgp85** Free the filename string and close the file pointer when returning.**** Found by Coverity Scan.**** Revision 1.3 2003/08/25 21:51:43 f1rmb** Reduce GCC verbosity (various prototype declaration fixes). ffmpeg, wine and fft*post are untouched (fft: for now).**** Revision 1.2 2003/01/09 18:36:40 jkeil** memcpy copies too much, corrupts malloc heap**** Revision 1.1 2003/01/08 07:04:35 tmmm** initial import of Nosefart sources**** Revision 1.14 2000/07/05 14:54:45 matt** fix for naughty Crystalis rip**** Revision 1.13 2000/07/04 04:59:38 matt** removed DOS-specific stuff, fixed bug in address handlers**** Revision 1.12 2000/07/03 02:19:36 matt** dynamic address range handlers, cleaner and faster**** Revision 1.11 2000/06/23 03:27:58 matt** cleaned up external sound inteface**** Revision 1.10 2000/06/20 20:42:47 matt** accuracy changes**** Revision 1.9 2000/06/20 00:05:58 matt** changed to driver-based external sound generation**** Revision 1.8 2000/06/13 03:51:54 matt** update API to take freq/sample data on nsf_playtrack**** Revision 1.7 2000/06/12 03:57:14 matt** more robust checking for winamp plugin**** Revision 1.6 2000/06/12 01:13:00 matt** added CPU/APU as members of the nsf struct**** Revision 1.5 2000/06/11 16:09:21 matt** nsf_free is more robust**** Revision 1.4 2000/06/09 15:12:26 matt** initial revision***/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -