⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nsf.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)****** This program is free software; you can redistribute it and/or** modify it under the terms of version 2 of the GNU Library General ** Public License as published by the Free Software Foundation.**** 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 ** Library General Public License for more details.  To obtain a ** copy of the GNU Library General Public License, write to the Free ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.**** Any permitted reproduction of these routines, in whole or in part,** must bear this legend.****** nsf.c**** NSF loading/saving related functions** $Id: nsf.c,v 1.4 2006/09/26 00:52:17 dgp85 Exp $*/#include <stdio.h>#include <string.h>#include "types.h"#include "nsf.h"#include "log.h"#include "nes6502.h"#include "nes_apu.h"#include "vrcvisnd.h"#include "vrc7_snd.h"#include "mmc5_snd.h"#include "fds_snd.h"/* TODO: bleh! should encapsulate in NSF */#define  MAX_ADDRESS_HANDLERS    32static nes6502_memread nsf_readhandler[MAX_ADDRESS_HANDLERS];static nes6502_memwrite nsf_writehandler[MAX_ADDRESS_HANDLERS];static nsf_t *cur_nsf = NULL;static void nsf_setcontext(nsf_t *nsf){   ASSERT(nsf);   cur_nsf = nsf;}static uint8 read_mirrored_ram(uint32 address){   return cur_nsf->cpu->mem_page[0][address & 0x7FF];}static void write_mirrored_ram(uint32 address, uint8 value){   cur_nsf->cpu->mem_page[0][address & 0x7FF] = value;}/* can be used for both banked and non-bankswitched NSFs */static void nsf_bankswitch(uint32 address, uint8 value){   int cpu_page;   uint8 *offset;   cpu_page = address & 0x0F;   offset = (cur_nsf->data - (cur_nsf->load_addr & 0x0FFF)) + (value << 12);   nes6502_getcontext(cur_nsf->cpu);   cur_nsf->cpu->mem_page[cpu_page] = offset;   nes6502_setcontext(cur_nsf->cpu);}static nes6502_memread default_readhandler[] ={   { 0x0800, 0x1FFF, read_mirrored_ram },   { 0x4000, 0x4017, apu_read },   { -1,     -1,     NULL }};static nes6502_memwrite default_writehandler[] ={   { 0x0800, 0x1FFF, write_mirrored_ram },   { 0x4000, 0x4017, apu_write },   { 0x5FF6, 0x5FFF, nsf_bankswitch },   { -1,     -1,     NULL}};static uint8 invalid_read(uint32 address){#ifdef NOFRENDO_DEBUG   log_printf("filthy NSF read from $%04X\n", address);#endif /* NOFRENDO_DEBUG */   return 0xFF;}static void invalid_write(uint32 address, uint8 value){#ifdef NOFRENDO_DEBUG   log_printf("filthy NSF tried to write $%02X to $%04X\n", value, address);#endif /* NOFRENDO_DEBUG */}/* set up the address handlers that the CPU uses */static void build_address_handlers(nsf_t *nsf){   int count, num_handlers;   memset(nsf_readhandler, 0, sizeof(nsf_readhandler));   memset(nsf_writehandler, 0, sizeof(nsf_writehandler));    num_handlers = 0;   for (count = 0; num_handlers < MAX_ADDRESS_HANDLERS; count++, num_handlers++)   {      if (NULL == default_readhandler[count].read_func)         break;      memcpy(&nsf_readhandler[num_handlers], &default_readhandler[count],             sizeof(nes6502_memread));   }   if (nsf->apu->ext)   {      if (NULL != nsf->apu->ext->mem_read)      {         for (count = 0; num_handlers < MAX_ADDRESS_HANDLERS; count++, num_handlers++)         {            if (NULL == nsf->apu->ext->mem_read[count].read_func)               break;            memcpy(&nsf_readhandler[num_handlers], &nsf->apu->ext->mem_read[count],                   sizeof(nes6502_memread));         }      }   }   /* catch-all for bad reads */   nsf_readhandler[num_handlers].min_range = 0x2000; /* min address */   nsf_readhandler[num_handlers].max_range = 0x5BFF; /* max address */   nsf_readhandler[num_handlers].read_func = invalid_read; /* handler */   num_handlers++;   nsf_readhandler[num_handlers].min_range = -1;   nsf_readhandler[num_handlers].max_range = -1;   nsf_readhandler[num_handlers].read_func = NULL;   num_handlers++;   ASSERT(num_handlers <= MAX_ADDRESS_HANDLERS);   num_handlers = 0;   for (count = 0; num_handlers < MAX_ADDRESS_HANDLERS; count++, num_handlers++)   {      if (NULL == default_writehandler[count].write_func)         break;      memcpy(&nsf_writehandler[num_handlers], &default_writehandler[count],             sizeof(nes6502_memwrite));   }   if (nsf->apu->ext)   {      if (NULL != nsf->apu->ext->mem_write)      {         for (count = 0; num_handlers < MAX_ADDRESS_HANDLERS; count++, num_handlers++)         {            if (NULL == nsf->apu->ext->mem_write[count].write_func)               break;            memcpy(&nsf_writehandler[num_handlers], &nsf->apu->ext->mem_write[count],                   sizeof(nes6502_memwrite));         }      }   }   /* catch-all for bad writes */   nsf_writehandler[num_handlers].min_range = 0x2000; /* min address */   nsf_writehandler[num_handlers].max_range = 0x5BFF; /* max address */   nsf_writehandler[num_handlers].write_func = invalid_write; /* handler */   num_handlers++;   /* protect region at $8000-$FFFF */   nsf_writehandler[num_handlers].min_range = 0x8000; /* min address */   nsf_writehandler[num_handlers].max_range = 0xFFFF; /* max address */   nsf_writehandler[num_handlers].write_func = invalid_write; /* handler */   num_handlers++;   nsf_writehandler[num_handlers].min_range = -1;   nsf_writehandler[num_handlers].max_range = -1;   nsf_writehandler[num_handlers].write_func = NULL;   num_handlers++;   ASSERT(num_handlers <= MAX_ADDRESS_HANDLERS);}#define  NSF_ROUTINE_LOC   0x5000/* sets up a simple loop that calls the desired routine and spins */static void nsf_setup_routine(uint32 address, uint8 a_reg, uint8 x_reg){   uint8 *mem;   nes6502_getcontext(cur_nsf->cpu);   mem = cur_nsf->cpu->mem_page[NSF_ROUTINE_LOC >> 12] + (NSF_ROUTINE_LOC & 0x0FFF);   /* our lovely 4-byte 6502 NSF player */   mem[0] = 0x20;            /* JSR address */   mem[1] = address & 0xFF;   mem[2] = address >> 8;   mem[3] = 0xF2;            /* JAM (cpu kill op) */   cur_nsf->cpu->pc_reg = NSF_ROUTINE_LOC;   cur_nsf->cpu->a_reg = a_reg;   cur_nsf->cpu->x_reg = x_reg;   cur_nsf->cpu->y_reg = 0;   cur_nsf->cpu->s_reg = 0xFF;   nes6502_setcontext(cur_nsf->cpu);}/* retrieve any external soundchip driver */static apuext_t *nsf_getext(nsf_t *nsf){   switch (nsf->ext_sound_type)   {   case EXT_SOUND_VRCVI:      return &vrcvi_ext;   case EXT_SOUND_VRCVII:      return &vrc7_ext;   case EXT_SOUND_FDS:      return &fds_ext;   case EXT_SOUND_MMC5:      return &mmc5_ext;   case EXT_SOUND_NAMCO106:   case EXT_SOUND_SUNSOFT_FME07:   case EXT_SOUND_NONE:   default:      return NULL;   }}static void nsf_inittune(nsf_t *nsf){   uint8 bank, x_reg;   uint8 start_bank, num_banks;   memset(nsf->cpu->mem_page[0], 0, 0x800);   memset(nsf->cpu->mem_page[6], 0, 0x1000);   memset(nsf->cpu->mem_page[7], 0, 0x1000);   if (nsf->bankswitched)   {      /* the first hack of the NSF spec! */      if (EXT_SOUND_FDS == nsf->ext_sound_type)      {         nsf_bankswitch(0x5FF6, nsf->bankswitch_info[6]);         nsf_bankswitch(0x5FF7, nsf->bankswitch_info[7]);      }      for (bank = 0; bank < 8; bank++)         nsf_bankswitch(0x5FF8 + bank, nsf->bankswitch_info[bank]);   }   else   {      /* not bankswitched, just page in our standard stuff */      ASSERT(nsf->load_addr + nsf->length <= 0x10000);      /* avoid ripper filth */      for (bank = 0; bank < 8; bank++)         nsf_bankswitch(0x5FF8 + bank, bank);      start_bank = nsf->load_addr >> 12;      num_banks = ((nsf->load_addr + nsf->length - 1) >> 12) - start_bank + 1;      for (bank = 0; bank < num_banks; bank++)         nsf_bankswitch(0x5FF0 + start_bank + bank, bank);   }   /* determine PAL/NTSC compatibility shite */   if (nsf->pal_ntsc_bits & NSF_DEDICATED_PAL)      x_reg = 1;   else         x_reg = 0;   /* execute 1 frame or so; let init routine run free */   nsf_setup_routine(nsf->init_addr, (uint8) (nsf->current_song - 1), x_reg);   nes6502_execute((int) NES_FRAME_CYCLES);}void nsf_frame(nsf_t *nsf){   //nsf_setcontext(nsf); /* future expansion =) */   /* one frame of NES processing */   nsf_setup_routine(nsf->play_addr, 0, 0);   nes6502_execute((int) NES_FRAME_CYCLES);}/* Deallocate memory */static void nes_shutdown(nsf_t *nsf){   int i;   ASSERT(nsf);      if (nsf->cpu)   {      if (nsf->cpu->mem_page[0])         free(nsf->cpu->mem_page[0]);      for (i = 5; i <= 7; i++)      {         if (nsf->cpu->mem_page[i])            free(nsf->cpu->mem_page[i]);      }      free(nsf->cpu);   }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -