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

📄 snes.c

📁 NES game Emulator in Linux.c and asm codes.
💻 C
字号:
/*

SNEeSe, an Open Source Super NES emulator.


Copyright (c) 1998-2004 Charles Bilyue'.
Portions Copyright (c) 2003-2004 Daniel Horchner.

This is free software.  See 'LICENSE' for details.
You must read and accept the license prior to use.

*/

/*#define CPUTRACKER 1048576*/
/*#define SPCTRACKER 1048576*/
#include <stdio.h>
#include <string.h>

/*#define DEINTERLEAVED_VRAM*/

#include "timers.h"
#include "helper.h"
#include "platform.h"
#include "apu/sound.h"
#include "cpu/cpu.h"
#include "apu/spc.h"
#include "apu/apuskip.h"

#ifdef DEBUG
#ifdef CPUTRACKER
unsigned char *InsAddress=0;
unsigned LastIns;
#endif
#ifdef SPCTRACKER
unsigned char *SPC_InsAddress=0;
unsigned SPC_LastIns;
#endif
#endif

extern void reset_bus_timings(void);

signed char snes_rom_loaded = 0;

#define SPC_CPU_CYCLE_MULTIPLICAND_PAL 102400
#define SPC_CPU_CYCLE_DIVISOR_PAL 2128137
#define SPC_CPU_CYCLE_MULTIPLICAND_NTSC 5632
#define SPC_CPU_CYCLE_DIVISOR_NTSC 118125

unsigned SPC_CPU_cycle_divisor, SPC_CPU_cycle_multiplicand;

/* Used to determine if APU emulation option change demands reset */
static signed char SPC_SAFE = TRUE;


#ifdef FAST_SPC
signed char spc700_clockdoubled = TRUE;
#else
signed char spc700_clockdoubled = FALSE;
#endif

static int Setup_Memory(void)
{
#ifdef DEBUG
#ifdef CPUTRACKER
#if CPUTRACKER >= 16
 InsAddress=(unsigned char *)malloc(CPUTRACKER);
#else
 InsAddress=(unsigned char *)malloc(5120);
#endif
#endif
#ifdef SPCTRACKER
 SPC_InsAddress=(unsigned char *)malloc(SPCTRACKER);
#endif
#endif

 return 0;
}


int snes_init(void)
{
 int memoryneeded;

 timers_init();

 memoryneeded = Setup_Memory();
 if (memoryneeded)
 {
  printf("Out of memory. Need up to %d more bytes free!\n", memoryneeded);
  return 1;
 }

 memset(&gbSNES_Screen8, 0, sizeof(gbSNES_Screen8));
 memset(&gbSNES_Screen16, 0, sizeof(gbSNES_Screen16));

 SNES_Screen8 =
  platform_get_gfx_buffer(8, 256, 239, 8, 0, &gbSNES_Screen8);
 if (SNES_Screen8 == 0) return 1;

 SNES_Screen16 =
  platform_get_gfx_buffer(16, 256, 239, 0, 0, &gbSNES_Screen16);
 if (SNES_Screen16 == 0) return 1;

 SetupTables();

 switch (sound_enabled)
 {
  case 2:
   if (Install_Sound(1)) break;
  case 1:
   Install_Sound(0);
 }

 return 0;
}

void snes_reset(void)
{
 reset_bus_timings();

 Reset_CPU();

 /* Copy the SPC ROM into the top of the SPC RAM */
 memcpy(SPCRAM + 0xFFC0, SPC_ROM_CODE, 64);
 Reset_SPC();
 Reset_APU_Skipper();
 Reset_Sound_DSP();

 /* APU reset, no need to check this in next call to snes_exec() */
 SPC_SAFE = TRUE;
}

extern unsigned FPSMaxTicks;

#define PAL_TICKS (TIMERS_PER_SECOND / (21281370.0 / 312 / 4 / 341))
#define NTSC_TICKS (TIMERS_PER_SECOND / (1.89e9 / 88 / 262 / 4 / 341))

void set_snes_pal(void)
{
 SNES_COUNTRY = 0x10;
 set_timer_throttle_ticks(PAL_TICKS);
 FPSMaxTicks = 50;
 LastVBLLine = 311;

 SPC_CPU_cycle_multiplicand = SPC_CPU_CYCLE_MULTIPLICAND_PAL *
  (spc700_clockdoubled ? 2 : 1);
 SPC_CPU_cycle_divisor = SPC_CPU_CYCLE_DIVISOR_PAL;
}

void set_snes_ntsc(void)
{
 SNES_COUNTRY = 0x00;
 set_timer_throttle_ticks(NTSC_TICKS);
 FPSMaxTicks = 60;
 LastVBLLine = 261;

 SPC_CPU_cycle_multiplicand = SPC_CPU_CYCLE_MULTIPLICAND_NTSC *
  (spc700_clockdoubled ? 2 : 1);
 SPC_CPU_cycle_divisor = SPC_CPU_CYCLE_DIVISOR_NTSC;
}

void set_spc700_clockdouble(int new_state)
{
 spc700_clockdoubled = new_state;
}

void snes_exec(void)
{
 if (SPC_ENABLED) Make_SPC(); else Make_APU_Skipper();

 /* Reset the SNES if the SPC has been enabled, and it wasn't before */
 if (SPC_ENABLED && !SPC_SAFE) snes_reset();
 SPC_SAFE = SPC_ENABLED;

 if (sound_enabled) sound_resume();

 timers_enable(Frametime);

 Do_CPU();    /* This is the emulation core. */

 timers_disable();

 if (sound_enabled) sound_pause();    /* Ensures silent GUI */
}

/* Resets memory heaps */
void Reset_Memory(void)
{
 int i;
#ifdef DEBUG
#ifdef CPUTRACKER
 /* Reset CPU instruction tracking buffer */
#if CPUTRACKER >= 16
 memset(InsAddress,0xFF,CPUTRACKER); LastIns=0;
#else
 memset(InsAddress,0,5120); LastIns=0;
#endif
#endif
#ifdef SPCTRACKER
 /* Reset SPC instruction tracking buffer */
 memset(SPC_InsAddress,0xFF,SPCTRACKER); SPC_LastIns=0;
#endif
#endif

 /* Reset blank ROM space to 0xFF */
 memset(Blank,0xFF,(64 << 10));

 /* Reset SPC address space to the value of pin A5 */
 for (i = 0; i < (64 << 10); i += (1 << 5))
 {
  memset(SPCRAM, i & (1 << 5) ? (0 - 1) : 0, (1 << 5));
 }

 /* Reset WRAM to 0x55 */
 memset(WRAM,0x55,(128 << 10));

 /* Reset VRAM to 0 */
 memset(VRAM,0,(64 << 10));

#if 0
 /* Clear CGRAM */
 Reset_CGRAM();
 /* Clear OAM */
 memset(OAM,0,512+32);
#endif
}

/* Resets Save RAM */
void Reset_SRAM(void)
{
 if (!SaveRamLength) return;

 /* Reset SRAM to 0xAA */
 memset(SRAM, 0xAA, SaveRamLength > (8 << 10) ? SaveRamLength : (8 << 10));
}

extern unsigned char OAM_Count[239][2];
extern unsigned OAM_Lines[239][34];
extern unsigned char TileCache2[4 * 64 << 10];
extern unsigned char TileCache4[2 * 64 << 10];
extern unsigned char TileCache8[1 * 64 << 10];
void save_debug_dumps(void)
{
 if (snes_rom_loaded)
 {
  FILE *fp;

#ifdef DEBUG
#ifdef SPCTRACKER
  /* This saves the SPC-tracker dump! */
  fp = fopen("SPC.DMP", "wb");
  if (fp)
  {
   fwrite(SPC_InsAddress + SPC_LastIns, 1, (SPCTRACKER) - SPC_LastIns, fp);
   fwrite(SPC_InsAddress, 1, SPC_LastIns, fp);
   fclose(fp);
  }
#endif

#ifdef CPUTRACKER
  /* This saves the CPU-tracker dump! */
  fp = fopen("C:\\INS.DMP", "wb");
  if (fp)
  {
#if CPUTRACKER >= 16
   fwrite(InsAddress + LastIns, 1, (CPUTRACKER) - LastIns, fp);
   fwrite(InsAddress, 1, LastIns, fp);
#else
   fwrite(InsAddress, 1, 5120, fp);
#endif
   fclose(fp);
  }
#endif

  fp = fopen("SPCRAM.DMP", "wb");
  if (fp)
  {
   fwrite(SPCRAM, 1, 65536, fp);
   fwrite(&_SPC_PC, 1, sizeof(unsigned), fp);
   fclose(fp);
  }

  fp = fopen("WRAM.DMP", "wb");
  if (fp)
  {
   fwrite(WRAM, 1, 131072, fp);
   fclose(fp);
  }

  fp = fopen("VRAM.DMP", "wb");
  if (fp)
  {
   fwrite(VRAM, 1, 65536, fp);
   fclose(fp);
  }

  fp = fopen("OAM.DMP", "wb");
  if (fp)
  {
   fwrite(OAM, 1, 512+32, fp);
   fclose(fp);
  }

  fp = fopen("OBJ.DMP", "wb");
  if (fp)
  {
   fwrite(OAM_Lines, sizeof(OAM_Lines), 1, fp);
   fwrite(OAM_Count, sizeof(OAM_Count), 1, fp);
   fclose(fp);
  }

  fp = fopen("PAL.DMP", "wb");
  if (fp)
  {
   fwrite(Real_SNES_Palette, sizeof(Real_SNES_Palette), 1, fp);
   fwrite(SNES_Palette, sizeof(SNES_Palette), 1, fp);
   fclose(fp);
  }

  fp = fopen("CACHE.DMP", "wb");
  if (fp)
  {
   fwrite(TileCache2, sizeof(TileCache2), 1, fp);
   fwrite(TileCache4, sizeof(TileCache4), 1, fp);
   fwrite(TileCache8, sizeof(TileCache8), 1, fp);
   fclose(fp);
  }

#endif

 }
}

⌨️ 快捷键说明

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