pkg://xNES-0.49-4.src.rpm:44552/xnessrc.tar.gz
info downloads
xNES/ 40755 765 144 0 6461743167 10652 5 ustar chuckjr users xNES/msg.c 100644 765 144 1662 6440366340 11675 0 ustar chuckjr users #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.c 100644 765 144 22367 6433657601 11652 0 ustar chuckjr users /** 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.c 100644 765 144 112722 6461743123 12125 0 ustar chuckjr users /*
* 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.h 100644 765 144 217 6440303261 11646 0 ustar chuckjr users #ifndef __MSG_H
#define __MSG_H
void gl_myinit(int, int, int);
void DisplayMsg(char *);
void DrawMsg();
extern int MessageFrameCount;
#endif xNES/xnes.h 100644 765 144 3130 6443121557 12063 0 ustar chuckjr users //
// 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.h 100644 765 144 2317 6460407443 11701 0 ustar chuckjr users //
// 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.h 100644 765 144 14043 6422445476 11652 0 ustar chuckjr users /** 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/LICENSE 100600 765 144 43313 6460701266 11761 0 ustar chuckjr users 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.h 100644 765 144 23531 6437405575 12603 0 ustar chuckjr users /* 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.c 100644 765 144 43011 6460701676 11715 0 ustar chuckjr users /*
* 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.h 100644 765 144 25452 6422445476 12204 0 ustar chuckjr users /** 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.h 100644 765 144 5271 6422445476 12336 0