home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / gbuk.lha / src / GB.C < prev    next >
C/C++ Source or Header  |  1996-11-22  |  20KB  |  607 lines

  1. /** VGB: portable GameBoy emulator ***************************/
  2. /**                                                         **/
  3. /**                           GB.c                          **/
  4. /**                                                         **/
  5. /** This file contains the portable part of the GameBoy     **/
  6. /** hardware emulation. See GB.h for #defines related to    **/
  7. /** drivers and GameBoy hardware.                           **/
  8. /**                                                         **/
  9. /** Copyright (C) Marat Fayzullin 1995,1996                 **/
  10. /**               Marcel de Kogel 1996                      **/
  11. /**     You are not allowed to distribute this software     **/
  12. /**     commercially. Please, notify me, if you make any    **/   
  13. /**     changes to this file.                               **/
  14. /*************************************************************/
  15.  
  16. #include "GB.h"
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <ctype.h>
  21.  
  22. //    PG CHANGE ->Verbose has default of 0
  23. //byte Verbose    = 1;     /* Verboseness level                            */
  24. byte Verbose    = 0;     /* Verboseness level                            */
  25.  
  26. byte *RAM,*Page[8];      /* RAM and pointers to Z80 address space 8x8kB) */
  27.  
  28. int  VPeriod    = 6000;  /* Number of Z80 cycles between VBlanks         */
  29. byte UPeriod    = 1;     /* Number of VBlanks per screen update          */
  30. byte LineDelay  = 1;     /* When 1, CMPLINE interrupts are delayed       */
  31. byte CheckCRC   = 1;     /* When 1, VGB checks cartridge CRC on loading  */
  32.  
  33. char *SaveName  = NULL;  /* .sav file name                               */
  34.  
  35. struct                   /* Cheat list to be filled before StartGB()     */
  36. {                        /* is called                                    */
  37.   byte Value,Orig;
  38.   word Address;
  39. } Cheats[MAXCHEAT];
  40. int CheatCount  = 0;     /* Number of cheats in the list                 */
  41.  
  42. byte SIOBuf;             /* Next byte to output via the serial line      */
  43. byte SIOFlag;            /* Bit0 -> SIO interrupt should be generated    */
  44.                          /* Bit1 -> Data should be sent out              */
  45.  
  46. byte IMask;              /* A mask to reset an event bit in IFLAGS       */
  47.  
  48. byte MBCType;            /* MBC type: 1 for MBC2, 0 for MBC1             */
  49. byte *ROMMap[256];       /* Addresses of ROM banks                       */
  50. byte ROMBank;            /* Number of ROM bank currently used            */
  51. byte ROMMask;            /* Mask for the ROM bank number                 */
  52. int  ROMBanks;           /* Total number of ROM banks                    */
  53. byte *RAMMap[256];       /* Addresses of RAM banks                       */ 
  54. byte RAMBank;            /* Number of RAM bank currently used            */
  55. byte RAMMask;            /* Mask for the RAM bank number                 */
  56. int  RAMBanks;           /* Total number of RAM banks                    */
  57.  
  58. byte JoyState   = 0xFF;  /* Joystick state: START.SELECT.B.A.D.U.L.R     */
  59.  
  60. byte BPal[4];            /* Background palette                           */
  61. byte SPal0[4],SPal1[4];  /* Sprite palettes                              */
  62.  
  63. byte *ChrGen;            /* Character generator                          */
  64. byte *BgdTab,*WndTab;    /* Background and window character tables       */
  65.  
  66. byte SprFlag    = 0;     /* <>0: sprites were enabled during the frame   */
  67.  
  68. //    got rid of reg param thing
  69. static void WriteROM (word A,byte V);
  70. static void WriteRAM (word A,byte V);
  71. static void WROMBank (word A,byte V);
  72. static void WRAMBank (word A,byte V);
  73. static void WriteIO(word A,byte V);
  74.  
  75. int IFreq=60;
  76.  
  77. static void WriteRAM (word A,byte V)
  78. {
  79.  Page[A>>13][A&0x1FFF]=V;
  80. }
  81.  
  82. static void WROMBank (word A,byte V)
  83. {
  84.  if(MBCType&&((A&0xFF00)!=0x2100)) return;
  85.  V&=ROMMask;
  86.  if(!V) V++;
  87.  if(ROMMask&&(V!=ROMBank))
  88.  {
  89.   ROMBank=V;
  90.   Page[2]=ROMMap[V]? ROMMap[V]:RAM+0x4000;
  91.   Page[3]=Page[2]+0x2000;
  92.   if(Verbose&0x08) printf("ROM: Bank %d selected\n",V);
  93.  }
  94. }
  95.  
  96. static void WriteROM (word A,byte V)
  97. {
  98.  if(Verbose&0x02) printf("Wrote %Xh to ROM at %Xh\n",V,A);
  99. }
  100.  
  101. static void WRAMBank (word A,byte V)
  102. {
  103.  byte v;
  104.  v=V;
  105.  V&=RAMMask;
  106.  if(RAMMask&&!MBCType&&(RAMBank!=V))
  107.  {
  108.   RAMBank=V;
  109.   Page[5]=RAMMap[V]? RAMMap[V]:RAM+0xA000;
  110.   if(Verbose&0x08) printf("RAM: Bank %d selected\n",v);
  111.  }
  112. }
  113. //    -PG- got rid if static declaration
  114. unsigned TimerTestParam=0;
  115. unsigned TimerRecurParam=65536/32;
  116.  
  117. static void WriteIO(word A,byte V)
  118. {
  119.   static unsigned TPFreqs[] = { 4096,262144,65536,16384 };
  120.   register byte *P;
  121.  
  122.   switch(A)
  123.   {
  124.     case 0xFF00: JOYPAD=0xCF|V;
  125.                  if(!(V&0x20)) JOYPAD&=(JoyState>>4)|0xF0;
  126.                  if(!(V&0x10)) JOYPAD&=JoyState|0xF0; 
  127.                  return;
  128.     case 0xFF01: SIOBuf=V;SIOFlag|=0x02;return;
  129.     case 0xFF02: if(V&0x80)
  130.                  {
  131.                    if((SIOFlag&0x02)? SIOSend(SIOBuf):SIOReceive(&SIODATA))
  132.                      SIOFlag|=0x01;
  133.                    SIOFlag=(SIOFlag&0xFD);
  134.                  }
  135.                  V|=0x7E; 
  136.                  break;
  137.     case 0xFF05: /*V=0;*/
  138.                  break;
  139.     case 0xFF07: TimerRecurParam=(TPFreqs[V&0x03]<<16)/(154*IFreq);
  140.                  V|=0xF8;break;
  141.     case 0xFF0F: V|=0xE0;break;
  142.     case 0xFFFF: V|=0xE0;break;
  143.     case 0xFF46: P=RAM+0xFE00;A=(word)V<<8;
  144.                  for(V=0;V<0xA0;V++) *P++=M_RDMEM(A++);
  145.                  return;
  146.     case 0xFF41: V=(V&0xF8)|(LCDSTAT&0x07);
  147.                  break;
  148.     case 0xFF40: ChrGen=RAM+(V&0x10? 0x8000:0x8800);
  149.                  BgdTab=RAM+(V&0x08? 0x9C00:0x9800);
  150.                  WndTab=RAM+(V&0x40? 0x9C00:0x9800);
  151.                  break;
  152.     case 0xFF44: V=0;break;
  153.     case 0xFF47: BPal[0]=V&0x03;
  154.                  BPal[1]=(V&0x0C)>>2;
  155.                  BPal[2]=(V&0x30)>>4;
  156.                  BPal[3]=(V&0xC0)>>6;
  157.                  break;
  158.     case 0xFF48: SPal0[0]=V&0x03;
  159.                  SPal0[1]=(V&0x0C)>>2;
  160.                  SPal0[2]=(V&0x30)>>4;
  161.                  SPal0[3]=(V&0xC0)>>6;
  162.                  break;
  163.     case 0xFF49: SPal1[0]=V&0x03;
  164.                  SPal1[1]=(V&0x0C)>>2;
  165.                  SPal1[2]=(V&0x30)>>4;
  166.                  SPal1[3]=(V&0xC0)>>6;
  167.                  break;
  168.     case 0xFF04: case 0xFF06:   /* other documented ports */
  169.     case 0xFF42: case 0xFF43: case 0xFF45: case 0xFF4A: case 0xFF4B:
  170.     case 0xFF30: case 0xFF31: case 0xFF32: case 0xFF33: case 0xFF34:
  171.     case 0xFF35: case 0xFF36: case 0xFF37: case 0xFF38: case 0xFF39:
  172.     case 0xFF3A: case 0xFF3B: case 0xFF3C: case 0xFF3D: case 0xFF3E:
  173.     case 0xFF3F:
  174.                  break;
  175.     default:     if((A>=0xFF10)&&(A<=0xFF26)) Sound(A-0xFF10,V);
  176. /*                 else if (A<0xFF80) printf ("Wrote %02x to %04x\n",V,A); */
  177.   }
  178.   Page[7][A&0x1FFF]=V;
  179. }
  180.  
  181. WriteMemFn WriteMemFnTable[256]= {
  182.  /* 0000-1FFF ROM */
  183.  WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
  184.  WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
  185.  WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
  186.  WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
  187.  /* 2000-3FFF ROM Bank Select */
  188.  WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,
  189.  WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,
  190.  WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,
  191.  WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,WROMBank,
  192.  /* 4000-5FFF RAM Bank Select */
  193.  WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,
  194.  WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,
  195.  WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,
  196.  WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,WRAMBank,
  197.  /* 6000-7FFF ROM */
  198.  WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
  199.  WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
  200.  WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
  201.  WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,WriteROM,
  202.  /* 8000-FEFF RAM */
  203.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  204.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  205.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  206.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  207.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  208.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  209.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  210.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  211.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  212.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  213.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  214.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  215.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  216.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  217.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  218.  WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,WriteRAM,
  219.  /* FF00-FFFF I/O */
  220.  WriteIO
  221. };
  222.  
  223. #ifndef FAST_MEM
  224.  void M_WRMEM (word A,byte V)
  225.  {
  226.   (*WriteMemFnTable[A>>8])(A,V);
  227.  }
  228.  byte M_RDMEM(register word A)
  229.  {
  230.   byte V;
  231.   V=(Page[A>>13][A&0x1FFF]);
  232.   return V;
  233.  }
  234. #endif
  235.  
  236. static int InitMachineDone=0;
  237. static word Exit_PC;
  238. int StartGB(char *CartName)
  239. {
  240.   static char *CartTypes[] =
  241.   {
  242.     "ROM ONLY","ROM+MBC1","ROM+MBC1+RAM",
  243.     "ROM+MBC1+RAM+BATTERY","UNKNOWN",
  244.     "ROM+MBC2","ROM+MBC2+BATTERY"
  245.   };
  246.  
  247.   static struct { word Code;char *Name; } Companies[] =
  248.   {
  249.     { 0x3301,"Nintendo"  },{ 0x7901,"Accolade"  },{ 0xA400,"Konami"    },
  250.     { 0x6701,"Ocean"     },{ 0x5601,"LJN"       },{ 0x9900,"ARC?"      },
  251.     { 0x0101,"Nintendo"  },{ 0x0801,"Capcom"    },{ 0x0100,"Nintendo"  },
  252.     { 0xBB01,"SunSoft"   },{ 0xA401,"Konami"    },{ 0xAF01,"Namcot?"   },
  253.     { 0x4901,"Irem"      },{ 0x9C01,"Imagineer" },{ 0xA600,"Kawada?"   },
  254.     { 0xB101,"Nexoft"    },{ 0x5101,"Acclaim"   },{ 0x6001,"Titus"     },
  255.     { 0xB601,"HAL"       },{ 0x3300,"Nintendo"  },{ 0x0B00,"Coconuts?" },
  256.     { 0x5401,"Gametek"   },{ 0x7F01,"Kemco?"    },{ 0xC001,"Taito"     },
  257.     { 0xEB01,"Atlus"     },{ 0xE800,"Asmik?"    },{ 0xDA00,"Tomy?"     },
  258.     { 0xB100,"ASCII?"    },{ 0xEB00,"Atlus"     },{ 0xC000,"Taito"     },
  259.     { 0x9C00,"Imagineer" },{ 0xC201,"Kemco?"    },{ 0xD101,"Sofel?"    },
  260.     { 0x6101,"Virgin"    },{ 0xBB00,"SunSoft"   },{ 0xCE01,"FCI?"      },
  261.     { 0xB400,"Enix?"     },{ 0xBD01,"Imagesoft" },{ 0x0A01,"Jaleco?"   },
  262.     { 0xDF00,"Altron?"   },{ 0xA700,"Takara?"   },{ 0xEE00,"IGS?"      },
  263.     { 0x8300,"Lozc?"     },{ 0x5001,"Absolute?" },{ 0xDD00,"NCS?"      },
  264.     { 0xE500,"Epoch?"    },{ 0xCB00,"VAP?"      },{ 0x8C00,"Vic Tokai" },
  265.     { 0xC200,"Kemco?"    },{ 0xBF00,"Sammy?"    },
  266.     { 0x1800,"Hudson Soft"    },{ 0xCA01,"Palcom/Ultra" },
  267.     { 0xCA00,"Palcom/Ultra"   },{ 0xC500,"Data East?" },
  268.     { 0xA900,"Technos Japan?" },{ 0xD900,"Banpresto?" },
  269.     { 0x7201,"Broderbund?"    },{ 0x7A01,"Triffix Entertainment?" },
  270.     { 0xE100,"Towachiki?"     },{ 0x9300,"Tsuburava?" },
  271.     { 0xC600,"Tonkin House?"  },{ 0xCE00,"Pony Canyon" },
  272.     { 0x7001,"Infogrames?"    },{ 0x8B01,"Bullet-Proof Software?" },
  273.     { 0x5501,"Park Place?"    },{ 0xEA00,"King Records?" },
  274.     { 0x5D01,"Tradewest?"     },{ 0x6F01,"ElectroBrain?" },
  275.     { 0xAA01,"Broderbund?"    },{ 0xC301,"SquareSoft" },
  276.     { 0x5201,"Activision?"    },{ 0x5A01,"Bitmap Brothers/Mindscape" },
  277.     { 0x5301,"American Sammy" },{ 0x1801,"Hudson Soft"},{ 0x0000,NULL }
  278.   };
  279.  
  280.   int Checksum,I,J,*T;
  281.   FILE *F;
  282.   char *P,S[50];
  283.   word A;
  284.   reg R;
  285.   int rambanks[4]= { 0,1,1,4 };
  286.  
  287.   /*** STARTUP CODE starts here: ***/
  288.   T=(int *)"\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  289. #ifdef LSB_FIRST
  290.   if(*T!=1)
  291.   {
  292.     puts("********** This machine is high-endian. *********");
  293.     puts("Take #define LSB_FIRST out and compile VGB again.");
  294.     return(0);
  295.   }
  296. #else
  297.   if(*T==1)
  298.   {
  299.     puts("********* This machine is low-endian. *********");
  300.     puts("Insert #define LSB_FIRST and compile VGB again.");
  301.     return(0);
  302.   }
  303. #endif
  304.  
  305.   for(I=0;I<256;I++) RAMMap[I]=ROMMap[I]=NULL;
  306.  
  307.   if(Verbose) printf("Allocating 64kB for address space...");
  308.   if(!(RAM=malloc(0x10000)))
  309.   { if(Verbose) puts("FAILED");return(0); }
  310.  
  311.   memset(RAM,NORAM,0x10000);
  312.   for(I=0;I<8;I++) Page[I]=RAM+I*0x2000;
  313.  
  314.   if(Verbose) printf("OK\nOpening %s...",CartName);
  315.   if(!(F=fopen(CartName,"rb")))
  316.   { if(Verbose) puts("FAILED");return(0); }
  317.  
  318.   if(Verbose) printf("reading...");
  319.   if(fread(RAM,1,0x4000,F)!=0x4000)
  320.   { if(Verbose) puts("FAILED");return(0); }
  321.  
  322.   ROMMap[0]=RAM;
  323.   ROMBanks=2<<RAM[0x0148];
  324.   RAMBanks=rambanks[RAM[0x0149]&3];     /* (1<<RAM[0x0149]*2)>>1; */
  325.   Checksum=((word)RAM[0x014E]<<8)+RAM[0x014F];
  326.   MBCType=RAM[0x0147]>3;
  327.  
  328.   P=NULL;
  329.   if((RAM[0x0147]==4)||(RAM[0x0147]>6)) P="Unknown ROM type";
  330.   if(P)
  331.   {
  332.     printf("\nError loading cartridge: %s\n",P);
  333.     fclose(F);return(0);
  334.   }
  335.  
  336.   if(Verbose)
  337.   {
  338.     strncpy(S,RAM+0x0134,16);S[16]='\0';
  339.     printf("OK\n  Name: %s\n",S);
  340.     printf("  Type: %s\n",CartTypes[RAM[0x0147]]);
  341.     printf("  ROM Size: %dx16kB\n",ROMBanks);
  342.     printf("  RAM Size: %dx8kB\n",RAMBanks);
  343.  
  344.     J=((word)RAM[0x014B]<<8)+RAM[0x014A];
  345.     for(I=0,P=NULL;!P&&Companies[I].Name;I++)
  346.       if(J==Companies[I].Code) P=Companies[I].Name;
  347.     printf("  Manufacturer ID: %Xh",J);
  348.     printf(" [%s]\n",P? P:"?");
  349.  
  350.     printf("  Version Number: %Xh\n",RAM[0x014C]);
  351.     printf("  Complement Check: %Xh\n",RAM[0x014D]);
  352.     printf("  Checksum: %Xh\n",Checksum);
  353.     J=((word)RAM[0x0103]<<8)+RAM[0x0102];
  354.     printf("  Start Address: %Xh\n",J);
  355.   }
  356.  
  357.   Checksum+=RAM[0x014E]+RAM[0x014F];
  358.   for(I=0;I<0x4000;I++) Checksum-=RAM[I];
  359.  
  360.   if(Verbose) printf("Loading %dx16kB ROM banks:\n.",ROMBanks);
  361.   for(I=1;I<ROMBanks;I++)
  362.     if(ROMMap[I]=malloc(0x4000))
  363.       if(fread(ROMMap[I],1,0x4000,F)==0x4000)
  364.       {
  365.         for(J=0;J<0x4000;J++) Checksum-=ROMMap[I][J];
  366.         if(Verbose) putchar('.');
  367.       }
  368.       else { if(Verbose) puts("READ FAILED");break; }
  369.     else { if(Verbose) puts("MALLOC FAILED");break; }
  370.  
  371.   fclose(F);if(I<ROMBanks) return(0);
  372.  
  373.   if(CheckCRC&&(Checksum&0xFFFF))
  374.   { puts("\nError loading cartridge: Checksum is wrong");return(0); }
  375.  
  376.   if(Verbose) puts("OK");
  377.  
  378.   if(RAMBanks&&!MBCType)
  379.   {
  380.     if(Verbose) printf("Allocating %dx8kB RAM banks...",RAMBanks);
  381.     for(I=0;I<RAMBanks;I++)
  382.       if(RAMMap[I]=malloc(0x2000))
  383.         memset(RAMMap[I],0,0x2000);
  384.       else
  385.       { if(Verbose) puts("FAILED");return(0); }
  386.     if(Verbose) puts("OK");
  387.   }
  388.  
  389.   if((RAM[0x0147]==3)||(RAM[0x0147]==6))
  390. /*    if(SaveName=malloc(strlen(CartName)+10)) */
  391.     if (SaveName)       /* SaveName is initialized in the startup code */
  392.     {
  393.       /*
  394.       strcpy(SaveName,CartName);
  395.       if(P=strrchr(SaveName,'.')) strcpy(P,".sav");
  396.       else strcat(SaveName,".sav");
  397.       */
  398.       if(Verbose) printf("Opening %s...",SaveName);
  399.       if(F=fopen(SaveName,"rb"))
  400.       {
  401.         if(Verbose) printf("reading...");
  402.         J=RAM[0x0147]==3? 0x2000:0x0200;
  403.         J=(fread(RAMMap[0]? RAMMap[0]:Page[5],1,J,F)==J);
  404.         if(Verbose) puts(J? "OK":"FAILED");
  405.         fclose(F);
  406.       }
  407.       else if(Verbose) puts("FAILED");
  408.     }
  409.  
  410.   if(CheatCount>0)
  411.   {
  412.     if(Verbose) puts("Patching cheats into the ROM code:");
  413.     for(J=0;J<CheatCount;J++)
  414.     {
  415.       A=Cheats[J].Address;
  416.       if(Verbose)
  417.         printf("  at %Xh: %Xh -> %Xh\n",A,Cheats[J].Orig,Cheats[J].Value);
  418.       if(A<0x4000)
  419.       { if(ROMMap[0][A]==Cheats[J].Orig) ROMMap[0][A]=Cheats[J].Value; }
  420.       else
  421.         for(I=0,A-=0x4000;I<ROMBanks;I++)
  422.           if(ROMMap[I][A]==Cheats[J].Orig) ROMMap[I][A]=Cheats[J].Value;
  423.     }
  424.   }
  425.  
  426.   if(ROMBanks<3) ROMMask=0;
  427.   else { for(I=1;I<ROMBanks;I<<=1);ROMMask=I-1;ROMBank=1; }
  428.   if(!RAMMap[0]) RAMMask=0;
  429.   else { for(I=1;I<RAMBanks;I<<=1);RAMMask=I-1;RAMBank=0; }
  430.  
  431.   if(RAMMap[0]) Page[5]=RAMMap[0];
  432.   if(ROMMap[1]) Page[2]=ROMMap[1];
  433.   Page[3]=Page[2]+0x2000;
  434.  
  435.   IPeriod=VPeriod/154;
  436.  
  437.   ChrGen=RAM+0x8800;BgdTab=WndTab=RAM+0x9800;
  438.   LCDCONT=0x81;LCDSTAT=0x00;
  439.   CURLINE=0x00;CMPLINE=0xFF;
  440.   IFLAGS=ISWITCH=0xE0;
  441.   TIMECNT=TIMEMOD=0x01;
  442.   TIMEFRQ=0xF8;
  443.   SIODATA=0x00;
  444.   SIOCONT=0x7E;
  445.   SIOBuf=SIOFlag=0x00;
  446.  
  447.   for(I=0;I<4;I++) SPal0[I]=SPal1[I]=BPal[I]=I;
  448.   BGRDPAL=SPR0PAL=SPR1PAL=0xE4;
  449.  
  450.   if (!InitMachine())
  451.    return 0;
  452.   InitMachineDone=1;
  453.   ResetZ80(&R);Exit_PC=Z80(R);
  454.  
  455.   return(1);
  456. }
  457.  
  458. void TrashGB(void)
  459. {
  460.   FILE *F;
  461.   int I;
  462.  
  463.   if (InitMachineDone)
  464.   {
  465.    //TrashMachine ();
  466.    if(Verbose) printf("EXITED at PC = %Xh.\n",Exit_PC);
  467.   }
  468.   if(SaveName&&((RAM[0x0147]==3)||(RAM[0x0147]==6)))   
  469.   {
  470.     if(Verbose) printf("\nOpening %s...",SaveName);   
  471.     if(F=fopen(SaveName,"wb"))
  472.     { 
  473.       if(Verbose) printf("writing...");
  474.       I=RAM[0x0147]==3? 0x2000:0x0200;
  475.       I=(fwrite(RAMMap[0]? RAMMap[0]:Page[5],1,I,F)==I);
  476.       if(Verbose) puts(I? "OK":"FAILED");
  477.       fclose(F);
  478.     }
  479.     else if(Verbose) puts("FAILED");
  480.   }
  481.  
  482.   //-PG CHANGE-if(SaveName) free(SaveName);
  483.   if(RAM) free(RAM);
  484.   for(I=1;ROMMap[I];I++) free(ROMMap[I]);
  485.   for(I=0;RAMMap[I];I++) free(RAMMap[I]);
  486. }
  487.  
  488. word Interrupt(void)
  489. {
  490.   static byte UCount=1;
  491.   register byte J;
  492.   unsigned tmp;
  493.  
  494.   DIVREG++;SprFlag|=LCDCONT&0x02;J=0x00;
  495.  
  496.   /* Setting HBlank state */
  497.   if(CURLINE<144) { LCDSTAT&=0xFC;J|=0x08; }
  498.  
  499.   /* Generating VBlank interrupt */
  500.   if((CURLINE==144)&&(LCDCONT&0x80))
  501.   {
  502.     LCDSTAT=(LCDSTAT&0xFC)|0x01;J|=0x10;
  503.     if(ISWITCH&VBL_IFLAG) IFLAGS|=VBL_IFLAG;
  504.   }
  505.  
  506.   if(LineDelay)
  507.   {
  508.     if(!UCount&&(CURLINE<144)) RefreshLine(CURLINE);
  509.     CURLINE=(CURLINE>=153)? 0:CURLINE+1;
  510.     if(CURLINE!=CMPLINE) LCDSTAT&=0xFB;
  511.     else { LCDSTAT|=0x04;J|=0x40; }
  512.   }
  513.   else
  514.   {
  515.     if(CURLINE!=CMPLINE) LCDSTAT&=0xFB;
  516.     else { LCDSTAT|=0x04;J|=0x40; }
  517.     CURLINE=(CURLINE>=153)? 0:CURLINE+1;
  518.     if(!UCount&&(CURLINE<144)) RefreshLine(CURLINE);
  519.   }
  520.  
  521.   /* If end of frame reached... */
  522.   if(CURLINE==144)
  523.   {
  524.     if(UCount) UCount--;
  525.     else
  526.     {
  527.       if(SprFlag&&(LCDCONT&0x80)) RefreshSprites();
  528.       RefreshScreen();SprFlag=0;UCount=UPeriod;
  529.     }
  530.   }
  531.   /* Generating LCD controller interrupt */
  532.   if((J&LCDSTAT)&&(ISWITCH&LCD_IFLAG)&&(LCDCONT&0x80)) IFLAGS|=LCD_IFLAG;
  533.  
  534.   /* Generating timer interrupt */
  535.   if(TIMEFRQ&0x04)
  536.   {
  537.    TimerTestParam+=TimerRecurParam;
  538.    if (TimerTestParam&0xFFFF0000)
  539.    {
  540.     tmp=TIMECNT+(TimerTestParam>>16);
  541.     TimerTestParam&=0x0000FFFF;
  542.     if (tmp&0xFFFFFF00)
  543.     {
  544.      TIMECNT=TIMEMOD;
  545.      if(ISWITCH&TIM_IFLAG) IFLAGS|=TIM_IFLAG;
  546.     }
  547.     else
  548.      TIMECNT=tmp;
  549.    }
  550.   }
  551.   if(CURLINE==144)
  552.   {
  553.     /* Generating serial IO interrupt */
  554.     if(SIOFlag&0x01)
  555.     {
  556.       SIOFlag&=0xFE;SIOCONT&=0x7F;
  557.       if(ISWITCH&SIO_IFLAG) IFLAGS|=SIO_IFLAG;
  558.     }
  559.  
  560.     /* Updating joystick */
  561.     J=JOYPAD|0xCF;JoyState=Joystick();
  562.     if(!(J&0x10)) JOYPAD=J&(JoyState|0xF0);
  563.     if(!(J&0x20)) JOYPAD=J&((JoyState>>4)|0xF0);
  564.   }
  565.  
  566.   /* Determining interrupt address */
  567.   if(IFLAGS&EXT_IFLAG) { IMask=EXT_IFLAG;return(0x0060); }
  568.   if(IFLAGS&SIO_IFLAG) { IMask=SIO_IFLAG;return(0x0058); }
  569.   if(IFLAGS&TIM_IFLAG) { IMask=TIM_IFLAG;return(0x0050); }
  570.   if(IFLAGS&LCD_IFLAG) { IMask=LCD_IFLAG;return(0x0048); }
  571.   if(IFLAGS&VBL_IFLAG) { IMask=VBL_IFLAG;return(0x0040); }
  572.   return(0xFFFF); 
  573.  
  574. int AddCheat(char *Cheat)
  575. {
  576.   static char Digits[]="0123456789ABCDEF";
  577.   int X1,X2;
  578.  
  579.   if(CheatCount>=MAXCHEAT) return(0);
  580.   else
  581.   {
  582.     if((Cheat[3]!='-')||(Cheat[7]!='-')) return(0);
  583.     X1=strchr(Digits,toupper(Cheat[0]))-Digits;
  584.     X2=strchr(Digits,toupper(Cheat[1]))-Digits;
  585.     if((X1<0)||(X2<0)) return(0);
  586.     else Cheats[CheatCount].Value=X1*16+X2;
  587.     X1=strchr(Digits,toupper(Cheat[4]))-Digits;
  588.     X2=strchr(Digits,toupper(Cheat[5]))-Digits;
  589.     if((X1<0)||(X2<0)) return(0);
  590.     else Cheats[CheatCount].Address=X1*16+X2;
  591.     X1=strchr(Digits,toupper(Cheat[6]))-Digits;
  592.     X2=strchr(Digits,toupper(Cheat[2]))-Digits;
  593.     if((X1<0)||(X2<0)) return(0);
  594.     else Cheats[CheatCount].Address+=256*((15-X1)*16+X2);
  595.     X1=strchr(Digits,toupper(Cheat[10]))-Digits;
  596.     X2=strchr(Digits,toupper(Cheat[8]))-Digits;
  597.     if((X1<0)||(X2<0)) return(0);
  598.     X1=~(16*X2+X1);
  599.     X1=((X1>>2)&0x3F)|((X1<<6)&0xC0);
  600.     Cheats[CheatCount].Orig=X1^0x45;
  601.  
  602.     if(Cheats[CheatCount].Address>=0x8000) return(0);
  603.     CheatCount++;return(1);
  604.   }
  605. }
  606.