Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://xNES-0.49-4.src.rpm:44552/xnessrc.tar.gz  info  downloads

xNES/ 40755    765    144           0  6461743167  10652 5ustar  chuckjrusersxNES/msg.c100644    765    144        1662  6440366340  11675 0ustar  chuckjrusers#include <vga.h>
#include <vgagl.h>
#include <stdarg.h>

#include "nes.h"
#include "msg.h"

void *GfxFont;

int MessageFrameCount = 0;
char *Message = NULL;

extern int sWIDTH;
extern int sHEIGHT;

void gl_myinit(int mode, int maxx, int maxy)
{
	GfxFont = (void *)malloc(256 * 8 * 8);
	if(!GfxFont) {
		TrashMachine();
		printf("Cannot malloc!\n");
		exit(1);
	}
	gl_setcontextvga(mode);
	gl_setcontextwidth(maxx);
	gl_setcontextheight(maxy);
	gl_expandfont(8, 8, 3, gl_font8x8, GfxFont);
	gl_setfont(8, 8, GfxFont);
	gl_setwritemode(WRITEMODE_MASKED);
}

void DisplayMsg(char *msg)
{
	MessageFrameCount = 40;
	if(Message)
		free(Message);
	Message = (char *)malloc(strlen(msg) + 1);
	strcpy(Message, msg);
}

void DrawMsg()
{
	int px = 32;
	int py = (sHEIGHT - (8 * 3));
	
	if(sWIDTH == 256 && sHEIGHT == 240)
		px = 5;
	/* Always in the same spot */
	if(MessageFrameCount) {
		gl_colorfont(8, 8, Red, GfxFont);
		gl_write(px, py, Message);
	}
}xNES/M6502.c100644    765    144       22367  6433657601  11652 0ustar  chuckjrusers/** M6502: portable 6502 emulator ****************************/
/**                                                         **/
/**                         M6502.c                         **/
/**                                                         **/
/** This file contains implementation for 6502 CPU. Don't   **/
/** forget to provide Rd6502(), Wr6502(), Loop6502(), and   **/
/** possibly Op6502() functions to accomodate the emulated  **/
/** machine's architecture.                                 **/
/**                                                         **/
/** Copyright (C) Marat Fayzullin 1996                      **/
/**               Alex Krasivsky  1996                      **/
/**     You are not allowed to distribute this software     **/
/**     commercially. Please, notify me, if you make any    **/   
/**     changes to this file.                               **/
/*************************************************************/

#include "M6502.h"
#include "Tables.h"
#include <stdio.h>

/** INLINE ***************************************************/
/** Different compilers inline C functions differently.     **/
/*************************************************************/
#ifdef __GNUC__
#define INLINE inline
#else
#define INLINE static
#endif

/** System-Dependent Stuff ***********************************/
/** This is system-dependent code put here to speed things  **/
/** up. It has to stay inlined to be fast.                  **/
/*************************************************************/
#ifdef INES
#define FAST_RDOP
extern byte *Page[];
INLINE byte Op6502(register word A) { return(Page[A>>13][A&0x1FFF]); }
#endif

/** FAST_RDOP ************************************************/
/** With this #define not present, Rd6502() should perform  **/
/** the functions of Rd6502().                              **/
/*************************************************************/
#ifndef FAST_RDOP
#define Op6502(A) Rd6502(A)
#endif

/** Addressing Methods ***************************************/
/** These macros calculate and return effective addresses.  **/
/*************************************************************/
#define MC_Ab(Rg)	M_LDWORD(Rg)
#define MC_Zp(Rg)	Rg.B.l=Op6502(R->PC.W++);Rg.B.h=0
#define MC_Zx(Rg)	Rg.B.l=Op6502(R->PC.W++)+R->X;Rg.B.h=0
#define MC_Zy(Rg)	Rg.B.l=Op6502(R->PC.W++)+R->Y;Rg.B.h=0
#define MC_Ax(Rg)	M_LDWORD(Rg);Rg.W+=R->X
#define MC_Ay(Rg)	M_LDWORD(Rg);Rg.W+=R->Y
#define MC_Ix(Rg)	K.B.l=Op6502(R->PC.W++)+R->X;K.B.h=0; \
			Rg.B.l=Op6502(K.W++);Rg.B.h=Op6502(K.W)
#define MC_Iy(Rg)	K.B.l=Op6502(R->PC.W++);K.B.h=0; \
			Rg.B.l=Op6502(K.W++);Rg.B.h=Op6502(K.W); \
			Rg.W+=R->Y

/** Reading From Memory **************************************/
/** These macros calculate address and read from it.        **/
/*************************************************************/
#define MR_Ab(Rg)	MC_Ab(J);Rg=Rd6502(J.W)
#define MR_Im(Rg)	Rg=Op6502(R->PC.W++)
#define	MR_Zp(Rg)	MC_Zp(J);Rg=Rd6502(J.W)
#define MR_Zx(Rg)	MC_Zx(J);Rg=Rd6502(J.W)
#define MR_Zy(Rg)	MC_Zy(J);Rg=Rd6502(J.W)
#define	MR_Ax(Rg)	MC_Ax(J);Rg=Rd6502(J.W)
#define MR_Ay(Rg)	MC_Ay(J);Rg=Rd6502(J.W)
#define MR_Ix(Rg)	MC_Ix(J);Rg=Rd6502(J.W)
#define MR_Iy(Rg)	MC_Iy(J);Rg=Rd6502(J.W)

/** Writing To Memory ****************************************/
/** These macros calculate address and write to it.         **/
/*************************************************************/
#define MW_Ab(Rg)	MC_Ab(J);Wr6502(J.W,Rg)
#define MW_Zp(Rg)	MC_Zp(J);Wr6502(J.W,Rg)
#define MW_Zx(Rg)	MC_Zx(J);Wr6502(J.W,Rg)
#define MW_Zy(Rg)	MC_Zy(J);Wr6502(J.W,Rg)
#define MW_Ax(Rg)	MC_Ax(J);Wr6502(J.W,Rg)
#define MW_Ay(Rg)	MC_Ay(J);Wr6502(J.W,Rg)
#define MW_Ix(Rg)	MC_Ix(J);Wr6502(J.W,Rg)
#define MW_Iy(Rg)	MC_Iy(J);Wr6502(J.W,Rg)

/** Modifying Memory *****************************************/
/** These macros calculate address and modify it.           **/
/*************************************************************/
#define MM_Ab(Cmd)	MC_Ab(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
#define MM_Zp(Cmd)	MC_Zp(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
#define MM_Zx(Cmd)	MC_Zx(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
#define MM_Ax(Cmd)	MC_Ax(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)

/** Other Macros *********************************************/
/** Calculating flags, stack, jumps, arithmetics, etc.      **/
/*************************************************************/
#define M_FL(Rg)	R->P=(R->P&~(Z_FLAG|N_FLAG))|ZNTable[Rg]
#define M_LDWORD(Rg)	Rg.B.l=Op6502(R->PC.W++);Rg.B.h=Op6502(R->PC.W++)

#define M_PUSH(Rg)	Wr6502(0x0100|R->S,Rg);R->S--
#define M_POP(Rg)	R->S++;Rg=Op6502(0x0100|R->S)
#define M_JR		R->PC.W+=(offset)Op6502(R->PC.W)+1;R->ICount--

#define M_ADC(Rg) \
  if(R->P&D_FLAG) \
  { \
    K.B.l=(R->A&0x0F)+(Rg&0x0F)+(R->P&C_FLAG); \
    K.B.h=(R->A>>4)+(Rg>>4)+(K.B.l>15? 1:0); \
    if(K.B.l>9) { K.B.l+=6;K.B.h++; } \
    if(K.B.h>9) K.B.h+=6; \
    R->A=(K.B.l&0x0F)|(K.B.h<<4); \
    R->P=(R->P&~C_FLAG)|(K.B.h>15? C_FLAG:0); \
  } \
  else \
  { \
    K.W=R->A+Rg+(R->P&C_FLAG); \
    R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
    R->P|=(~(R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
          (K.B.h? C_FLAG:0)|ZNTable[K.B.l]; \
    R->A=K.B.l; \
  }

/* Warning! C_FLAG is inverted before SBC and after it */
#define M_SBC(Rg) \
  if(R->P&D_FLAG) \
  { \
    K.B.l=(R->A&0x0F)-(Rg&0x0F)-(~R->P&C_FLAG); \
    if(K.B.l&0x10) K.B.l-=6; \
    K.B.h=(R->A>>4)-(Rg>>4)-(K.B.l&0x10); \
    if(K.B.h&0x10) K.B.h-=6; \
    R->A=(K.B.l&0x0F)|(K.B.h<<4); \
    R->P=(R->P&~C_FLAG)|(K.B.h>15? 0:C_FLAG); \
  } \
  else \
  { \
    K.W=R->A-Rg-(~R->P&C_FLAG); \
    R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
    R->P|=((R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
          (K.B.h? 0:C_FLAG)|ZNTable[K.B.l]; \
    R->A=K.B.l; \
  }

#define M_CMP(Rg1,Rg2) \
  K.W=Rg1-Rg2; \
  R->P&=~(N_FLAG|Z_FLAG|C_FLAG); \
  R->P|=ZNTable[K.B.l]|(K.B.h? 0:C_FLAG)
#define M_BIT(Rg) \
  R->P&=~(N_FLAG|V_FLAG|Z_FLAG); \
  R->P|=(Rg&(N_FLAG|V_FLAG))|(Rg&R->A? 0:Z_FLAG)

#define M_AND(Rg)	R->A&=Rg;M_FL(R->A)
#define M_ORA(Rg)	R->A|=Rg;M_FL(R->A)
#define M_EOR(Rg)	R->A^=Rg;M_FL(R->A)
#define M_INC(Rg)	Rg++;M_FL(Rg)
#define M_DEC(Rg)	Rg--;M_FL(Rg)

#define M_ASL(Rg)	R->P&=~C_FLAG;R->P|=Rg>>7;Rg<<=1;M_FL(Rg)
#define M_LSR(Rg)	R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg>>=1;M_FL(Rg)
#define M_ROL(Rg)	K.B.l=(Rg<<1)|(R->P&C_FLAG); \
			R->P&=~C_FLAG;R->P|=Rg>>7;Rg=K.B.l; \
			M_FL(Rg)
#define M_ROR(Rg)	K.B.l=(Rg>>1)|(R->P<<7); \
			R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg=K.B.l; \
			M_FL(Rg)

/** Reset6502() **********************************************/
/** This function can be used to reset the registers before **/
/** starting execution with Run6502(). It sets registers to **/
/** their initial values.                                   **/
/*************************************************************/
void Reset6502(M6502 *R)
{
  R->A=R->X=R->Y=0x00;
  R->P=Z_FLAG|R_FLAG;
  R->S=0xFF;
  R->PC.B.l=Rd6502(0xFFFC);
  R->PC.B.h=Rd6502(0xFFFD);   
  R->ICount=R->IPeriod;
  R->IRequest=INT_NONE;
  R->AfterCLI=0;
  R->TrapBadOps = 0;
}

/** Exec6502() ***********************************************/
/** This function will execute a single 6502 opcode. It     **/
/** will then return next PC, and current register values   **/
/** in R.                                                   **/
/*************************************************************/
word Exec6502(M6502 *R)
{
  register pair J,K;
  register byte I;

  I=Op6502(R->PC.W++);
  R->ICount-=Cycles[I];
  switch(I)
  {
#include "Codes.h"
  }

  /* We are done */
  return(R->PC.W);
}

/** Int6502() ************************************************/
/** This function will generate interrupt of a given type.  **/
/** INT_NMI will cause a non-maskable interrupt. INT_IRQ    **/
/** will cause a normal interrupt, unless I_FLAG set in R.  **/
/*************************************************************/
void Int6502(M6502 *R,byte Type)
{
  register pair J;

  if((Type==INT_NMI)||((Type==INT_IRQ)&&!(R->P&I_FLAG)))
  {
    R->ICount-=7;
    M_PUSH(R->PC.B.h);
    M_PUSH(R->PC.B.l);
    M_PUSH(R->P&~B_FLAG);
    R->P&=~D_FLAG;
    if(Type==INT_NMI) J.W=0xFFFA; else { R->P|=I_FLAG;J.W=0xFFFE; }
    R->PC.B.l=Rd6502(J.W++);
    R->PC.B.h=Rd6502(J.W);
  }
}

/** Run6502() ************************************************/
/** This function will run 6502 code until Loop6502() call  **/
/** returns INT_QUIT. It will return the PC at which        **/
/** emulation stopped, and current register values in R.    **/
/*************************************************************/
word Run6502(M6502 *R)
{
  register pair J,K;
  register byte I;
  register int r;
  
  for(;;)
  {
#ifdef DEBUG
    /* Turn tracing on when reached trap address */
    if(R->PC.W==R->Trap) R->Trace=1;
    /* Call single-step debugger, exit if requested */
    if(R->Trace)
      if(!Debug6502(R)) return(R->PC.W);
#endif

    I=Op6502(R->PC.W++);
    R->ICount-=Cycles[I];
    switch(I)
    {
#include "Codes.h"
    }
    if(R->ICount <= 0) {
    	if(R->AfterCLI) {
    		I = R->IRequest;
    		R->ICount += R->IBackup - 1;
    		R->AfterCLI = 0;
    	} else {
	        I=Loop6502(R);            /* Call the periodic handler */
	        R->ICount =R->IPeriod;     /* Reset the cycle counter   */
	}
      if(I==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT     */
      if(I) Int6502(R,I);              /* Interrupt if needed  */ 
    }
  }

  /* Execution stopped */
  return(R->PC.W);
}
xNES/xnes.c100644    765    144      112722  6461743123  12125 0ustar  chuckjrusers/*
 * xNES - Nintendo Emulator  --  Linux
 *
 * * 1997-8 by the xNES team
 *    Richard Bannister - MacOS port
 *    Chuck Mason - Linux port, core code
 *    Jeff Mitchell - Unix port
 *    Brad Oliver - MacOS port, core code, coordinator
 *
 *    Thanks to Nicolas Hamel and David Michel for the original code.
 *
 * File: XNES.C - Nintendo Hardware Emulation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include        <stdio.h>
#include        <stdlib.h>
#include        <string.h>

#include        <signal.h>

#include        <malloc.h>
#include 	<vgakeyboard.h>


#include        "M6502.h"
#include        "xnes.h"
#include        "nes.h"
#include	"mmc.h"
#include	"msg.h"

/*#define         SnapScreen()    { save_pcx( "XNes.pcx", screen , Pallete ); }*/
#define SnapScreen()
#define getch() vga_getch()
#define FatalError( msg ) { printf("%s\n",msg); exit(1); }

#define Help() printf( "Syntax :\n%s <filename.nes> [-flags]\n\n\t\t" \
                       "-f x \t\t: Set frame rate to x (default : 1/3)\n\t\t" \
                       "-vga\t\t: Use standard VGA mode\n\t\t" \
                       "-bat s\t\t: Use alternate savegame file\n\t\t" \
                       "-stretch\t: Stretches 320x200 (only) to fit fullscreen.\n\t\t" \
                       "-nosound\t: Disables sound.\n\t\t" \
                       "-nojoy\t\t: Disable use of joystick\n", argv[0] );

#define         Version         "0.49"       

#define         TOP_VISIBLE_SCANLINE                    0
#define         BOTTOM_VISIBLE_SCANLINE                 231

#define		PPU_Control0 RAM[0x2000]
#define		PPU_Control1 RAM[0x2001]
#define		PPU_Status   RAM[0x2002]
#define		PPU_Addr     PPU_REG_6

#define 	NEW_INTERRUPT_TIMING
#define		VRAM_SIZE 0x8000

static int cycles_per_scanline  = 115;
static int scanlines_per_frame  = 242;
int     current_scanline = TOP_VISIBLE_SCANLINE;

int     FirstRead = 1;
int     Joypad_Toggle = 0;
int     Joypad_Read_1 = 1;
//
// Option pour le skip frame
//

/* Default was 1 if we have scanbased line gfx */

int     FrameRate = 2;          // 3 par d‚faut
int     CurrentFrame = 0;
int     iperiod = 115;

int     MMC, MMC_chr, MMC_Bank_Size, MMC1_Base;
int     MMC_low_base, MMC_high_base, MMC4_mid_base, MMC4_hmid_base;
int	MMC1_Reg_0 = 0, 
	MMC1_Reg_1 = 0, 
	MMC1_Reg_2 = 0, 
	MMC1_Reg_3 = 0;
int	MMC1_Reg_0_WriteNo = 0 , MMC1_Reg_1_WriteNo = 0 , MMC1_Reg_2_WriteNo = 0 , MMC1_Reg_3_WriteNo = 0;
int	CHR_Ram = 0 , PRG_Rom = 0;
int	Panning;
int     MMC_Base_Bootup,MMC_Size_Select;
int     MMC1_High = 0;

int	MMC4_IRQ = -1;
int	MMC4_DOIRQ = 0;

int	DW4 = 0; /* 1MByte MMC1 Cart */
char   *DW4Banks[4]; /* Each bank is 256kb */
int	DW3 = 0; /* 512KByte MMC1 Cart */
char   *DW3Banks[2]; /* Each bank is 256kb */

mmc    *Mapper;

M6502  *M;
char   *CmdName;
char   *RomName;

static int spritePause;
int UseSound = 1;

byte   *dirty_VRAM;

//
// Ouf on arrive au main :)
//

int	Reset_Mapper(int);
void	Mapper1_Write(int, byte);
void	Mapper4_Write(int, byte);


main( int argc , char *argv[] )
{
        FILE    *Nes,*Battery_File;

        char    Tmp[80] , OptROM[2] , Option[80] , Argument[80];
        int Cart_Size , Wait = 0 , i,Addr,Have_WRAM_File = 0, j=0;
	char	pr, cr;
        int     sizeCHR = 0, sizePRG = 0;
	int	options;
	int	err;
	        
        CmdName = argv[0];
        strcpy( Battery_Name,"default.srm");
        	
        printf("*********************************************************\n");
        printf("*            xNES - Nintendo Emulator v0.5.0            *\n");
        printf("*********************************************************\n");
        printf("* - 1998 by Brad Oliver, Chuck Mason, Richard Bannister,*\n");
        printf("* Jeff Mitchell, and Nicolas Hamel. All Rights Reserved.*\n");
        printf("*********************************************************\n\n");

	
        Linear = 0;
        Vga = 0;

        MMC_low_base = 0;
        MMC_high_base = 0;                
	Trainer = 0;

        //      Pointeur
        M = malloc( sizeof( M6502 ) );

        //      V‚rifie les arguments et actionne les options
        if( argc == 1 )
		FatalError("Bad Number of arguments ! Type -? for help.");
		        
        for( i = 1 ; i < argc ; i++ )
        {
                strcpy( Argument , argv[ i ] );

                if( Argument[ 0 ] == '-' )
                {
                        if( strcmp( Argument , "-f" ) == 0 )
                        {
                                FrameRate = atoi(argv[ ++i ]);
                                printf("Frame Rate set to 1/%d.\n",FrameRate);
                                Wait = 1;
                        }
                        if( strcmp( Argument , "-?" ) == 0 )
                        {
                                Help();
                                exit(1);
                        }
                        if( strcmp( Argument , "-linear" ) == 0 )
                        {
                                Linear = 1;
                                puts("Using Linear frame buffer.");
                        }
                        if( strcmp( Argument , "-vga" ) == 0 )
                        {
                        	if(Vga != 1) {
	                                Vga = 1;
        	                        puts("Using VGA...");
        	                }
                        }
                        if( strcmp( Argument , "-stretch") == 0 )
                        {
                        	stretch = 1;
                        	printf("Stretch-Screen selected...");
                        	if( Vga != 1 ) {
                        		puts("Using VGA.");
                        		Vga = 1;
                        	} else
                        		puts("");
                        }
                        if( strcmp( Argument , "-bat" ) == 0 )
                        {
                        	Have_WRAM_File = 1;
	                        strcpy( Battery_Name , argv[ ++i ] );
                                printf("Battery Name : %s\n",Battery_Name);
                        }
                        if( strcmp( Argument , "-nojoy" ) == 0 )
                        {
                        	NoJoy = 1;
                        }
                        if( strcmp( Argument , "-240" ) == 0 )
                        {
                        	Vga = 2;
                        }
                        if( strcmp( Argument , "-nosound" ) == 0 )
                        {
                        	UseSound = 0;
                        	break;
                        }
                        if( strcmp( Argument , "-?" ) == 0 )
                        {
                        	Help();
                        	exit(1);
                        }
                        if( strcmp( Argument , "-cps" ) == 0 )
                        {
                        	cycles_per_scanline = atoi(argv[++i]);
                        	printf("Cycles set to %d\n", cycles_per_scanline);
                        }
                } else { /* Fix */
                	if(j == 1) {
                		puts("Two file names? -- Exit.");
                		exit(1);
                	}
                	strcpy(CartName, Argument);
                	j = 1;
                }
        }

	if(j != 1) {
		puts("You must specify an NES rom!");
		exit(1);
	}
	j = 0;
	
        puts("");

        strcpy( CartName , argv[1] );

	/* Sets up save-state file name */
	RomName = (char *)malloc(strlen(CartName) + 1);
	strcpy( RomName , CartName );
	*strrchr( RomName , '.' ) = '\0';
	strcpy( &RomName[strlen(RomName)] , ".xns");

        // V‚rifie si c'est bien un format iNes

        Nes = fopen( CartName , "rb" );

        if( !Nes )                            
        {                     
		FatalError("File not found!");
	}
        else
        {
                fread( Tmp , 1 , 3 , Nes );
                Tmp[3] = '\0';
                if( strcmp( Tmp , "NES" ) != 0 )
                {
                        fclose(Nes);
                        puts("Unsupported file format.");
                        exit(1);
                }
        }

        puts("iNes file format found.");

        fseek( Nes, 4 , 0 );

        // Prise du nombre de PRG Rom et de CHR Ram

        PRG_Rom = fgetc( Nes );

	CHR_Ram = fgetc( Nes );
	
        printf("[ %d ] of PRG Rom\n",PRG_Rom);
        printf("[ %d ] of CHR Ram\n",CHR_Ram);

        Cart_Size = (PRG_Rom<<4)+CHR_Ram*8;

	MMC_high_base = (PRG_Rom - 1) * 16384;
	
        printf( "\n\tSize of the Cartridge : [ %d Ko ]\n\n" , Cart_Size );

        // V‚rifie si la cartouche est support‚
        // MMCs 2 en cours........

        fseek( Nes , 6 , 0 );
        i = fgetc( Nes );

        // Prise des options de la ROM
        
        // here i check the options of the ROM
        // V‚rifie si il a un MMcs si oui >> J'ABANDONNE !!! Okay David ?

        // J'ai chang‚ le OptROM[1] par atoi(OptROM[1])
        // comme ‡a pas de pb avec les a-->f si maj. ou min.:)

        // J'ai aussi vir‚ le d‚fault...inutile
	MMC = (i & 0xF0)  >> 4;
	
	for(j = 0; mmc_list[j].iNesMapper != -1; j++) {
		if(MMC == mmc_list[j].iNesMapper) 
			break;
	}
	Mapper = &mmc_list[j];
	if(MMC == Mapper->iNesMapper)
		printf("Mapper %d found (%s)\n", Mapper->iNesMapper, Mapper->desc);
	else {
		printf("Mapper %d not found (%s)\n", MMC, Mapper->desc);
		goto error2;
	}
		
	options = i & 0x0F;

	Mirroring = (options & 0x01) + 1;
	Battery = options & 0x02;
	Trainer = options & 0x04;
	SVRam = options & 0x08;

	/* Added
	 * Checks to see if game is one meg and uses MMC1
	 */
	if(MMC == 1 && Cart_Size == 1024) 
		DW4 = 1;
	else if(MMC == 1 && Cart_Size == 512)
		DW3 = 1;
				
        switch( Mirroring )
        {
                case 1:
                        puts("Horizontal Mirroring found.");
                        break;
                case 2:
                        puts("Vertical Mirroring found.");
                        break;
        }


        // J'ai vir‚ le case 0

        // Allocation de la m‚moire

        puts("Allocating Memory.");

	sizePRG = ( PRG_Rom+1 ) * 16 * 1024;
	sizeCHR = ( CHR_Ram+1 ) * 8 * 1024;
	
        RAM = (byte *)malloc( 0x10000 );

	if(DW4 == 0 && DW3 == 0)
		ROM = (byte *)malloc( sizePRG );
	else if(DW4 == 1) {  /* Rom is a pointer to the actual bank */
		for(j = 0; j < 4; j++) {
			if((DW4Banks[j] = (char *)malloc(256*1024)) == NULL) {
				printf("Cannot malloc!!\n");
				exit(1);
			}
		}
		ROM = DW4Banks[0];
	} else if(DW3 == 1) {
		for(j = 0; j < 2; j++) {
			if((DW3Banks[j] = (char *)malloc(256*1024)) == NULL) {
				printf("Cannot malloc!!\n");
				exit(1);
			}
		}
		ROM = DW3Banks[0];
	}
	

	VRAM = (byte *)malloc( VRAM_SIZE );
	
	VROM = (byte *)malloc( sizeCHR );
                dirty_VRAM = malloc (VRAM_SIZE);

	SRAM = (byte *)malloc( 0x0100 );

	if( !RAM || !ROM || !VRAM || !VROM || !SRAM )
		FatalError("Not enough memory\n");

        memset( SRAM , 0 , 0x0100 );
        memset( RAM , 0 , 0x8000 );

	if(DW4 == 0 && DW3 == 0)
	        memset( ROM , 0 , sizePRG );

        memset( VRAM , 0 , VRAM_SIZE );
        memset( VROM , 0 , sizeCHR );
        memset( dirty_VRAM , 0 , VRAM_SIZE );
                                        			
        printf("\nLoading ROM...");

	fseek(Nes, 16, 0);

	if(Trainer) /* Load trainer at 0x7000 if it exists */
	{
		printf("Trainer found...");
		fflush(stdout);
		fread(&RAM[0x7000], 1, 0x200, Nes);
	}

	if(PRG_Rom == 1) {
		printf("Only 1 PRG-ROM Found...");
		fflush(stdout);
		fread(&ROM[0x4000], 1, 0x4000, Nes);
	} else if(DW4 == 1) {
		printf("Dragon Warrior 4 ROM Found...");
		for(j = 0; j < 4; j++)
			fread(DW4Banks[j], 1, (256 * 1024), Nes);
	} else if(DW3 == 1) {
		printf("512Kb Cart information...");
		for(j = 0; j < 2; j++)
			fread(DW3Banks[j], 1, (256 * 1024), Nes);
	} else
		fread(ROM, PRG_Rom, 0x4000, Nes);

	if(CHR_Ram > 0)
		fread(VROM, CHR_Ram, 0x2000, Nes);

	puts("Ok.");


        if(Battery)
        {
                puts("A backed memory has been found.");

                // Chargement de la Backed Memory
		if(!Have_WRAM_File) 
		{
	                strcpy( Battery_Name , CartName );
        	        strcpy( &Battery_Name[ strlen( Battery_Name ) -4 ] , ".srm");
        	}
                printf("  Loading %s...",Battery_Name);

                Battery_File = fopen( Battery_Name , "rb" );

                if( !Battery_File )
                {
                        puts("Failed!");
                        puts("Cannot find the battery. Seems to be the first use of game.");
                }
                else                        
                {
                        fread( &RAM[ 0x6000 ] , 1 , 0x2000 , Battery_File );
                        puts("Ok.");
                        fclose( Battery_File );
                }

        }                

	err = Reset_Mapper(MMC);
	
	switch(err) {
		case 0:
			break;
		case 1:
			break;
		case 2:
			goto error2;
			break;
	}
	
        fflush(stdin);
	fflush(stdout);
	
        InitMachine();
        
	Reset_Nes();
        Run6502(M);

        TrashMachine();

        puts("\n  Thanks for using XNes!");

        free(RAM);
	
	if(DW4 == 0 && DW3 == 0)
	        free(ROM);

        free(VRAM);
        free(SRAM);
        free(VROM);
        free(dirty_VRAM);

	if(DW4) {
		for(j = 0; j < 4; j++)
			free(DW4Banks[j]);
	} else if(DW3) {
		for(j = 0; j < 2; j++)
			free(DW3Banks[j]);
	}
	
error2:
        free(M);
        fclose(Nes);
}

// **********************************************************************
// *                                                                    *
// *                  FONCTION SPECIFIQUE … XNES                        *
// *                                                                    *
// **********************************************************************

// Cela n'aurait pu ˆtre accompli si David ne m'aurait aider
// Encore un greeting ! 

inline byte Rd6502(register word addr)
{
        byte    retour;
        int     key;

        // Un,dos,tres , yarrive … compter sur mes doigts.

        switch (addr & 0xE000)
        {
        case 0x0000:
        {
                // Access RAM standard
                return( RAM[ addr&0x07FF ] );
        }
        case 0x2000:
        {
            switch (addr)
            {

            case 0x2000:
            {
                return( RAM[ addr ] );
            }
            case 0x2001:
            {
                return( RAM[ addr ] );
            }
            case 0x2002:
            {
                // 0x2002 : PPU Status Register
                // Standard
                retour = RAM[ addr ];
                
#ifndef NEW_INTERRUPT_TIMING        
		RAM[ 0x2002 ] ^= 0x80;
		RAM[ 0x2002 ] ^= 0x40;
		spritePause ++;
#else
		/* Reset sprite hit flag */
/*		RAM[ 0x2002 ] &= ~0x40;		
		RAM[ 0x2002 ] &= ~0x80;*/
#endif		
		
                return( retour );
            }
            case 0x2003:
            {
                // Sprite Memory Address
                // Ce PORT est seulement en ‚criture normalement

                return( RAM[ addr ] );
            }
            case 0x2004:
            {
                // SPRITE MEMORY DATA
                // Ecriture et Lecture
                return( RAM[0x2003] );
            }
            case 0x2005:
            {
	                return( RAM[ addr ] );
            }
            case 0x2006:
            {
                // PPU Memory Adress
                // THIS NIGHT A DAVID SAVE MY LIFE ....:))

                return( PPU_REG_6 );
            }                
            case 0x2007:
            {
                // PPU IO Register

                // Lit ou Ecrit la VRAM … l'adresse sp‚cifi‚ en 0x2006


		if(FirstRead) {
			FirstRead--;
			return 0;
		}
		PPU_REG_6 &= 0x3FFF;
		retour = VRAM[PPU_REG_6];
		if(RAM[0x2000] & 0x40)
			PPU_REG_6 += 32;
		else
			PPU_REG_6 += 1;
			
                return( retour );
            }
            default:
                return( RAM[ addr ] );
            }

        }
        case 0x4000:
        switch(addr)
        {
		case 0x4014:
                {
                	return( RAM[ addr ] );
                }
                case 0x4016:
                {
                        RAM[0x4016] = ReadBit( Joypad_1, Joypad_Read_1);

                        Joypad_Read_1 = (Joypad_Read_1 + 1) & 0x7;

/*                        if( Joypad_Read_1 == 0 )
                                Joypad_1 = 0;                                                        */

                        return (RAM[0x4016]);
                }
                // A ecrire
                default:
                                return( RAM[addr] );
        }

        case 0x6000:
                return( RAM[addr] );
	default:
	{
		// Reading ROM
		return Mapper->Read( addr );		
		break;
	}
	}
}		
        
inline void Wr6502(register word addr, register byte Value)
{
        int     i;      // Pour le for
	char	tmp[0x1000];
	static int reg0, reg1, reg2, reg3;
		 
	static int MMC_mode;
	
        switch ( addr & 0xE000 )
        {
        case 0x0000:
        {
            // L… je crois qu'il y a eu une petite erreur
            // La ram de 0x0000 … 0x0800 et r‚fl‚chi trois fois :

            RAM[ addr & 0x7FF ] = Value;
            break;
        }
        case 0x2000:
            switch (addr)
            {

            case 0x2000:
            {
                // 0x2000 : PPU Control Register #1
                // Ecriture seulement

                RAM[0x2000] = Value;
                break;
            }
            case 0x2001:
            {
                // 0x2001 : PPU Control Register #2
                // Ecriture Seulement

                RAM[ addr ] = Value;
                break;        
            }
            case 0x2003:
            {
                // Port SPRITE MEMORY ADRESS
                // Ecriture seulement

                RAM[addr] = Value;
                break;
            }

            case 0x2004:
            {
                // SPRITE IO
                // Easy !:)
                SRAM[ RAM[0x2003] ] = Value;

                RAM[ 0x2003 ]++; // Incr‚mentation de 1
                break;
            }                        

            case 0x2005:
            {
                if( BGScroll_toggle )
                {
                        // Background Scroll Register
                        // C'est un double write en premier il ‚crite
                        // Le scrolling Horrizontal puis le vertical

                        // Donc Ici le vertical

                        // Pour l'instant on s'en fout

                        // PPU_REG_5A = Value;
                        if( Value < 240 )
                        	PPU_REG_5A = Value;
                        else
                        	PPU_REG_5A = 0;
                }
                else
                {
                        // Horizontal

                        PPU_REG_5B = Value;
                }

                BGScroll_toggle =! BGScroll_toggle;
                break;
            }

            // 0x2006 & 0x2007 par MrDavid
                        
            case 0x2006:
            {
                // PPU Memory Adress

                if( PPU_addr_toggle == 1)
                {
                        // Ecriture des 8 bits inf‚rieur
                        PPU_REG_6 = ( PPU_REG_6 & 0xFF00 ) | ( Value );
                        PPU_addr_toggle = 0;
                }
                else
                {
                        // Ecriture des 8 bits sup‚rieur
                        PPU_REG_6 = ( PPU_REG_6 & 0xFF ) | ( Value << 8 );
                        PPU_addr_toggle = 1;
                }

                FirstRead = 1;

                break;
            }

            case 0x2007:
            {
                // PPU IO Register

                if( ReadBit( RAM[ 0x2002 ] , 5 ) == 1 )
                        break;

                VRAM[ PPU_REG_6 ] = Value;

                if( Mirroring == 0 )
                {
                        VRAM[ PPU_REG_6+0x400 ] = Value;
                        VRAM[ PPU_REG_6+0x800 ] = Value;
                        VRAM[ PPU_REG_6+0xC00 ] = Value;
                }

		if( PPU_REG_6 & 0x2000 ) {
			if(Mirroring == 2) {
				if(PPU_REG_6 & 0x800)
					VRAM[PPU_REG_6 - 0x800] = Value;
				else
					VRAM[PPU_REG_6 + 0x800] = Value;
			} else if(Mirroring == 1) {
				if(PPU_REG_6 & 0x800)
					VRAM[PPU_REG_6 - 0x400] = Value;
				else
					VRAM[PPU_REG_6 + 0x400] = Value;
			}
		}
	        
	        if(PPU_REG_6 == 0x3F10) {
			VRAM[0x3F00] =
			 VRAM[0x3F04] =
			 VRAM[0x3F08] =
			 VRAM[0x3F0C] =
			 VRAM[0x3F10] =
			 VRAM[0x3F14] =
			 VRAM[0x3F18] =
			 VRAM[0x3F1C] =
                        	Value;
		}

                if( ReadBit( RAM[0x2000] , 2 ) == 1 )	//####
                        PPU_REG_6 += 32;
                else
                        PPU_REG_6 += 1;

                break;
            }
                
            // Il faut que j'‚crive les autres ports
       
            default:
                RAM[ addr ] = Value;
                break;

            }

        case 0x4000:
            // la c'est pareil qu'en 0x2000 sauf qu'on a un peu plus
            // de ports, de 0x4000 - 0x4017.

        switch( addr )
        {
                case 0x4003: /* Square Wave 1 */
                {
                        int freq;
                        RAM[0x4003] = Value;
                        if(UseSound) {
	                        freq = RAM[0x4002] + (Value & 7) * 256;
        	                freq = 111860.78 / (freq + 1);

			
                	        Sound(0, freq, 255);
                	}
                        break;
                }
                case 0x4007: /* Sqaure Wave 2 */
                {
                        int freq;
                        RAM[0x4007] = Value;
                        if(UseSound) {
	                        freq = RAM[0x4006] + (Value & 7) * 256;
        	                freq = 111860.78 / (freq + 1);
                	        Sound(1, freq, 255);
                	}
                        break;
                }
                case 0x400B: /* Triangle Wave */
                {
                        int freq;
                        RAM[0x400B] = Value;
                        if(UseSound) {
	                        freq = RAM[0x400A] + (Value & 7) * 256;
        	                freq = 111860.78 / (freq + 1);
                	        Sound(2, freq, 255);
                        }
                        break;
                }
                /*case 0x400F: /* PCM Sound Register - wish i knew how this really worked*/
                /*{
                        int freq;
                        RAM[0x400F] = Value;
                        freq = RAM[0x400E] + (Value & 7) * 256;
                        freq = 111860.78 / freq;
                        Sound(3, freq, 255);
                        break;
                }*/

                case 0x4014:
                {
                        // SPRITE DMA

                        // Transfer 256 bytes de m‚moires
                        // de l'adresse $100*N
                        // N = est la valeur ‚crit dans le registre                                
                        // dans la RAM des sprites

/*                        for( i = 0 ; i < 256 ; i++ )
                                SRAM[ i ] = Rd6502( (0x100*Value)+i );*/
                        for( i = 0; i < 256; i++ )
                        	SRAM[ i ] = RAM[ (0x100*Value)+i ];
                        break;
                }
                case 0x4015:
                {
                        // Sound Control Register

                        RAM[ addr ] = Value;
                        break;
                }
                case 0x4016:
                {
                        if ((RAM[0x4016] == 1) && (Value == 0))
                            Joypad_Read_1 = 0;

                        RAM[0x4016] = Value;    
                        
                        break;
                }
                default:
                {
                        // C'est en fait tous ce qui relatif aux sons

                        RAM[addr] = Value;
                        break;
                }
        }
        case 0x6000:
        {
            // MEMOIRE PILE
            // A ECRIRE DANS LES FUTURES VERSIONS

            // Quoique j'ai une id‚e sur l'affaire:)

            // David m'a donn‚ le feu vert si je veux l'implant‚
            // J'avais bien compris:)

	    RAM[ addr ] = Value;
            break;
        }
        default:
        {
        	Mapper->Write( addr, Value );
        	break;
        	switch( MMC )
        	{
        		case 0:
				/* Not allowed to write to ROM.. heh, thats why
				 * we call it READ ONLY MEMORY
				 */
        			break;
        		case 1:
        			Mapper1_Write(addr, Value);
        			break;
        		case 2:
	       			MMC_low_base = Value * 0x4000;
        			break;
        		case 3:
        			MMC_chr = (Value & 0x03) * 0x2000;
        			memcpy( &VRAM[ 0 ], &VROM[ MMC_chr ], 0x2000 );
        			break;
        		case 4:
				Mapper4_Write(addr, Value);
				break;
        		case 7:
        			if((Value & 0x10) == 0)
	  				MMC_Table = 0x2000;
        			else
        				MMC_Table = 0x2400;

        			Value &= 0x0F;
        			
        			MMC_low_base = Value * 0x8000;
        			break;
        		case 9:
        			
        			if(addr >= 0xA000 && addr <= 0xAFFF) {
        				memcpy( &RAM[ 0x8000 ] , &ROM[ Value*0x2000 ] , 0x2000 );
        				break;
        			}
        			switch( addr ) 
        			{
        				case 0xB000:
        					memcpy( &VRAM[ 0x0 ] , &VROM[ Value * 0x1000 ] , 0x1000 );
        					break;
        				case 0xC000:
        				        memcpy( &VRAM[ 0x0 ] , &VROM[ Value * 0x1000 ] , 0x1000 );
                                                break;
					case 0xD000:
						memcpy( &VRAM[ 0x1000 ] , &VROM[ Value * 0x1000 ] , 0x1000 );
						break;
					case 0xE000:
						memcpy( &VRAM[ 0x1000 ] , &VROM[ Value * 0x1000 ] , 0x1000 );
						break;
					case 0xF000:
						if( Value == 0 )
							Mirroring = 2;
						else
							Mirroring = 1;
						break;
				}
				break;
			case 10:
				switch(addr & 0xF000) {
					case 0xA000:
						MMC_low_base = Value * 0x4000;
						break;
					case 0xB000:
					case 0xD000:
						memcpy(VRAM, &VROM[0x2000 * Value], 0x2000);
						break;
					case 0xC000:
					case 0xE000:
						memcpy(&VRAM[0x1000], &VROM[0x2000 * Value], 0x2000);
						break;
					case 0xF000:
						if(Value == 0)
							Mirroring = 1;
						else
							Mirroring = 2;
						break;
				}
				break;
						
						
        		case 11:
        			MMC_chr = ( Value & 0xF0 ) * 8192;
        			MMC_low_base = ( Value & 0x0F ) * 32768;
        			
        			memcpy( VRAM , &VROM[ MMC_chr ] , 0x2000 );
        			break;
        	}
        }
	}
}

byte Loop6502(register M6502 *R)
{
	int ret;
	static int first_time_in_vblank = 0;

	for(ret = 0; ret <= 3; ret++)
		Sound(ret, 0, 0);

	ret = INT_NONE;

        // If we're using MMC4, check if IRQs are enabled
        if (MMC == 4)
        {
                /* Decrement & check the IRQ scanline counter */
                if (MMC4_DOIRQ && (--MMC4_IRQ == 0))
                        ret = INT_IRQ;
        }

        if (current_scanline == SRAM [0])
        {
                PPU_Status |= 0x40;
                /* if the current scanline is the same as the y position of spr */
                if ((PPU_Control0 & 0x40) && (PPU_Control1 & 0x10))
                        ret = INT_NMI;
        }

	if ((current_scanline <= BOTTOM_VISIBLE_SCANLINE) && (current_scanline >= TOP_VISIBLE_SCANLINE))
		if (CurrentFrame == FrameRate) RenderLine (current_scanline);

        // If NMI on sprite hit is on and sprites are showing and the screen is
        if (current_scanline >= BOTTOM_VISIBLE_SCANLINE)
        {
                // VBlank in progress, set flag
                PPU_Status |= 0x80;

                // ??
                RAM[ 0x4016 ] &= 0xFD;
                if (current_scanline == BOTTOM_VISIBLE_SCANLINE + 8)
                {
                        // Check if NMIs are enabled on vblank
                        if (PPU_Control0 & 0x80) ret = INT_NMI;
                }

                // This code only needs to be executed once per frame
                if (first_time_in_vblank == 0)
                {
                        first_time_in_vblank = 1;

                        // Reset writes to the scroll register
                        BGScroll_toggle = 0;

                        // Update the controls
                        CheckKb();

                        // Render the screen
                        if (CurrentFrame++ >= FrameRate)
                        {
                                // If the screen is on, draw it
                                if (PPU_Control1 & 0x08)
                                {
					Refresh_Screen();
                                }
                                CurrentFrame = 0;
                        }
                }
        }
        else PPU_Status &= ~0x80;
        // Increment the scanline pointer & check to see if it's rolled
        if ( ++ current_scanline >= scanlines_per_frame)
        {
                // vblank is over, start at top of screen again
                current_scanline = TOP_VISIBLE_SCANLINE;
                first_time_in_vblank = 0;

                // Clear the vblank flag
                PPU_Status &= ~0xC0;
        }

        // If we're to quit, return INT_QUIT so the 6502 knows to bail
	return ret;
}

void Reset_Nes(void)
{
	M->IPeriod = cycles_per_scanline;
	current_scanline = TOP_VISIBLE_SCANLINE;
        PPU_Control0 = PPU_Control1 = PPU_Status = PPU_REG_5B = PPU_REG_5A = 0;
        PPU_Addr = PPU_addr_toggle = BGScroll_toggle = 0;
	   
	FirstRead = 1;
	Reset_Mapper(MMC);
	
	Joypad_1 = 0;
	Joypad_Read_1 = 0;
	
	Reset6502(M);
}

	                     
void save_state(char *filename)
{
	FILE *fp;

	if((fp = fopen(filename, "wb")) == NULL)
		return;

	fwrite(RAM, 0x10000, 1, fp);
	fwrite(VRAM, 0x4000, 1, fp);
	fwrite(M, sizeof(M6502), 1, fp); /* saves stack pointer & program counter */
	fclose(fp);
}

void load_state(char *filename)
{
	FILE *fp;

	if((fp = fopen(filename, "rb")) == NULL)
		return;
	
	fread(RAM, 0x10000, 1, fp);
	fread(VRAM, 0x4000, 1, fp);
	fread(M, sizeof(M6502), 1, fp);
	fclose(fp);
}

/* Write_PPU!! */
void Write_PPU(byte Value)
{
	if(PPU_REG_6 > 0x4000) /* ignore */
		return;
	
	PPU_REG_6 &= 0x3FFF;
	
	VRAM[ PPU_REG_6 ] = Value;
	dirty_VRAM[ PPU_REG_6] = 1;
	
	if(PPU_REG_6 & 0x2000) {
                if (Mirroring & 0x02) /* Vertical */
                {
                        if (PPU_Addr & 0x800)
                        {
                                VRAM [PPU_Addr - 0x800] = Value;
                                dirty_VRAM [PPU_Addr - 0x800] = 1;
                        }
                        else
                        {
                                VRAM [PPU_Addr + 0x800] = Value;
                                dirty_VRAM [PPU_Addr + 0x800] = 1;
                        }
                }
                if (Mirroring & 0x01) /* Horizontal */
                {
                        if (PPU_Addr & 0x400)
                        {
                                VRAM [PPU_Addr - 0x400] = Value;
                                dirty_VRAM [PPU_Addr - 0x400] = 1;
                        }
                        else
                        {
                                VRAM [PPU_Addr + 0x400] = Value;
                                dirty_VRAM [PPU_Addr + 0x400] = 1;
                        }
                }
        }
        if (PPU_Addr == 0x3f10)
        {
                VRAM [0x3f00] = Value;
                VRAM [0x3f10] = Value;
        }

        if (PPU_Addr == 0x3f00)
        {
                VRAM [0x3f00] = Value;
                VRAM [0x3f10] = Value;
        }

        if (PPU_Control0 & 0x04)
                PPU_Addr += 32;
        else
                PPU_Addr += 1;
}
		
		
/* RESETMAPPER */
int Reset_Mapper(int mapperNum)
{
	int err = 0;
	
	MMC1_Reg_0 = MMC1_Reg_1 = MMC1_Reg_2 = MMC1_Reg_3 = 0;
        MMC1_Reg_0_WriteNo = 0;
        MMC1_Reg_1_WriteNo = 0;
        MMC1_Reg_2_WriteNo = 0;
        MMC1_Reg_3_WriteNo = 0;

        MMC_Bank_Size = 1;
        MMC_Base_Bootup = 1;
        MMC_Size_Select = 0;

        // If there are 1 or more VROM pages, copy the first 1 to VRAM
        if (CHR_Ram > 0)
                memcpy( VRAM, VROM, 0x2000);

        switch (mapperNum)
        {
                case 0:
                        err = 1; /* No mapper found */
                        MMC_low_base = 0;
                        MMC_high_base = 0;
                        break;
                case 1:
                        MMC_low_base = 0;
                        if(DW4 == 0 && DW3 == 0)
	                        MMC_high_base = (PRG_Rom - 1) * 0x4000;
	                else
	                	MMC_high_base = 15 * 0x4000;
	                	
                        MMC1_High = MMC_high_base;
                        break;
                case 2:
                        MMC_low_base = 0;
                        MMC_high_base = (PRG_Rom-1) * 0x4000;
                        break;
                case 3:
                        break;
                case 4:
                        MMC_low_base = (PRG_Rom-1) * 0x4000;
                        MMC4_hmid_base = (PRG_Rom-1) * 0x4000 + 0x2000;
                        MMC4_mid_base = MMC_low_base;
                        MMC_high_base = MMC4_hmid_base;
                        MMC4_DOIRQ = 0;
                        MMC4_IRQ = 0;
                        break;
                case 7:
                        MMC_low_base = 0;
                        MMC_high_base = (PRG_Rom-1) * 0x4000;
                        break;
                case 9:
                        MMC_low_base = 0;
                        MMC_high_base = ((PRG_Rom*2) - 2) * 0x2000;
                        break;
                case 10:
                        MMC_low_base = 0;
                        MMC_high_base = (PRG_Rom-1) * 0x4000;
                        break;
                case 11:
                        MMC_low_base = 0;
                        MMC_high_base = (PRG_Rom-1) * 0x4000;
                        break;
                case 15:
                        MMC_low_base = 0;
                        MMC_high_base = (PRG_Rom-1) * 0x4000;
                        break;

                default:
                        err = 2; /* Mapper not supported */
                        break;
        }
        return err;
}

void Mapper4_Write (int addr, byte Value)
{
        static int cmd = 0;
        static int chr = 0;
        static int prg = 0;
        static int irq;
        static int select_high;
        static int select2;
        static int first_time = 1;
	static int lowhigh, highest;

	
        switch( addr & 0xE001)
        {
                case 0x8000:
                        cmd = Value & 0x07;
                        if( Value & 0x80 )
                                chr = 0x1000;
                        else
                                chr = 0x0000;
	
			select_high = Value & 0x40;
                        
                        break;
		case 0x8001:
		        switch(cmd)
			{
				case 0:
                        		Value &= 0xFE;
                        		memcpy(&VRAM[chr ^ 0],&VROM[Value*0x400], 0x800);
                        		break;
                		case 1:
                        		memcpy(&VRAM[chr ^ 0x0800], &VROM[Value*0x400],0x800);
                        		break;
				case 2:
					memcpy(&VRAM[chr ^ 0x1000], &VROM[Value*0x400],0x400);
					break;

				case 3:
					memcpy(&VRAM[chr ^ 0x1400], &VROM[Value*0x400],0x400);
					break;

				case 4:
					memcpy(&VRAM[chr ^ 0x1800], &VROM[Value*0x400],0x400);
					break;

				case 5:
					memcpy(&VRAM[chr ^ 0x1C00], &VROM[Value*0x400],0x400);
					break;

				case 6:
					if(select_high)
						MMC4_hmid_base = (Value & 0x7F) * 0x2000;
					else
						MMC_low_base = (Value & 0x7F) * 0x2000;
					break;
				case 7:
					MMC4_mid_base = (Value & 0x7F) * 0x2000;
					break;
			}
			cmd = 8;
                        break;
                case 0xA000:
                        Mirroring = (Value & 0x01) ? 1 : 2;
                        break;

                case 0xC000: // IRQ scanline counter
                        MMC4_IRQ = Value;
                        break;

                case 0xC001: // IRQ latch value
                        irq = Value;
                        break;

                case 0xE000: // Copy latch & disable IRQs
                        MMC4_IRQ = irq;
                        MMC4_DOIRQ = 0;

                        if (Value & 0x20)
                        {
                                int temp;
	                        temp = MMC_low_base;
        			MMC_low_base = MMC4_mid_base;
				MMC4_mid_base = temp;
                        }

                        // G.I. Joe writes 0x80 during title screen...
                        // Gauntlet writes 0x08 at startup...
                        // Batman 3 writes 0x31 at startup...0xa000 bank select
                        // Batman writes 0xc0 then 0x12 - 0x8000 bank select??
                        // SMB 3 writes 0xef when you press start

                        break;

                case 0xE001: // Enable IRQs
                        MMC4_DOIRQ = 1;
                        break;

                default:
			break;
	}
}



xNES/msg.h100644    765    144         217  6440303261  11646 0ustar  chuckjrusers#ifndef __MSG_H
#define __MSG_H

void gl_myinit(int, int, int);
void DisplayMsg(char *);
void DrawMsg();

extern int MessageFrameCount;

#endifxNES/xnes.h100644    765    144        3130  6443121557  12063 0ustar  chuckjrusers//
// Xnes.h
//
#include "M6502.h"
// --------------------------------------------------------
// Les fonctions suivantes ont ‚t‚ fournis par Mr.David :))

#define WriteBit(var, bit, pos) {ClearBit(var, pos); var |= (bit << pos);}
#define SetBit(var, pos) var |= (1 << pos)
#define ClearBit(var, pos) var &= ~(1 << pos)
#define TestBit(var, pos) (var & (1 << pos) ? 1 : 0)
#define ReadBit(x,y) ((x >> y) & 0x01)

// --------------------------------------------------------
typedef short int WORD;
typedef unsigned char BYTE;

unsigned char *RAM,*ROM,*VRAM,*SRAM;  // Pointeur vers la     RAM Principale
unsigned char *VROM;                  //                      ROM

WORD addrmask;                             //                      RAM Video
unsigned char *gameImage;                             //                      RAM Sprite                                        

short   PPU_REG_6;           // Encore une id‚e … David
short   PPU_REG_5A;
short   PPU_REG_5B;

int     PPU_addr_toggle;     // Snifff...
int     BGScroll_toggle;     // Ca c'est une id‚e … moi non mais !

int     Mirroring;
int     SVRam;
int     Battery;
int     Trainer;

int     Linear;
int     Vga;

int 	MMC;
int	MMC_Table;
int	Screen_Change;

extern  M6502  *M;
extern  int iperiod;
extern  int Panning;
extern  char *RomName;
extern  byte *dirty_VRAM;
extern  int UseSound;

unsigned char    Joypad_1;
extern int Joypad_Read_1;


char    CartName[ 80 ];
char    Battery_Name[ 80 ];
void	load_state(char *), save_state(char *);

int     CheckKb( void );
void	Write_PPU(byte);
void	Reset_Nes();

extern int FrameRate;
extern char *CmdName;
xNES/nes.h100644    765    144        2317  6460407443  11701 0ustar  chuckjrusers//
//      NES.h
//

// Ce fichier contient les d‚clarations des fonctions
// en Nes.c

#define         Black   69
#define         Red     70
#define         Green   71
#define         Blue    72

typedef char    BITMAP;

typedef struct RGB_color_typ
{
	int red;
	int green;
	int blue;
} RGB_color, *RGB_color_ptr;

typedef RGB_color PALLETE[256];
	
extern BITMAP  *Bitmap;
extern BITMAP  *Bitmap2;
extern BITMAP  *Bitmap3;
extern BITMAP  *Bitmap4;
extern BITMAP  *Bitmap5;
extern BITMAP  *Bitmap6;

BITMAP  *Interface;

PALLETE Pallete;

extern int     First_Time;        
extern int     First_Time2;
extern int     First_Time3;        
extern int     First_Time4;
extern int     stretch;
/*char Screen_Info[ 640 ] [ 600 ];*/
extern char *Screen_Info;

int	Tile_Index[64][60];
int	Scroll_Sens;

int     InitMachine();
int     TrashMachine();
int     PresentXNes();
int     ReturnAddrTile( int );
int     ShowTile_Screen( int , int , int , int , int , int , int , int , int , int , BITMAP *);
int     Refresh_Sprite();
int     ClearScreen();
BITMAP *create_bitmap(int, int);
void    load_pallete_from_pcx(char *);
void Update_Joystick();
void CalibrateJoystick();
void	save_pcx(BITMAP *);

extern int Keycodes[];
extern int NoJoy;
xNES/M6502.h100644    765    144       14043  6422445476  11652 0ustar  chuckjrusers/** M6502: portable 6502 emulator ****************************/
/**                                                         **/
/**                         M6502.h                         **/
/**                                                         **/
/** This file contains declarations relevant to emulation   **/
/** of 6502 CPU.                                            **/
/**                                                         **/
/** Copyright (C) Marat Fayzullin 1996                      **/
/**               Alex Krasivsky  1996                      **/
/**     You are not allowed to distribute this software     **/
/**     commercially. Please, notify me, if you make any    **/   
/**     changes to this file.                               **/
/*************************************************************/
#ifndef M6502_H
#define M6502_H

#define LSB_FIRST

                               /* Loop6502() returns:        */
#define INT_NONE  0            /* No interrupt required      */
#define INT_IRQ	  1            /* Standard IRQ interrupt     */
#define INT_NMI	  2            /* Non-maskable interrupt     */
#define INT_QUIT  3            /* Exit the emulation         */

                               /* 6502 status flags:         */
#define	C_FLAG	  0x01         /* 1: Carry occured           */
#define	Z_FLAG	  0x02         /* 1: Result is zero          */
#define	I_FLAG	  0x04         /* 1: Interrupts disabled     */
#define	D_FLAG	  0x08         /* 1: Decimal mode            */
#define	B_FLAG	  0x10         /* Break [0 on stk after int] */
#define	R_FLAG	  0x20         /* Always 1                   */
#define	V_FLAG	  0x40         /* 1: Overflow occured        */
#define	N_FLAG	  0x80         /* 1: Result is negative      */

/** Simple Datatypes *****************************************/
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2               **/
/*************************************************************/
typedef unsigned char byte;
typedef unsigned short word;
typedef signed char offset;

/** Structured Datatypes *************************************/
/** NOTICE: #define LSB_FIRST for machines where least      **/
/**         signifcant byte goes first.                     **/
/*************************************************************/
typedef union
{
#ifdef LSB_FIRST
  struct { byte l,h; } B;
#else
  struct { byte h,l; } B;
#endif
  word W;
} pair;

typedef struct
{
  byte A,P,X,Y,S;     /* CPU registers and program counter   */
  pair PC;

  int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */
                      /* between calls to Loop6502()         */
  byte IRequest;      /* Set to the INT_IRQ when pending IRQ */
  byte AfterCLI;      /* Private, don't touch                */
  int IBackup;        /* Private, don't touch                */
  void *User;         /* Arbitrary user data (ID,RAM*,etc.)  */
  byte TrapBadOps;    /* Set to 1 to warn of illegal opcodes */
  word Trap;          /* Set Trap to address to trace from   */
  byte Trace;         /* Set Trace=1 to start tracing        */
} M6502;

/** Reset6502() **********************************************/
/** This function can be used to reset the registers before **/
/** starting execution with Run6502(). It sets registers to **/
/** their initial values.                                   **/
/*************************************************************/
void Reset6502(register M6502 *R);

/** Exec6502() ***********************************************/
/** This function will execute a single 6502 opcode. It     **/
/** will then return next PC, and current register values   **/
/** in R.                                                   **/
/*************************************************************/
word Exec6502(register M6502 *R);

/** Int6502() ************************************************/
/** This function will generate interrupt of a given type.  **/
/** INT_NMI will cause a non-maskable interrupt. INT_IRQ    **/
/** will cause a normal interrupt, unless I_FLAG set in R.  **/
/*************************************************************/
void Int6502(register M6502 *R,register byte Type);

/** Run6502() ************************************************/
/** This function will run 6502 code until Loop6502() call  **/
/** returns INT_QUIT. It will return the PC at which        **/
/** emulation stopped, and current register values in R.    **/
/*************************************************************/
word Run6502(register M6502 *R);

/** Rd6502()/Wr6502/Op6502() *********************************/
/** These functions are called when access to RAM occurs.   **/
/** They allow to control memory access. Op6502 is the same **/
/** as Rd6502, but used to read *opcodes* only, when many   **/
/** checks can be skipped to make it fast. It is only       **/
/** required if there is a #define FAST_RDOP.               **/
/************************************ TO BE WRITTEN BY USER **/
inline void Wr6502(register word Addr,register byte Value);
inline byte Rd6502(register word Addr);
byte Op6502(register word Addr);

/** Debug6502() **********************************************/
/** This function should exist if DEBUG is #defined. When   **/
/** Trace!=0, it is called after each command executed by   **/
/** the CPU, and given the 6502 registers. Emulation exits  **/
/** if Debug6502() returns 0.                               **/
/*************************************************************/
byte Debug6502(register M6502 *R);

/** Loop6502() ***********************************************/
/** 6502 emulation calls this function periodically to      **/
/** check if the system hardware requires any interrupts.   **/
/** This function must return one of following values:      **/
/** INT_NONE, INT_IRQ, INT_NMI, or INT_QUIT to exit the     **/
/** emulation loop.                                         **/
/************************************ TO BE WRITTEN BY USER **/
byte Loop6502(register M6502 *R);

#endif /* M6502_H */
xNES/LICENSE100600    765    144       43313  6460701266  11761 0ustar  chuckjrusers                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.
U0C
                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)
U0C
These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
U0C
  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
U0C
  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS
U0C
            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 19yy  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) 19yy name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.

xNES/palette.h100644    765    144       23531  6437405575  12603 0ustar  chuckjrusers/* Automatically generated by a program chuck wrote.*/

#ifndef __PAL_H
#define __PAL_H

typedef struct __pal {
	int red;
	int blue;
	int green;
} pal;

pal palette[256] = {
	{ 0x1D, 0x1D, 0x1D }, /* Value 0 */
	{ 0x09, 0x06, 0x23 }, /* Value 1 */
	{ 0x00, 0x00, 0x2A }, /* Value 2 */
	{ 0x11, 0x00, 0x27 }, /* Value 3 */
	{ 0x23, 0x00, 0x1D }, /* Value 4 */
	{ 0x2A, 0x00, 0x04 }, /* Value 5 */
	{ 0x29, 0x00, 0x00 }, /* Value 6 */
	{ 0x1F, 0x02, 0x00 }, /* Value 7 */
	{ 0x10, 0x0B, 0x00 }, /* Value 8 */
	{ 0x00, 0x11, 0x00 }, /* Value 9 */
	{ 0x00, 0x14, 0x00 }, /* Value 10 */
	{ 0x00, 0x0F, 0x05 }, /* Value 11 */
	{ 0x06, 0x0F, 0x17 }, /* Value 12 */
	{ 0x00, 0x00, 0x00 }, /* Value 13 */
	{ 0x00, 0x00, 0x00 }, /* Value 14 */
	{ 0x00, 0x00, 0x00 }, /* Value 15 */
	{ 0x2F, 0x2F, 0x2F }, /* Value 16 */
	{ 0x00, 0x1C, 0x3B }, /* Value 17 */
	{ 0x08, 0x0E, 0x3B }, /* Value 18 */
	{ 0x20, 0x00, 0x3C }, /* Value 19 */
	{ 0x2F, 0x00, 0x2F }, /* Value 20 */
	{ 0x39, 0x00, 0x16 }, /* Value 21 */
	{ 0x36, 0x0A, 0x00 }, /* Value 22 */
	{ 0x32, 0x13, 0x03 }, /* Value 23 */
	{ 0x22, 0x1C, 0x00 }, /* Value 24 */
	{ 0x00, 0x25, 0x00 }, /* Value 25 */
	{ 0x00, 0x2A, 0x00 }, /* Value 26 */
	{ 0x00, 0x24, 0x0E }, /* Value 27 */
	{ 0x00, 0x20, 0x22 }, /* Value 28 */
	{ 0x00, 0x00, 0x00 }, /* Value 29 */
	{ 0x00, 0x00, 0x00 }, /* Value 30 */
	{ 0x00, 0x00, 0x00 }, /* Value 31 */
	{ 0x3F, 0x3F, 0x3F }, /* Value 32 */
	{ 0x0F, 0x2F, 0x3F }, /* Value 33 */
	{ 0x17, 0x25, 0x3F }, /* Value 34 */
	{ 0x10, 0x22, 0x3F }, /* Value 35 */
	{ 0x3D, 0x1E, 0x3F }, /* Value 36 */
	{ 0x3F, 0x1D, 0x2D }, /* Value 37 */
	{ 0x3F, 0x1D, 0x18 }, /* Value 38 */
	{ 0x3F, 0x26, 0x0E }, /* Value 39 */
	{ 0x3C, 0x2F, 0x0F }, /* Value 40 */
	{ 0x20, 0x34, 0x04 }, /* Value 41 */
	{ 0x13, 0x37, 0x12 }, /* Value 42 */
	{ 0x16, 0x3E, 0x26 }, /* Value 43 */
	{ 0x00, 0x3A, 0x36 }, /* Value 44 */
	{ 0x00, 0x00, 0x00 }, /* Value 45 */
	{ 0x00, 0x00, 0x00 }, /* Value 46 */
	{ 0x00, 0x00, 0x00 }, /* Value 47 */
	{ 0x3F, 0x3F, 0x3F }, /* Value 48 */
	{ 0x2A, 0x39, 0x3F }, /* Value 49 */
	{ 0x31, 0x35, 0x3F }, /* Value 50 */
	{ 0x35, 0x32, 0x3F }, /* Value 51 */
	{ 0x3F, 0x31, 0x3F }, /* Value 52 */
	{ 0x3F, 0x31, 0x36 }, /* Value 53 */
	{ 0x3F, 0x2F, 0x2C }, /* Value 54 */
	{ 0x3F, 0x36, 0x2A }, /* Value 55 */
	{ 0x3F, 0x39, 0x28 }, /* Value 56 */
	{ 0x38, 0x3F, 0x28 }, /* Value 57 */
	{ 0x2A, 0x3C, 0x2F }, /* Value 58 */
	{ 0x2C, 0x3F, 0x33 }, /* Value 59 */
	{ 0x27, 0x3F, 0x3C }, /* Value 60 */
	{ 0x00, 0x00, 0x00 }, /* Value 61 */
	{ 0x00, 0x00, 0x00 }, /* Value 62 */
	{ 0x00, 0x00, 0x00 }, /* Value 63 */
	{ 0x00, 0x00, 0x00 }, /* Value 64 */
	{ 0x00, 0x00, 0x00 }, /* Value 65 */
	{ 0x00, 0x00, 0x00 }, /* Value 66 */
	{ 0x00, 0x00, 0x00 }, /* Value 67 */
	{ 0x00, 0x00, 0x00 }, /* Value 68 */
	{ 0x00, 0x00, 0x00 }, /* Value 69 */
	{ 0x3F, 0x00, 0x00 }, /* Value 70 */
	{ 0x00, 0x3F, 0x00 }, /* Value 71 */
	{ 0x00, 0x00, 0x3F }, /* Value 72 */
	{ 0x00, 0x00, 0x00 }, /* Value 73 */
	{ 0x00, 0x00, 0x00 }, /* Value 74 */
	{ 0x00, 0x00, 0x00 }, /* Value 75 */
	{ 0x00, 0x00, 0x00 }, /* Value 76 */
	{ 0x00, 0x00, 0x00 }, /* Value 77 */
	{ 0x00, 0x00, 0x00 }, /* Value 78 */
	{ 0x00, 0x00, 0x00 }, /* Value 79 */
	{ 0x00, 0x00, 0x00 }, /* Value 80 */
	{ 0x00, 0x00, 0x00 }, /* Value 81 */
	{ 0x00, 0x00, 0x00 }, /* Value 82 */
	{ 0x00, 0x00, 0x00 }, /* Value 83 */
	{ 0x00, 0x00, 0x00 }, /* Value 84 */
	{ 0x00, 0x00, 0x00 }, /* Value 85 */
	{ 0x00, 0x00, 0x00 }, /* Value 86 */
	{ 0x00, 0x00, 0x00 }, /* Value 87 */
	{ 0x00, 0x00, 0x00 }, /* Value 88 */
	{ 0x00, 0x00, 0x00 }, /* Value 89 */
	{ 0x00, 0x00, 0x00 }, /* Value 90 */
	{ 0x00, 0x00, 0x00 }, /* Value 91 */
	{ 0x00, 0x00, 0x00 }, /* Value 92 */
	{ 0x00, 0x00, 0x00 }, /* Value 93 */
	{ 0x00, 0x00, 0x00 }, /* Value 94 */
	{ 0x00, 0x00, 0x00 }, /* Value 95 */
	{ 0x00, 0x00, 0x00 }, /* Value 96 */
	{ 0x00, 0x00, 0x00 }, /* Value 97 */
	{ 0x00, 0x00, 0x00 }, /* Value 98 */
	{ 0x00, 0x00, 0x00 }, /* Value 99 */
	{ 0x00, 0x00, 0x00 }, /* Value 100 */
	{ 0x00, 0x00, 0x00 }, /* Value 101 */
	{ 0x00, 0x00, 0x00 }, /* Value 102 */
	{ 0x00, 0x00, 0x00 }, /* Value 103 */
	{ 0x00, 0x00, 0x00 }, /* Value 104 */
	{ 0x00, 0x00, 0x00 }, /* Value 105 */
	{ 0x00, 0x00, 0x00 }, /* Value 106 */
	{ 0x00, 0x00, 0x00 }, /* Value 107 */
	{ 0x00, 0x00, 0x00 }, /* Value 108 */
	{ 0x00, 0x00, 0x00 }, /* Value 109 */
	{ 0x00, 0x00, 0x00 }, /* Value 110 */
	{ 0x00, 0x00, 0x00 }, /* Value 111 */
	{ 0x00, 0x00, 0x00 }, /* Value 112 */
	{ 0x00, 0x00, 0x00 }, /* Value 113 */
	{ 0x00, 0x00, 0x00 }, /* Value 114 */
	{ 0x00, 0x00, 0x00 }, /* Value 115 */
	{ 0x00, 0x00, 0x00 }, /* Value 116 */
	{ 0x00, 0x00, 0x00 }, /* Value 117 */
	{ 0x00, 0x00, 0x00 }, /* Value 118 */
	{ 0x00, 0x00, 0x00 }, /* Value 119 */
	{ 0x00, 0x00, 0x00 }, /* Value 120 */
	{ 0x00, 0x00, 0x00 }, /* Value 121 */
	{ 0x00, 0x00, 0x00 }, /* Value 122 */
	{ 0x00, 0x00, 0x00 }, /* Value 123 */
	{ 0x00, 0x00, 0x00 }, /* Value 124 */
	{ 0x00, 0x00, 0x00 }, /* Value 125 */
	{ 0x00, 0x00, 0x00 }, /* Value 126 */
	{ 0x00, 0x00, 0x00 }, /* Value 127 */
	{ 0x00, 0x00, 0x00 }, /* Value 128 */
	{ 0x00, 0x00, 0x00 }, /* Value 129 */
	{ 0x00, 0x00, 0x00 }, /* Value 130 */
	{ 0x00, 0x00, 0x00 }, /* Value 131 */
	{ 0x00, 0x00, 0x00 }, /* Value 132 */
	{ 0x00, 0x00, 0x00 }, /* Value 133 */
	{ 0x00, 0x00, 0x00 }, /* Value 134 */
	{ 0x00, 0x00, 0x00 }, /* Value 135 */
	{ 0x00, 0x00, 0x00 }, /* Value 136 */
	{ 0x00, 0x00, 0x00 }, /* Value 137 */
	{ 0x00, 0x00, 0x00 }, /* Value 138 */
	{ 0x00, 0x00, 0x00 }, /* Value 139 */
	{ 0x00, 0x00, 0x00 }, /* Value 140 */
	{ 0x00, 0x00, 0x00 }, /* Value 141 */
	{ 0x00, 0x00, 0x00 }, /* Value 142 */
	{ 0x00, 0x00, 0x00 }, /* Value 143 */
	{ 0x00, 0x00, 0x00 }, /* Value 144 */
	{ 0x00, 0x00, 0x00 }, /* Value 145 */
	{ 0x00, 0x00, 0x00 }, /* Value 146 */
	{ 0x00, 0x00, 0x00 }, /* Value 147 */
	{ 0x00, 0x00, 0x00 }, /* Value 148 */
	{ 0x00, 0x00, 0x00 }, /* Value 149 */
	{ 0x00, 0x00, 0x00 }, /* Value 150 */
	{ 0x00, 0x00, 0x00 }, /* Value 151 */
	{ 0x00, 0x00, 0x00 }, /* Value 152 */
	{ 0x00, 0x00, 0x00 }, /* Value 153 */
	{ 0x00, 0x00, 0x00 }, /* Value 154 */
	{ 0x00, 0x00, 0x00 }, /* Value 155 */
	{ 0x00, 0x00, 0x00 }, /* Value 156 */
	{ 0x00, 0x00, 0x00 }, /* Value 157 */
	{ 0x00, 0x00, 0x00 }, /* Value 158 */
	{ 0x00, 0x00, 0x00 }, /* Value 159 */
	{ 0x00, 0x00, 0x00 }, /* Value 160 */
	{ 0x00, 0x00, 0x00 }, /* Value 161 */
	{ 0x00, 0x00, 0x00 }, /* Value 162 */
	{ 0x00, 0x00, 0x00 }, /* Value 163 */
	{ 0x00, 0x00, 0x00 }, /* Value 164 */
	{ 0x00, 0x00, 0x00 }, /* Value 165 */
	{ 0x00, 0x00, 0x00 }, /* Value 166 */
	{ 0x00, 0x00, 0x00 }, /* Value 167 */
	{ 0x00, 0x00, 0x00 }, /* Value 168 */
	{ 0x00, 0x00, 0x00 }, /* Value 169 */
	{ 0x00, 0x00, 0x00 }, /* Value 170 */
	{ 0x00, 0x00, 0x00 }, /* Value 171 */
	{ 0x00, 0x00, 0x00 }, /* Value 172 */
	{ 0x00, 0x00, 0x00 }, /* Value 173 */
	{ 0x00, 0x00, 0x00 }, /* Value 174 */
	{ 0x00, 0x00, 0x00 }, /* Value 175 */
	{ 0x00, 0x00, 0x00 }, /* Value 176 */
	{ 0x00, 0x00, 0x00 }, /* Value 177 */
	{ 0x00, 0x00, 0x00 }, /* Value 178 */
	{ 0x00, 0x00, 0x00 }, /* Value 179 */
	{ 0x00, 0x00, 0x00 }, /* Value 180 */
	{ 0x00, 0x00, 0x00 }, /* Value 181 */
	{ 0x00, 0x00, 0x00 }, /* Value 182 */
	{ 0x00, 0x00, 0x00 }, /* Value 183 */
	{ 0x00, 0x00, 0x00 }, /* Value 184 */
	{ 0x00, 0x00, 0x00 }, /* Value 185 */
	{ 0x00, 0x00, 0x00 }, /* Value 186 */
	{ 0x00, 0x00, 0x00 }, /* Value 187 */
	{ 0x00, 0x00, 0x00 }, /* Value 188 */
	{ 0x00, 0x00, 0x00 }, /* Value 189 */
	{ 0x00, 0x00, 0x00 }, /* Value 190 */
	{ 0x00, 0x00, 0x00 }, /* Value 191 */
	{ 0x00, 0x00, 0x00 }, /* Value 192 */
	{ 0x00, 0x00, 0x00 }, /* Value 193 */
	{ 0x00, 0x00, 0x00 }, /* Value 194 */
	{ 0x00, 0x00, 0x00 }, /* Value 195 */
	{ 0x00, 0x00, 0x00 }, /* Value 196 */
	{ 0x00, 0x00, 0x00 }, /* Value 197 */
	{ 0x00, 0x00, 0x00 }, /* Value 198 */
	{ 0x00, 0x00, 0x00 }, /* Value 199 */
	{ 0x00, 0x00, 0x00 }, /* Value 200 */
	{ 0x00, 0x00, 0x00 }, /* Value 201 */
	{ 0x00, 0x00, 0x00 }, /* Value 202 */
	{ 0x00, 0x00, 0x00 }, /* Value 203 */
	{ 0x00, 0x00, 0x00 }, /* Value 204 */
	{ 0x00, 0x00, 0x00 }, /* Value 205 */
	{ 0x00, 0x00, 0x00 }, /* Value 206 */
	{ 0x00, 0x00, 0x00 }, /* Value 207 */
	{ 0x00, 0x00, 0x00 }, /* Value 208 */
	{ 0x00, 0x00, 0x00 }, /* Value 209 */
	{ 0x00, 0x00, 0x00 }, /* Value 210 */
	{ 0x00, 0x00, 0x00 }, /* Value 211 */
	{ 0x00, 0x00, 0x00 }, /* Value 212 */
	{ 0x00, 0x00, 0x00 }, /* Value 213 */
	{ 0x00, 0x00, 0x00 }, /* Value 214 */
	{ 0x00, 0x00, 0x00 }, /* Value 215 */
	{ 0x00, 0x00, 0x00 }, /* Value 216 */
	{ 0x00, 0x00, 0x00 }, /* Value 217 */
	{ 0x00, 0x00, 0x00 }, /* Value 218 */
	{ 0x00, 0x00, 0x00 }, /* Value 219 */
	{ 0x00, 0x00, 0x00 }, /* Value 220 */
	{ 0x00, 0x00, 0x00 }, /* Value 221 */
	{ 0x00, 0x00, 0x00 }, /* Value 222 */
	{ 0x00, 0x00, 0x00 }, /* Value 223 */
	{ 0x00, 0x00, 0x00 }, /* Value 224 */
	{ 0x00, 0x00, 0x00 }, /* Value 225 */
	{ 0x00, 0x00, 0x00 }, /* Value 226 */
	{ 0x00, 0x00, 0x00 }, /* Value 227 */
	{ 0x00, 0x00, 0x00 }, /* Value 228 */
	{ 0x00, 0x00, 0x00 }, /* Value 229 */
	{ 0x00, 0x00, 0x00 }, /* Value 230 */
	{ 0x00, 0x00, 0x00 }, /* Value 231 */
	{ 0x00, 0x00, 0x00 }, /* Value 232 */
	{ 0x00, 0x00, 0x00 }, /* Value 233 */
	{ 0x00, 0x00, 0x00 }, /* Value 234 */
	{ 0x00, 0x00, 0x00 }, /* Value 235 */
	{ 0x00, 0x00, 0x00 }, /* Value 236 */
	{ 0x00, 0x00, 0x00 }, /* Value 237 */
	{ 0x00, 0x00, 0x00 }, /* Value 238 */
	{ 0x00, 0x00, 0x00 }, /* Value 239 */
	{ 0x00, 0x00, 0x00 }, /* Value 240 */
	{ 0x00, 0x00, 0x00 }, /* Value 241 */
	{ 0x00, 0x00, 0x00 }, /* Value 242 */
	{ 0x00, 0x00, 0x00 }, /* Value 243 */
	{ 0x00, 0x00, 0x00 }, /* Value 244 */
	{ 0x00, 0x00, 0x00 }, /* Value 245 */
	{ 0x00, 0x00, 0x00 }, /* Value 246 */
	{ 0x00, 0x00, 0x00 }, /* Value 247 */
	{ 0x00, 0x00, 0x00 }, /* Value 248 */
	{ 0x00, 0x00, 0x00 }, /* Value 249 */
	{ 0x00, 0x00, 0x00 }, /* Value 250 */
	{ 0x00, 0x00, 0x00 }, /* Value 251 */
	{ 0x00, 0x00, 0x00 }, /* Value 252 */
	{ 0x00, 0x00, 0x00 }, /* Value 253 */
	{ 0x00, 0x00, 0x00 }, /* Value 254 */
	{ 0x00, 0x00, 0x00 }  /* Value 255 */
};

#endif /* __PAL_H */
xNES/nes.c100644    765    144       43011  6460701676  11715 0ustar  chuckjrusers/*
 * xNES - Nintendo Emulator  --  Linux
 *
 * * 1997-8 by the xNES team
 *    Richard Bannister - MacOS port
 *    Chuck Mason - Linux port, core code
 *    Jeff Mitchell - Unix port
 *    Brad Oliver - MacOS port, core code, coordinator
 *
 *    Thanks to Nicolas Hamel and David Michel for the original code.
 *
 * File: NES.C - Video Rendering Code
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdlib.h>
#include <stdio.h>
#include <vga.h>
#include <vgakeyboard.h>
#include <linux/joystick.h>
#include <fcntl.h>
#include <unistd.h>

#include        "nes.h"
#include	"xnes.h"
#include	"msg.h"
                          
#define byte unsigned char
#define X_POS   30

#define SnapScreen(x) save_pcx(x)

int sWIDTH, sHEIGHT;

char *map;
                         
/* Allocate mem for bitmap */

short int sprite_map[256];
int Keycodes[256];
int Toggle = 0;
int Using_Joystick = 0;
int Joystick_fd = 0;
int Joystick_CenterX, Joystick_CenterY;
int NoJoy = 0;
char *Screen_Info;

void keyboard_handler(int, int);
int  Checksum( byte *var , int x , int nx );

int	stretch = 0;

int  Checksum_Palette;
int  Current_Checksum;
int     First_Time;
int     First_Time2;
int     First_Time3;
int     First_Time4;

void Render_Screen_Section (int start_x, int y, int NameTable);

BITMAP  *Bitmap;
BITMAP  *Bitmap2;
BITMAP  *Bitmap3;
BITMAP  *Bitmap4;
BITMAP  *Bitmap5;
BITMAP  *Bitmap6;

BITMAP *create_bitmap( int x, int y )
{
	BITMAP *temp;
	temp = (BITMAP *)malloc(sizeof(BITMAP) * (x * y));
	if(temp != NULL)
		return temp;
	else {
		printf("Unable to allocate %d bytes of data!\n", x * y);
		exit(1);
	}
	return NULL;
}

void destroy_bitmap(BITMAP *bmp)
{
	free(bmp);
}

void _putpixel(BITMAP *screen, 	int x, int y, unsigned char color)
{
	screen[(y * sWIDTH) + x] = color;
}

byte _getpixel(BITMAP *screen, int x, int y)
{
	return(screen[(y*sWIDTH) +x]);
}

inline void blitbmp(BITMAP *from, BITMAP *to, int fromx, int fromy, int tox, int toy, int width, int height)
{
	int voffset = (fromy * sWIDTH) + fromx;
	char *source = &from[voffset];
	char *dest = &to[tox + (toy * sWIDTH)];
	int a;

	for(a = 0; a < height; a++) {
		memcpy(dest, source, width);
		dest += sWIDTH;
		source += sWIDTH;
	}
        if(MessageFrameCount > 0) {
		DrawMsg();
		MessageFrameCount -= 1;
        }
                                                	
}
		
inline void blit(BITMAP *virtual, int xscroll, int yscroll, int xpos)
{
        int y = (sHEIGHT / 2) - (232 / 2),
            l = y + 232;

	int virtual_offset = (yscroll * sWIDTH) + xscroll;
	char *dest = &map[xpos + (y * sWIDTH)];
	char *source = &virtual[virtual_offset];

	if(sHEIGHT == 240 && sWIDTH == 256) {
		blit240(virtual, xscroll, yscroll);
	        if(MessageFrameCount > 0) {
        	        DrawMsg();
                	MessageFrameCount -= 1;
		}
		return;
	}
	
	if(sHEIGHT != 200) {
		for(; y < l; y++) {
			memcpy(dest, source, 256);
			dest += sWIDTH;
			source += sWIDTH;
		}
		vga_copytoplanar256(map, sWIDTH, 0, 80, sWIDTH, sHEIGHT);
		return;
	}

	virtual_offset = (yscroll+16) * sWIDTH + xscroll;
	source = &virtual[virtual_offset];
	dest = &graph_mem[xpos];
	
	for(y = 0; y < 232; y++) {
		memcpy(dest, source, 256);
		dest += sWIDTH;
		source += sWIDTH;
	}

        if(MessageFrameCount > 0) {
        	DrawMsg();
                MessageFrameCount -= 1;
	}

}

void stretchbmp(BITMAP *In, BITMAP *out, int inx, int iny, int width, int height)
{
	char *from = &In[(iny * sWIDTH) + inx]; /* 256x232 */
	char *to   = &out[0]; /* 320x200 */
	int  xgain = 320 - 256;
	int  gain  = 256 / xgain;
	
	int  i,a;
	for(a = 0; a < height; a++) {
		for(i = 0; i < width; i++) {
			*to = *from;
			to++;
			if((i % gain) == 0) {
				*to = *from;
				to++;
			}
			from++;
		}
		from  += (sWIDTH-256);
	}
}
	
void clear_to_color(BITMAP *clear, byte color)
{
	memset(clear, color, 640*600);
}

void clear(BITMAP *clear)
{
	clear_to_color(clear, 0);
}
			
//
// Refresh_Screen
//
int old_Refresh_Screen( void )
{
	int NameTable;
	int NameTables[] = { 0x2000, 0x2400, 0x2800, 0x2C00 };

	NameTable = NameTables[RAM[0x2000] & 0x03];
	
	if(MMC == 7) {
		NameTable += (MMC_Table - 0x2000);
	}
	Render_Screen_Section(0, 0, NameTable);

	NameTable += 0x400;
	
	if(NameTable >= 0x3000)
		NameTable = 0x2000;
	
	if(PPU_REG_5B > 0)
		Render_Screen_Section(256, 0, NameTable);
	
	NameTable += 0x400;
	if(NameTable >= 0x3000)
		NameTable = 0x2000;
		
	if(PPU_REG_5A > 0)
		Render_Screen_Section(0, 240, NameTable);

	NameTable += 0x400;

	if(NameTable >= 0x3000)
		NameTable = 0x2000;
	
	if(PPU_REG_5A > 0 && PPU_REG_5B > 0)
		Render_Screen_Section(256, 240, NameTable);

	if(RAM[0x2001] & 0x10) {
		Refresh_Sprite();
		RAM[0x2002] |= 0x40; /* Sprite hit flag */
	}
			
	if(stretch == 1) {
		stretchbmp( Bitmap , Bitmap2 , PPU_REG_5B , PPU_REG_5A , 256, 232 );
		blitbmp( Bitmap2 , graph_mem , 0 , 16 , 0, 0, 320, 200 );
	} else
		blit( Bitmap , PPU_REG_5B , PPU_REG_5A , X_POS );

/*        ClearScreen();*/
}

void Render_Screen_Section(int start_x, int y, int NameTable)
{
	int i, x, addr, pos, color, tileColor, index;
	int bit_2, bit_3, TileCounter, ColorTable;
	
	x = start_x;
	ColorTable = NameTable + 0x3C0;
	
	TileCounter = 0;
	
	for(i = NameTable; i < NameTable + 0x03C0; i++) {
		dirty_VRAM[i] = 0;

		addr = VRAM[ i ] << 4;
		
		if(TileCounter & 0x40)
			index = 4;
		else
			index = 0;
			
		pos = (TileCounter & 0x380) >> 4;
		pos += (TileCounter & 0x1F) >> 2;
		
		index += (TileCounter & 0x02);
		color = VRAM[ ColorTable + pos ];
		bit_2 = ReadBit(color, index);
		bit_3 = ReadBit(color, index + 1);
		tileColor = bit_3 * 2 + bit_2;
		
		TileCounter += 1;
		
		if(RAM[0x2000] & 0x10)
			addr |= 0x1000;

		if( x+8 >= PPU_REG_5B-8 && x <= PPU_REG_5B+256 && y >= PPU_REG_5A-8 && y <= PPU_REG_5A+232)
			ShowTile_BackGround( addr , x , y , tileColor, Bitmap );

		x += 8;
		
		if( x == start_x + 256 )
		{
			y += 8;
			x = start_x;
		}
	}
}
//
//      InitMachine : Initialize Allegro
//
int     InitMachine()
{
	int i;
        // Initialisation d'SVGAlib
        vga_init();
        if(NoJoy == 0) {
	        Using_Joystick = 1;
		printf("Initializing joystick..."); fflush(stdout);

		Joystick_fd = open("/dev/js0", O_RDONLY);
		if(Joystick_fd < 0) {
			printf("cannot open /dev/js0.\n");
			Using_Joystick = 0;
		} else 
			printf("success.\n");
		/* Calibrate */
		if(Using_Joystick)
			CalibrateJoystick();
	} 
        // Mis en place de l'‚cran

	if(Vga == 2) {
		mode256x240();
		sWIDTH = 256;
		sHEIGHT = 240;
		gl_myinit(G320x200x256, 256, 240);
	} else if(Vga == 1) {
        	vga_setmode(G320x200x256); 
        	sWIDTH = 320;
        	sHEIGHT= 200;
        	gl_myinit(G320x200x256, 320, 200);
        } else {
        	vga_setmode(G320x240x256);
        	sWIDTH = 320;
        	sHEIGHT= 240;
        	gl_myinit(G320x200x256, 320, 240);
        }

        Screen_Info = (char *)malloc(520*520);
        
ok:
        // Cr‚ation du bitmap
        Bitmap = create_bitmap( 640, 600 );
        Bitmap2 = create_bitmap( 640, 600 );
        Bitmap3 = create_bitmap( 640, 600 );
        
	if(sHEIGHT == 200)
		memset(graph_mem, 100, 320*200);
		
	map = (char *)malloc(sWIDTH * sHEIGHT);
	if(!map) {
		TrashMachine();
		exit(1);
	}
	memset(map, 100, sHEIGHT * sWIDTH);
	 
        load_pallete_from_pcx(CmdName);

        ClearScreen();

        keyboard_init();
	keyboard_seteventhandler(keyboard_handler);

	if(UseSound)
		InitSound(8000, 2);
	
	for(i = 0; i < 256; i++)
		sprite_map[i] = i*16;
        return(1);
}

//
//      TrashMachine : libŠre tout
//
int     TrashMachine()
{
        // on DESTROYYY (beuarhhh) le bitmap
	if(UseSound)
		TrashSound();
        destroy_bitmap( Bitmap );
        free(map);
        // on quitte SVGAlib
	vga_setmode(TEXT);

	keyboard_close();

        return(1);
}
//
//	ShowTile_BackGround
//
//	Shows a background tile
//
int	ShowTile_BackGround( int addr, int x, int y,  int color, BITMAP *B)
{
	int i;
	int x3 = 0, y3 = 0;
	int x2;
	int CurrentColor;
	int a, b, c;
	
	int Size;
	
	x3 = x;
	y3 = y;
	
	for(i = addr ; i <= addr + 0x7; i++) 
	{
		for(x2 = 0 ; x2 < 8; x2++) 
		{
			a = ReadBit( VRAM[ i ] , (7-x2) );
			b = ReadBit( VRAM[ i+8 ], (7-x2) );
		
			c = (color << 2) + (b << 1) + a;
			
                        if((c == 0x00) || (c == 0x04) || (c == 0x08) || (c == 0x0C)) {
                                CurrentColor = VRAM[ 0x3F00 ];
                                c = 0;
//				Screen_Info[ x3 ] [ y3 ] = 0;
                        } else {
//                        	Screen_Info[ x3 ] [ y3 ] = 1;
                                CurrentColor = VRAM[ 0x3F00+c ];
			}

			_putpixel( B , x3 , y3 , CurrentColor );
			
			x3++;
		}
		y3++;
		x3 = x;
	}
	return 1;
}

//
//	ShowTile_Sprite
//
//	Shows a sprite tile with priority
//
//
int	ShowTile_Sprite( int addr, int x, int y, int flipx, int flipy,
			 int color, int Priority, BITMAP *B, int S)
{
	int	x2 = 0, y2 = 0, i;
	int	x3 = 0, y3 = 0;
	int	CurrentColor;
	int	a, b, c, d;
	int	Size = S;
	
	char *ptr = vga_getgraphmem();
		
/*	x += PPU_REG_5B;
	y += PPU_REG_5A;*/
 
       if (flipx)
                x3 = x + 7;
        else
                x3 = x;

        if (flipy)
                y3 = y + Size - 1;
        else
                y3 = y;
 
       	for( d = 0; d < Size; d++) {
		if(d >= 0x08) 
			i = addr+0x08+d;
		else
			i = addr+d;

		for( x2 = 0; x2 < 8; x2++) {
			a = ReadBit( VRAM[ i ], (7-x2) );
			b = ReadBit( VRAM[ i+8 ], (7-x2) );
			
			c = (b << 1) + a;
			
			if(c == 0)
				goto next_pixel;
			if(Priority == 1 && *(Screen_Info + x3 + y3 * 200))
				goto next_pixel;

			c = c | color;
			
                        CurrentColor = VRAM[ 0x3F10 + c];
        
			_putpixel( B, x3 , y3 , CurrentColor );
/*			ptr[(y3*sWIDTH)+x3] = CurrentColor;*/

next_pixel:			
                        if (flipx)
                                x3--;
                        else
                                x3++;
                }
                if (flipy)
                        y3--;
                else
                        y3++;

                if (flipx)
                        x3 = x+7;
                else
                        x3 = x;

	}
	return 1;
}

int     Refresh_Sprite( void )
{
	int x, y;
	int tile,addr,i,j;
	int flip;
	int byt2;
	int baseaddr = (RAM[0x2000] & 0x08) << 9;
	word NameTable;
	int	Size;
	
	Size = 0x08 << ReadBit( RAM[0x2000] , 5 );
		
	for(j = 63; j >= 0; j--) {
		i = j << 2;
		y    = SRAM[ i ] + 1;
		byt2 = SRAM[ i + 0x0002 ];
		x    = SRAM[ i + 0x0003 ];
		tile = SRAM[ i + 0x0001 ];
		if(y > 232)
			continue;
			
                if((Size == 16) && (tile & 0x01)) {
	                tile |= 0x100;
                        tile ^= 0x01;
                }
                
		addr = baseaddr + ( tile << 4 );
				                                                                                                		
		flip = (byt2 & 0xC0) >> 6;
		
		ShowTile_Sprite( addr , x , y , flip , ReadBit( SRAM[ i+0x0002 ] , 0 ) , ReadBit( SRAM[ i+0x0002 ] , 1 ) , ReadBit( SRAM[ i+0x0002 ] , 5 ) , Bitmap , Size);

        }
}

//
// ClearScreen()
//

int ClearScreen()
{
        int Color;

        //
        // Efface l'‚cran dans Bitmap avec la couleur adequate
        //

        Color = RAM[ 0x2001 ] & 0xE0;

        switch( Color )
        {
                case 0:
                        clear_to_color( Bitmap , Black );
                        break;
                case 32:
                        clear_to_color( Bitmap , Red );
                        break;
                case 64:
                        clear_to_color( Bitmap , Green );
                        break;
                case 128:
                        clear_to_color( Bitmap , Blue );
                        break;
                default:
			clear_to_color( Bitmap , Black );
                        break;
        }                        
}

void keyboard_handler(int code, int press)
{
	char message[512];
	FILE *Battery_File;
	
	Keycodes[code] = press;

	if(code == SCANCODE_ESCAPE) {
		TrashMachine();
		if(Battery == 1) {
			printf("Saving battery backup [ %s ]...", Battery_Name);
			Battery_File = fopen( Battery_Name, "wb");
			if( !Battery_File ) {
				puts("Failed!");
				puts("Cannot open the file.");
			} else {
				fwrite( &RAM[0x6000] , 1 , 0x2000 , Battery_File );
				fclose( Battery_File );
				puts("Ok.");
			}
		}
		puts("  Thanks for using XNes!");
		
		exit(1);
	} else if(code == SCANCODE_F7) {
		save_state(RomName);
		sprintf(message, "State saved");
		DisplayMsg(message);
	} else if(code == SCANCODE_F8) {
		load_state(RomName);
		sprintf(message, "State loaded");
		DisplayMsg(message);
	}
}

void set_palette_reg(int index, RGB_color_ptr rgbcolor)
{
	vga_setpalette(index, rgbcolor->red,
			      rgbcolor->green,
			      rgbcolor->blue);
}

#include "palette.h"

void load_pallete_from_pcx(char *pcxfile)
{
#if 0
	FILE *fp;
	int index;
	PALLETE x;
	if((fp = fopen(pcxfile, "rb")) == NULL) {
		printf("Unable to open DATA FILE!\n");
		exit(0);
	}
	fseek(fp, -768, SEEK_END);
	for(index = 0; index < 256; index++) {
		x[index].red = getc(fp) >> 2;
		x[index].green = getc(fp) >> 2;
		x[index].blue = getc(fp) >> 2;
		set_palette_reg(index, &x[index]);
	}
	fclose(fp);
#else
	int index;
	for(index = 0; index < 256; index++) {
		vga_setpalette(index, palette[index].red,
				      palette[index].blue,
				      palette[index].green);
	}
#endif
}

void   Update_Joystick()
{
	static struct JS_DATA_TYPE js;
	static int status;
	
	Joypad_1 &= 0xFF0C;
	
	status = read(Joystick_fd, &js, JS_RETURN);
	if(status != JS_RETURN) {
		TrashMachine();
		perror("joystick");
		exit(2);
	}

	if(js.y < (Joystick_CenterY - 100)) {
		Joypad_1 |= 0x0010;
	} else {
		if(js.y > (Joystick_CenterY + 100))
			Joypad_1 |= 0x0020;
		else {
			Joypad_1 &= ~0x0020;
			Joypad_1 &= ~0x0010;
		}
	}

	if(js.x < (Joystick_CenterX - 100)) {
		Joypad_1 |= 0x0040;
	} else {
		if(js.x > (Joystick_CenterX + 100))
			Joypad_1 |= 0x0080;
		else {
			Joypad_1 &= ~0x0080;
			Joypad_1 &= ~0x0080;
		}
	}
	
	if(js.buttons & 2)
		Joypad_1 |= 0x0001;
	else
		Joypad_1 &= ~0x0001;
	if(js.buttons & 1)
		Joypad_1 |= 0x0002;
	else
		Joypad_1 &= ~0x0002;
}
		
int    CheckKb( void )
{
	static int Used_Joystick = -1;
	
	if(Used_Joystick == -1) {
		Used_Joystick = Using_Joystick;
	}
	
	keyboard_update();
	if(Using_Joystick) 
		Update_Joystick();
	else {
		if(Keycodes[SCANCODE_CURSORBLOCKUP] == 1) /* Up */
    			Joypad_1 |= 0x0010;
    		else
    			WriteBit(Joypad_1, 0, 4);
		if(Keycodes[SCANCODE_LEFTALT] == 1)
		        Joypad_1 |= 0x0001;
		else
			WriteBit(Joypad_1, 0, 0);
        	if(Keycodes[SCANCODE_LEFTCONTROL] == 1)
        		Joypad_1 |= 0x0002;
        	else
        		WriteBit(Joypad_1, 0, 1);
		if(Keycodes[SCANCODE_CURSORBLOCKDOWN] == 1)
			Joypad_1 |= 0x0020;
		else
			WriteBit(Joypad_1, 0, 5);
	        if(Keycodes[SCANCODE_CURSORBLOCKLEFT] == 1)
        		Joypad_1 |= 0x0040;
        	else
        		WriteBit(Joypad_1, 0, 6);
		if(Keycodes[SCANCODE_CURSORBLOCKRIGHT] == 1)
        	        Joypad_1 |= 0x0080;
        	else
        		WriteBit(Joypad_1, 0, 7);
        }
        if(Keycodes[SCANCODE_ENTER] == 1) /* Start */
	        Joypad_1 |= 0x0008;
	else
		WriteBit(Joypad_1, 0, 3);
        if(Keycodes[SCANCODE_TAB] == 1)
                Joypad_1 |= 0x0004;
        else
        	WriteBit(Joypad_1, 0, 2);
                                                                                 
        if(Keycodes[SCANCODE_ESCAPE] == 1) {
                TrashMachine();
   	        puts("  Thanks for using XNes !");
                exit(1);
        }
        if(Keycodes[SCANCODE_F10] == 1) 
       	        SnapScreen(Bitmap);
        if(Keycodes[SCANCODE_F3] == 1) {
        	if(sWIDTH == 320 && sHEIGHT == 200) {
        		if(stretch) {
        			DisplayMsg("Stretch Disabled.");
        			stretch = 0;
        			memset(vga_getgraphmem(), Black, sWIDTH*sHEIGHT);
        		} else {
        			DisplayMsg("Stretch Enabled.");
        			stretch = 1;
        		}
        	} else 
        		DisplayMsg("Wrong video mode.\n");
        	Keycodes[SCANCODE_F3] = 0;
        }
        if(Keycodes[SCANCODE_F4] == 1) {
      	        palette_disp();
      	        DisplayMsg("Palette display.");
      	}
        if(Keycodes[SCANCODE_F5] == 1) {
		Reset_Nes();
		DisplayMsg("System reset.");
	}
  	if(Keycodes[SCANCODE_EQUAL] == 1)
                FrameRate++;
        if(Keycodes[SCANCODE_MINUS] == 1) {
               	FrameRate--;
                if( FrameRate < 1 )
	                FrameRate = 1;
	} 
	if(Keycodes[SCANCODE_F6] == 1) {
		if(Used_Joystick) {
			Using_Joystick = !Using_Joystick;
			if(Using_Joystick) 
				DisplayMsg("Joystick on.");
			else
				DisplayMsg("Joystick off.");
		}
		
	}
}

// ScanKb
//
// retourne 0 si aucune touche press‚ sinon retourne
// le code de la touche
//

int     ScanKb()
{
	return 0;
}

void CalibrateJoystick()
{
	struct JS_DATA_TYPE js;
	int status;
	
	status = read(Joystick_fd, &js, JS_RETURN);
	status = read(Joystick_fd, &js, JS_RETURN);
	if(status != JS_RETURN) {
		perror("joystick");
		exit(2);
	}
	Joystick_CenterX = js.x;
	Joystick_CenterY = js.y;
}


int Checksum( byte *var , int x, int nx )
{
	int i, Checksum_R = 0;
	for(i = x; i <= nx; i++)
		Checksum_R += var[ i ];
	return(Checksum_R);
}xNES/Codes.h100644    765    144       25452  6422445476  12204 0ustar  chuckjrusers/** M6502: portable 6502 emulator ****************************/
/**                                                         **/
/**                          Codes.h                        **/
/**                                                         **/
/** This file contains implementation for the main table of **/
/** 6502 commands. It is included from 6502.c.              **/
/**                                                         **/
/** Copyright (C) Marat Fayzullin 1996                      **/
/**               Alex Krasivsky  1996                      **/
/**     You are not allowed to distribute this software     **/
/**     commercially. Please, notify me, if you make any    **/
/**     changes to this file.                               **/
/*************************************************************/

case 0x10: if(R->P&N_FLAG) R->PC.W++; else { M_JR; } break; /* BPL * REL */
case 0x30: if(R->P&N_FLAG) { M_JR; } else R->PC.W++; break; /* BMI * REL */
case 0xD0: if(R->P&Z_FLAG) R->PC.W++; else { M_JR; } break; /* BNE * REL */
case 0xF0: if(R->P&Z_FLAG) { M_JR; } else R->PC.W++; break; /* BEQ * REL */
case 0x90: if(R->P&C_FLAG) R->PC.W++; else { M_JR; } break; /* BCC * REL */
case 0xB0: if(R->P&C_FLAG) { M_JR; } else R->PC.W++; break; /* BCS * REL */
case 0x50: if(R->P&V_FLAG) R->PC.W++; else { M_JR; } break; /* BVC * REL */
case 0x70: if(R->P&V_FLAG) { M_JR; } else R->PC.W++; break; /* BVS * REL */

/* RTI */
case 0x40:
  M_POP(R->P);R->P|=R_FLAG;M_POP(R->PC.B.l);M_POP(R->PC.B.h);
  break;

/* RTS */
case 0x60:
  M_POP(R->PC.B.l);M_POP(R->PC.B.h);R->PC.W++;break;

/* JSR $ssss ABS */
case 0x20:
  K.B.l=Op6502(R->PC.W++);
  K.B.h=Op6502(R->PC.W);
  M_PUSH(R->PC.B.h);
  M_PUSH(R->PC.B.l);
  R->PC=K;break;

/* JMP $ssss ABS */
case 0x4C: M_LDWORD(K);R->PC=K;break;

/* JMP ($ssss) ABDINDIR */
case 0x6C:
  M_LDWORD(K);
  R->PC.B.l=Rd6502(K.W++);
  R->PC.B.h=Rd6502(K.W);
  break;

/* BRK */
case 0x00:
  R->PC.W++;
  M_PUSH(R->PC.B.h);M_PUSH(R->PC.B.l);
  M_PUSH(R->P|B_FLAG);
  R->P=(R->P|I_FLAG)&~D_FLAG;
  R->PC.B.l=Rd6502(0xFFFE);
  R->PC.B.h=Rd6502(0xFFFF);
  break;

/* CLI */
case 0x58:
  if((R->IRequest!=INT_NONE)&&(R->P&I_FLAG))
  {
    R->AfterCLI=1;
    R->IBackup=R->ICount;
    R->ICount=1;
  }
  R->P&=~I_FLAG;
  break;

/* PLP */
case 0x28:
  M_POP(I);
  if((R->IRequest!=INT_NONE)&&((I^R->P)&~I&I_FLAG))
  {
    R->AfterCLI=1;
    R->IBackup=R->ICount;
    R->ICount=1;
  }
  R->P=I|R_FLAG;
  break;

case 0x08: M_PUSH(R->P);break;               /* PHP */
case 0x18: R->P&=~C_FLAG;break;              /* CLC */
case 0xB8: R->P&=~V_FLAG;break;              /* CLV */
case 0xD8: R->P&=~D_FLAG;break;              /* CLD */
case 0x38: R->P|=C_FLAG;break;               /* SEC */
case 0xF8: R->P|=D_FLAG;break;               /* SED */
case 0x78: R->P|=I_FLAG;break;               /* SEI */
case 0x48: M_PUSH(R->A);break;               /* PHA */
case 0x68: M_POP(R->A);M_FL(R->A);break;     /* PLA */
case 0x98: R->A=R->Y;M_FL(R->A);break;       /* TYA */
case 0xA8: R->Y=R->A;M_FL(R->Y);break;       /* TAY */
case 0xC8: R->Y++;M_FL(R->Y);break;          /* INY */
case 0x88: R->Y--;M_FL(R->Y);break;          /* DEY */
case 0x8A: R->A=R->X;M_FL(R->A);break;       /* TXA */
case 0xAA: R->X=R->A;M_FL(R->X);break;       /* TAX */
case 0xE8: R->X++;M_FL(R->X);break;          /* INX */
case 0xCA: R->X--;M_FL(R->X);break;          /* DEX */
case 0xEA: break;                            /* NOP */
case 0x9A: R->S=R->X;break;                  /* TXS */
case 0xBA: R->X=R->S;break;                  /* TSX */

case 0x24: MR_Zp(I);M_BIT(I);break;       /* BIT $ss ZP */
case 0x2C: MR_Ab(I);M_BIT(I);break;       /* BIT $ssss ABS */

case 0x05: MR_Zp(I);M_ORA(I);break;       /* ORA $ss ZP */
case 0x06: MM_Zp(M_ASL);break;            /* ASL $ss ZP */
case 0x25: MR_Zp(I);M_AND(I);break;       /* AND $ss ZP */
case 0x26: MM_Zp(M_ROL);break;            /* ROL $ss ZP */
case 0x45: MR_Zp(I);M_EOR(I);break;       /* EOR $ss ZP */
case 0x46: MM_Zp(M_LSR);break;            /* LSR $ss ZP */
case 0x65: MR_Zp(I);M_ADC(I);break;       /* ADC $ss ZP */
case 0x66: MM_Zp(M_ROR);break;            /* ROR $ss ZP */
case 0x84: MW_Zp(R->Y);break;             /* STY $ss ZP */
case 0x85: MW_Zp(R->A);break;             /* STA $ss ZP */
case 0x86: MW_Zp(R->X);break;             /* STX $ss ZP */
case 0xA4: MR_Zp(R->Y);M_FL(R->Y);break;  /* LDY $ss ZP */
case 0xA5: MR_Zp(R->A);M_FL(R->A);break;  /* LDA $ss ZP */
case 0xA6: MR_Zp(R->X);M_FL(R->X);break;  /* LDX $ss ZP */
case 0xC4: MR_Zp(I);M_CMP(R->Y,I);break;  /* CPY $ss ZP */
case 0xC5: MR_Zp(I);M_CMP(R->A,I);break;  /* CMP $ss ZP */
case 0xC6: MM_Zp(M_DEC);break;            /* DEC $ss ZP */
case 0xE4: MR_Zp(I);M_CMP(R->X,I);break;  /* CPX $ss ZP */
case 0xE5: MR_Zp(I);M_SBC(I);break;       /* SBC $ss ZP */
case 0xE6: MM_Zp(M_INC);break;            /* INC $ss ZP */

case 0x0D: MR_Ab(I);M_ORA(I);break;       /* ORA $ssss ABS */
case 0x0E: MM_Ab(M_ASL);break;            /* ASL $ssss ABS */
case 0x2D: MR_Ab(I);M_AND(I);break;       /* AND $ssss ABS */
case 0x2E: MM_Ab(M_ROL);break;            /* ROL $ssss ABS */
case 0x4D: MR_Ab(I);M_EOR(I);break;       /* EOR $ssss ABS */
case 0x4E: MM_Ab(M_LSR);break;            /* LSR $ssss ABS */
case 0x6D: MR_Ab(I);M_ADC(I);break;       /* ADC $ssss ABS */
case 0x6E: MM_Ab(M_ROR);break;            /* ROR $ssss ABS */
case 0x8C: MW_Ab(R->Y);break;             /* STY $ssss ABS */
case 0x8D: MW_Ab(R->A);break;             /* STA $ssss ABS */
case 0x8E: MW_Ab(R->X);break;             /* STX $ssss ABS */
case 0xAC: MR_Ab(R->Y);M_FL(R->Y);break;  /* LDY $ssss ABS */
case 0xAD: MR_Ab(R->A);M_FL(R->A);break;  /* LDA $ssss ABS */
case 0xAE: MR_Ab(R->X);M_FL(R->X);break;  /* LDX $ssss ABS */
case 0xCC: MR_Ab(I);M_CMP(R->Y,I);break;  /* CPY $ssss ABS */
case 0xCD: MR_Ab(I);M_CMP(R->A,I);break;  /* CMP $ssss ABS */
case 0xCE: MM_Ab(M_DEC);break;            /* DEC $ssss ABS */
case 0xEC: MR_Ab(I);M_CMP(R->X,I);break;  /* CPX $ssss ABS */
case 0xED: MR_Ab(I);M_SBC(I);break;       /* SBC $ssss ABS */
case 0xEE: MM_Ab(M_INC);break;            /* INC $ssss ABS */

case 0x09: MR_Im(I);M_ORA(I);break;       /* ORA #$ss IMM */
case 0x29: MR_Im(I);M_AND(I);break;       /* AND #$ss IMM */
case 0x49: MR_Im(I);M_EOR(I);break;       /* EOR #$ss IMM */
case 0x69: MR_Im(I);M_ADC(I);break;       /* ADC #$ss IMM */
case 0xA0: MR_Im(R->Y);M_FL(R->Y);break;  /* LDY #$ss IMM */
case 0xA2: MR_Im(R->X);M_FL(R->X);break;  /* LDX #$ss IMM */
case 0xA9: MR_Im(R->A);M_FL(R->A);break;  /* LDA #$ss IMM */
case 0xC0: MR_Im(I);M_CMP(R->Y,I);break;  /* CPY #$ss IMM */
case 0xC9: MR_Im(I);M_CMP(R->A,I);break;  /* CMP #$ss IMM */
case 0xE0: MR_Im(I);M_CMP(R->X,I);break;  /* CPX #$ss IMM */
case 0xE9: MR_Im(I);M_SBC(I);break;       /* SBC #$ss IMM */

case 0x15: MR_Zx(I);M_ORA(I);break;       /* ORA $ss,x ZP,x */
case 0x16: MM_Zx(M_ASL);break;            /* ASL $ss,x ZP,x */
case 0x35: MR_Zx(I);M_AND(I);break;       /* AND $ss,x ZP,x */
case 0x36: MM_Zx(M_ROL);break;            /* ROL $ss,x ZP,x */
case 0x55: MR_Zx(I);M_EOR(I);break;       /* EOR $ss,x ZP,x */
case 0x56: MM_Zx(M_LSR);break;            /* LSR $ss,x ZP,x */
case 0x75: MR_Zx(I);M_ADC(I);break;       /* ADC $ss,x ZP,x */
case 0x76: MM_Zx(M_ROR);break;            /* ROR $ss,x ZP,x */
case 0x94: MW_Zx(R->Y);break;             /* STY $ss,x ZP,x */
case 0x95: MW_Zx(R->A);break;             /* STA $ss,x ZP,x */
case 0x96: MW_Zy(R->X);break;             /* STX $ss,y ZP,y */
case 0xB4: MR_Zx(R->Y);M_FL(R->Y);break;  /* LDY $ss,x ZP,x */
case 0xB5: MR_Zx(R->A);M_FL(R->A);break;  /* LDA $ss,x ZP,x */
case 0xB6: MR_Zy(R->X);M_FL(R->X);break;  /* LDX $ss,y ZP,y */
case 0xD5: MR_Zx(I);M_CMP(R->A,I);break;  /* CMP $ss,x ZP,x */
case 0xD6: MM_Zx(M_DEC);break;            /* DEC $ss,x ZP,x */
case 0xF5: MR_Zx(I);M_SBC(I);break;       /* SBC $ss,x ZP,x */
case 0xF6: MM_Zx(M_INC);break;            /* INC $ss,x ZP,x */

case 0x19: MR_Ay(I);M_ORA(I);break;       /* ORA $ssss,y ABS,y */
case 0x1D: MR_Ax(I);M_ORA(I);break;       /* ORA $ssss,x ABS,x */
case 0x1E: MM_Ax(M_ASL);break;            /* ASL $ssss,x ABS,x */
case 0x39: MR_Ay(I);M_AND(I);break;       /* AND $ssss,y ABS,y */
case 0x3D: MR_Ax(I);M_AND(I);break;       /* AND $ssss,x ABS,x */
case 0x3E: MM_Ax(M_ROL);break;            /* ROL $ssss,x ABS,x */
case 0x59: MR_Ay(I);M_EOR(I);break;       /* EOR $ssss,y ABS,y */
case 0x5D: MR_Ax(I);M_EOR(I);break;       /* EOR $ssss,x ABS,x */
case 0x5E: MM_Ax(M_LSR);break;            /* LSR $ssss,x ABS,x */
case 0x79: MR_Ay(I);M_ADC(I);break;       /* ADC $ssss,y ABS,y */
case 0x7D: MR_Ax(I);M_ADC(I);break;       /* ADC $ssss,x ABS,x */
case 0x7E: MM_Ax(M_ROR);break;            /* ROR $ssss,x ABS,x */
case 0x99: MW_Ay(R->A);break;             /* STA $ssss,y ABS,y */
case 0x9D: MW_Ax(R->A);break;             /* STA $ssss,x ABS,x */
case 0xB9: MR_Ay(R->A);M_FL(R->A);break;  /* LDA $ssss,y ABS,y */
case 0xBC: MR_Ax(R->Y);M_FL(R->Y);break;  /* LDY $ssss,x ABS,x */
case 0xBD: MR_Ax(R->A);M_FL(R->A);break;  /* LDA $ssss,x ABS,x */
case 0xBE: MR_Ay(R->X);M_FL(R->X);break;  /* LDX $ssss,y ABS,y */
case 0xD9: MR_Ay(I);M_CMP(R->A,I);break;  /* CMP $ssss,y ABS,y */
case 0xDD: MR_Ax(I);M_CMP(R->A,I);break;  /* CMP $ssss,x ABS,x */
case 0xDE: MM_Ax(M_DEC);break;            /* DEC $ssss,x ABS,x */
case 0xF9: MR_Ay(I);M_SBC(I);break;       /* SBC $ssss,y ABS,y */
case 0xFD: MR_Ax(I);M_SBC(I);break;       /* SBC $ssss,x ABS,x */
case 0xFE: MM_Ax(M_INC);break;            /* INC $ssss,x ABS,x */

case 0x01: MR_Ix(I);M_ORA(I);break;       /* ORA ($ss,x) INDEXINDIR */
case 0x11: MR_Iy(I);M_ORA(I);break;       /* ORA ($ss),y INDIRINDEX */
case 0x21: MR_Ix(I);M_AND(I);break;       /* AND ($ss,x) INDEXINDIR */
case 0x31: MR_Iy(I);M_AND(I);break;       /* AND ($ss),y INDIRINDEX */
case 0x41: MR_Ix(I);M_EOR(I);break;       /* EOR ($ss,x) INDEXINDIR */
case 0x51: MR_Iy(I);M_EOR(I);break;       /* EOR ($ss),y INDIRINDEX */
case 0x61: MR_Ix(I);M_ADC(I);break;       /* ADC ($ss,x) INDEXINDIR */
case 0x71: MR_Iy(I);M_ADC(I);break;       /* ADC ($ss),y INDIRINDEX */
case 0x81: MW_Ix(R->A);break;             /* STA ($ss,x) INDEXINDIR */
case 0x91: MW_Iy(R->A);break;             /* STA ($ss),y INDIRINDEX */
case 0xA1: MR_Ix(R->A);M_FL(R->A);break;  /* LDA ($ss,x) INDEXINDIR */
case 0xB1: MR_Iy(R->A);M_FL(R->A);break;  /* LDA ($ss),y INDIRINDEX */
case 0xC1: MR_Ix(I);M_CMP(R->A,I);break;  /* CMP ($ss,x) INDEXINDIR */
case 0xD1: MR_Iy(I);M_CMP(R->A,I);break;  /* CMP ($ss),y INDIRINDEX */
case 0xE1: MR_Ix(I);M_SBC(I);break;       /* SBC ($ss,x) INDEXINDIR */
case 0xF1: MR_Iy(I);M_SBC(I);break;       /* SBC ($ss),y INDIRINDEX */

case 0x0A: M_ASL(R->A);break;             /* ASL a ACC */
case 0x2A: M_ROL(R->A);break;             /* ROL a ACC */
case 0x4A: M_LSR(R->A);break;             /* LSR a ACC */
case 0x6A: M_ROR(R->A);break;             /* ROR a ACC */

default:
  if(R->TrapBadOps)
    printf
    (
      "[M6502 %lX] Unrecognized instruction: $%02X at PC=$%04X\n",
      R->User,Op6502(R->PC.W-1),(word)(R->PC.W-1)
    );
  break;
xNES/Tables.h100644    765    144        5271  6422445476  12336 0