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

📄 gb.c

📁 知名gba模拟器vgba代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/** VGB: portable GameBoy emulator ***************************/
/**                                                         **/
/**                           GB.c                          **/
/**                                                         **/
/** This file contains the portable part of the GameBoy     **/
/** hardware emulation. See GB.h for #defines related to    **/
/** drivers and GameBoy hardware.                           **/
/**                                                         **/
/** Copyright (C) Marat Fayzullin 1995,1996                 **/
/**               Marcel de Kogel 1996                      **/
/**     You are not allowed to distribute this software     **/
/**     commercially. Please, notify me, if you make any    **/   
/**     changes to this file.                               **/
/*************************************************************/

#include "GB.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

byte Verbose    = 1;     /* Verboseness level                            */

byte *RAM,*Page[8];      /* RAM and pointers to Z80 address space 8x8kB) */

int  VPeriod    = 69905; /* Number of Z80 cycles between VBlanks         */
byte UPeriod    = 1;     /* Number of VBlanks per screen update          */
byte LineDelay  = 1;     /* When 1, screen refreshing is delayed         */
byte CheckCRC   = 1;     /* When 1, VGB checks cartridge CRC on loading  */

char *SaveName  = NULL;  /* .sav file name                               */

char *SndName   = NULL;  /* Soundtrack log file                          */
FILE *SndStream = NULL;

struct                   /* Cheat list to be filled before StartGB()     */
{                        /* is called                                    */
  byte Value,Orig;
  word Address;
} Cheats[MAXCHEAT];
int CheatCount  = 0;     /* Number of cheats in the list                 */

byte SIOBuf;             /* Next byte to output via the serial line      */
byte SIOFlag;            /* Bit0 -> SIO interrupt should be generated    */
                         /* Bit1 -> Data should be sent out              */

byte IMask;              /* A mask to reset an event bit in IFLAGS       */

byte MBCType;            /* MBC type: 1 for MBC2, 0 for MBC1             */
byte *ROMMap[256];       /* Addresses of ROM banks                       */
byte ROMBank;            /* Number of ROM bank currently used            */
byte ROMMask;            /* Mask for the ROM bank number                 */
int  ROMBanks;           /* Total number of ROM banks                    */
byte *RAMMap[256];       /* Addresses of RAM banks                       */ 
byte RAMBank;            /* Number of RAM bank currently used            */
byte RAMMask;            /* Mask for the RAM bank number                 */
int  RAMBanks;           /* Total number of RAM banks                    */

byte JoyState   = 0xFF;  /* Joystick state: START.SELECT.B.A.D.U.L.R     */
byte AutoA      = 0;     /* When 1, autofire emulation for button A      */
byte AutoB      = 0;     /* When 1, autofire emulation for button B      */

unsigned TCount,TStep;   /* Timer counter and increment                  */
unsigned SIOCount;       /* Serial I/O counter                           */ 

byte BPal[4];            /* Background palette                           */
byte SPal0[4],SPal1[4];  /* Sprite palettes                              */

byte *ChrGen;            /* Character generator                          */
byte *BgdTab,*WndTab;    /* Background and window character tables       */

int IFreq=60;            /* Interrupt Frequency in Hertz                 */

static unsigned NumInts=0;
static void WriteIntStamp (void)
{
 if (NumInts>65535)
 {
  fputc (0xFF,SndStream);
  fputc (NumInts,SndStream);
  fputc (NumInts>>8,SndStream);
  fputc (NumInts>>16,SndStream);
  fputc (NumInts>>24,SndStream);
 }
 else
 {
  if (NumInts>255)
  {
   fputc (0xFE,SndStream);
   fputc (NumInts,SndStream);
   fputc (NumInts>>8,SndStream);
  }
  else
  {
   fputc (0xFD,SndStream);
   fputc (NumInts,SndStream);
  }
 }
 NumInts=0;
}
static void _Sound (byte Reg, byte Value)
{
 if(SndStream)
 { WriteIntStamp();fputc(Reg,SndStream);fputc(Value,SndStream); }
 Sound (Reg,Value);
}

static void WriteROM (unsigned A,byte V)  __attribute__ ((regparm(3)));
static void WriteCartRAM (unsigned A,byte V) __attribute__ ((regparm(3)));
static void WriteRAM (unsigned A,byte V) __attribute__ ((regparm(3)));
static void WROMBank (unsigned A,byte V) __attribute__ ((regparm(3)));
static void WRAMBank (unsigned A,byte V) __attribute__ ((regparm(3)));
static void WriteIO (unsigned A,byte V) __attribute__ ((regparm(3)));

static void WriteCartRAM (unsigned A,byte V)
{
 Page[A>>13][A&0x1FFF]=V;
}

static void WriteRAM (unsigned A,byte V)
{
 RAM[A]=V;
}

static void WROMBank (unsigned A,byte V)
{
 if(MBCType&&((A&0xFF00)!=0x2100)) return;
 V&=ROMMask;
 if(!V) V=1;
 if(ROMMask&&(V!=ROMBank))
 {
  ROMBank=V;
  Page[2]=ROMMap[V]? ROMMap[V]:RAM+0x4000;
  Page[3]=Page[2]+0x2000;
  if(Verbose&0x08) printf("ROM: Bank %d selected\n",V);
 }
}

static void WriteROM (unsigned A,byte V)
{
 if(Verbose&0x02) printf("Wrote %Xh to ROM at %Xh\n",V,A);
}

static void WRAMBank (unsigned A,byte V)
{
 V&=RAMMask;
 if(RAMMask&&!MBCType&&(RAMBank!=V))
 {
  RAMBank=V;
  Page[5]=RAMMap[V]? RAMMap[V]:RAM+0xA000;
  if(Verbose&0x08) printf("RAM: Bank %d selected\n",V);
 }
}

static void WriteIO(unsigned A,byte V)
{
  static unsigned long TPFreqs[] = { 4096,262144,65536,16384 };
  byte *P;

  switch(A)
  {
    case 0xFF00: JOYPAD=0xCF|V;
                 if(!(V&0x20)) JOYPAD&=(JoyState>>4)|0xF0;
                 if(!(V&0x10)) JOYPAD&=JoyState|0xF0; 
                 return;
    case 0xFF01: SIOBuf=V;SIOFlag|=0x02;return;
    case 0xFF02: SIOCount=0;
                 if(V&0x80)
                 {
                   if ((V&1)==0)        /* external clock */
                   {
                    if(SIOFlag&0x02? SIOSend(SIOBuf):SIOReceive(&SIODATA))
                     SIOCount=8;
                   }
                   else                 /* internal clock */
                    SIOCount=8;
                   SIOFlag=(SIOFlag&0xFD);
                 }
                 V|=0x7E; 
                 break;
    case 0xFF07: TStep=(TPFreqs[V&0x03]<<16)/(154*IFreq);
                 V|=0xF8;break;
    case 0xFF0F: V&=0x1F;break;
    case 0xFFFF: V&=0x1F;break;
    case 0xFF46: P=RAM+0xFE00;A=(word)V<<8;
                 for(V=0;V<0xA0;V++) *P++=M_RDMEM(A++);
                 return;
    case 0xFF41: V=(V&0xF8)|(LCDSTAT&0x07);
                 break;
    case 0xFF40: ChrGen=RAM+(V&0x10? 0x8000:0x8800);
                 BgdTab=RAM+(V&0x08? 0x9C00:0x9800);
                 WndTab=RAM+(V&0x40? 0x9C00:0x9800);
                 break;
    case 0xFF44: V=0;break;
    case 0xFF47: BPal[0]=V&0x03;
                 BPal[1]=(V&0x0C)>>2;
                 BPal[2]=(V&0x30)>>4;
                 BPal[3]=(V&0xC0)>>6;
                 break;
    case 0xFF48: SPal0[0]=V&0x03;
                 SPal0[1]=(V&0x0C)>>2;
                 SPal0[2]=(V&0x30)>>4;
                 SPal0[3]=(V&0xC0)>>6;
                 break;
    case 0xFF49: SPal1[0]=V&0x03;
                 SPal1[1]=(V&0x0C)>>2;
                 SPal1[2]=(V&0x30)>>4;
                 SPal1[3]=(V&0xC0)>>6;
                 break;
    default:     if((A>=0xFF10)&&(A<=0xFF26))
                  _Sound(A-0xFF10,V);
  }
  RAM[A]=V;
}

WriteMemFn WriteMemFnTable[256]= {
 /* 0000-1FFF ROM */
 WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
 WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
 WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
 WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
 /* 2000-3FFF ROM Bank Select */
 WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,
 WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,
 WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,
 WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,
 /* 4000-5FFF RAM Bank Select */
 WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,
 WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,
 WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,
 WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,
 /* 6000-7FFF ROM */
 WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
 WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
 WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
 WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
 /* 8000-9FFF RAM */
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 /* A000-BFFF Cartridge RAM */
 WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,
 WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,
 WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,
 WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,WriteCartRAM,
 /* C000-FEFF RAM */
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
 /* FF00-FFFF I/O */
 WriteIO
};

void M_WRMEM (unsigned A,byte V)
{
 (*WriteMemFnTable[A>>8])(A,V);
}
byte M_RDMEM(unsigned A)
{
 return (Page[A>>13][A&0x1FFF]);
}
byte M_RDMEM_OPCODE (void)
{
 byte V;
 V=M_RDMEM (R.PC.D);
 R.PC.W++;
 return V;
}

void ResetGB (void)
{
  int I;
  if(RAMMap[0]) Page[5]=RAMMap[0];
  if(ROMMap[1]) Page[2]=ROMMap[1];
  Page[3]=Page[2]+0x2000;

  TStep=32768;TCount=0;

  ChrGen=RAM+0x8800;BgdTab=WndTab=RAM+0x9800;
  LCDCONT=0x81;LCDSTAT=0x00;
  CURLINE=0x00;CMPLINE=0xFF;
  IFLAGS=ISWITCH=0x00;
  TIMECNT=TIMEMOD=0x01;
  TIMEFRQ=0xF8;
  SIODATA=0x00;
  SIOCONT=0x7E;
  SIOBuf=SIOFlag=0x00;
  JoyState=0xFF;

  for(I=0;I<4;I++) SPal0[I]=SPal1[I]=BPal[I]=I;
  BGRDPAL=SPR0PAL=SPR1PAL=0xE4;

  /* Initialise the timer */
  M_WRMEM (0xFF07,RAM[0xFF07]);
  ResetZ80(&R);
}

static int InitMachineDone=0;
static word Exit_PC;
int StartGB(char *CartName)
{
  static char *CartTypes[] =
  {
    "ROM ONLY","ROM+MBC1","ROM+MBC1+RAM",
    "ROM+MBC1+RAM+BATTERY","UNKNOWN",
    "ROM+MBC2","ROM+MBC2+BATTERY"
  };

  /*** Following are some known manufacturer codes *************************/
  static struct { word Code;char *Name; } Companies[] =
  {
  { 0x3301,"Nintendo"  },{ 0x7901,"Accolade"  },{ 0xA400,"Konami"    },
  { 0x6701,"Ocean"     },{ 0x5601,"LJN"       },{ 0x9900,"ARC?"      },
  { 0x0101,"Nintendo"  },{ 0x0801,"Capcom"    },{ 0x0100,"Nintendo"  },
  { 0xBB01,"SunSoft"   },{ 0xA401,"Konami"    },{ 0xAF01,"Namcot?"   },
  { 0x4901,"Irem"      },{ 0x9C01,"Imagineer" },{ 0xA600,"Kawada?"   },
  { 0xB101,"Nexoft"    },{ 0x5101,"Acclaim"   },{ 0x6001,"Titus"     },
  { 0xB601,"HAL"       },{ 0x3300,"Nintendo"  },{ 0x0B00,"Coconuts?" },
  { 0x5401,"Gametek"   },{ 0x7F01,"Kemco?"    },{ 0xC001,"Taito"     },
  { 0xEB01,"Atlus"     },{ 0xE800,"Asmik?"    },{ 0xDA00,"Tomy?"     },
  { 0xB100,"ASCII?"    },{ 0xEB00,"Atlus"     },{ 0xC000,"Taito"     },
  { 0x9C00,"Imagineer" },{ 0xC201,"Kemco?"    },{ 0xD101,"Sofel?"    },
  { 0x6101,"Virgin"    },{ 0xBB00,"SunSoft"   },{ 0xCE01,"FCI?"      },
  { 0xB400,"Enix?"     },{ 0xBD01,"Imagesoft" },{ 0x0A01,"Jaleco?"   },
  { 0xDF00,"Altron?"   },{ 0xA700,"Takara?"   },{ 0xEE00,"IGS?"      },
  { 0x8300,"Lozc?"     },{ 0x5001,"Absolute?" },{ 0xDD00,"NCS?"      },
  { 0xE500,"Epoch?"    },{ 0xCB00,"VAP?"      },{ 0x8C00,"Vic Tokai" },
  { 0xC200,"Kemco?"    },{ 0xBF00,"Sammy?"    },
  { 0x1800,"Hudson Soft"    },{ 0xCA01,"Palcom/Ultra" },
  { 0xCA00,"Palcom/Ultra"   },{ 0xC500,"Data East?" },
  { 0xA900,"Technos Japan?" },{ 0xD900,"Banpresto?" },
  { 0x7201,"Broderbund?"    },{ 0x7A01,"Triffix Entertainment?" },
  { 0xE100,"Towachiki?"     },{ 0x9300,"Tsuburava?" },
  { 0xC600,"Tonkin House?"  },{ 0xCE00,"Pony Canyon" },
  { 0x7001,"Infogrames?"    },{ 0x8B01,"Bullet-Proof Software?" },
  { 0x5501,"Park Place?"    },{ 0xEA00,"King Records?" },
  { 0x5D01,"Tradewest?"     },{ 0x6F01,"ElectroBrain?" },
  { 0xAA01,"Broderbund?"    },{ 0xC301,"SquareSoft" },
  { 0x5201,"Activision?"    },{ 0x5A01,"Bitmap Brothers/Mindscape" },
  { 0x5301,"American Sammy" },{ 0x4701,"Spectrum Holobyte" },
  { 0x1801,"Hudson Soft"},{ 0x0000,NULL }
  };

  int Checksum,I,J,*T;
  FILE *F;
  char *P,S[50];
  word A;
  int rambanks[4]= { 0,1,1,4 };

  /*** STARTUP CODE starts here: ***/
  T=(int *)"\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
#ifdef LSB_FIRST
  if(*T!=1)
  {
    puts("********** This machine is high-endian. *********");
    puts("Take #define LSB_FIRST out and compile VGB again.");
    return(0);
  }
#else
  if(*T==1)
  {
    puts("********* This machine is low-endian. *********");
    puts("Insert #define LSB_FIRST and compile VGB again.");
    return(0);
  }
#endif

⌨️ 快捷键说明

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