Commit 8d5f4a12 authored by Matt Sephton's avatar Matt Sephton
Browse files

version 4.9 changes

parent 81ec0f95
/** EMULib Emulation Library *********************************/
/** **/
/** Hunt.c **/
/** **/
/** This file implements mechanism for searching possible **/
/** cheats inside running game data. Also see Hunt.h. **/
/** **/
/** Copyright (C) Marat Fayzullin 2013-2016 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "Hunt.h"
#include <stdio.h>
#if defined(VGBA)
#include "ARM.h"
#define MEMREAD32(A) QRdARM(A)
#define MEMREAD16(A) WRdARM(A)
#define MEMREAD8(A) BRdARM(A)
#elif defined(INES)
#include "M6502.h"
#define MEMREAD32(A) (Rd6502(A)+((int)Rd6502(A+1)<<8)+((int)Rd6502(A+2)<<16)+((int)Rd6502(A+3)<<24))
#define MEMREAD16(A) (Rd6502(A)+((int)Rd6502(A+1)<<8))
#define MEMREAD8(A) Rd6502(A)
#elif defined(VGB) || defined(MG) || defined(COLEM) || defined(SPECCY) || defined(FMSX)
#include "Z80.h"
#define MEMREAD32(A) (RdZ80(A)+((int)RdZ80(A+1)<<8)+((int)RdZ80(A+2)<<16)+((int)RdZ80(A+3)<<24))
#define MEMREAD16(A) (RdZ80(A)+((int)RdZ80(A+1)<<8))
#define MEMREAD8(A) RdZ80(A)
#else
#define MEMREAD32(A) (0)
#define MEMREAD16(A) (0)
#define MEMREAD8(A) (0)
#endif
static HUNTEntry Buf[HUNT_BUFSIZE];
static int Count;
/** InitHUNT() ***********************************************/
/** Initialize cheat search, clearing all data. **/
/*************************************************************/
void InitHUNT(void) { Count=0; }
/** TotalHUNT() **********************************************/
/** Get total number of currently watched locations. **/
/*************************************************************/
int TotalHUNT(void) { return(Count); }
/** GetHUNT() ************************************************/
/** Get Nth memory location. Returns 0 for invalid N. **/
/*************************************************************/
HUNTEntry *GetHUNT(int N)
{ return((N>=0)&&(N<Count)? &Buf[N]:0); }
/** AddHUNT() ************************************************/
/** Add a new value to search for, with the address range **/
/** to search in. Returns number of memory locations found. **/
/*************************************************************/
int AddHUNT(unsigned int Addr,unsigned int Size,unsigned int Value,unsigned int NewValue,unsigned int Flags)
{
unsigned int J,M;
int I;
/* Force 32bit/16bit mode for large values */
if((Value>=0x10000)||(NewValue>=0x10000))
Flags = (Flags&~HUNT_MASK_SIZE)|HUNT_32BIT;
else if((Value>=0x100)||(NewValue>=0x100))
Flags = (Flags&~HUNT_MASK_SIZE)|HUNT_16BIT;
/* Compute mask for given value size and truncate value */
M = Flags&HUNT_32BIT? 0xFFFFFFFF:Flags&HUNT_16BIT? 0xFFFF:0x00FF;
#ifdef VGBA
/* ARM aligns data to the size boundary */
if(M>0xFFFF) Addr&=~3; else if(M>0xFF) Addr&=~1;
#endif
/* Scan memory for given value */
for(Size+=Addr,I=0;(Addr<Size)&&(Count<HUNT_BUFSIZE);++Addr)
{
J = (M>0xFFFF? MEMREAD32(Addr):M>0xFF? MEMREAD16(Addr):MEMREAD8(Addr))&M;
if((J==Value)||(J==((Value-1)&M)))
{
Buf[Count].Addr = Addr;
Buf[Count].Flags = Flags;
Buf[Count].Value = J;
Buf[Count].Orig = J==Value? NewValue:((NewValue-1)&M);
Buf[Count].Count = 0;
++Count;
++I;
}
#ifdef VGBA
/* ARM aligns data to the size boundary */
if(M>0xFFFF) Addr+=3; else if(M>0xFF) Addr+=1;
#endif
}
/* Return the number of matches found */
return(I);
}
/** ScanHUNT() ***********************************************/
/** Scan memory for changed values and update search data. **/
/** Returns number of memory locations updated. **/
/*************************************************************/
int ScanHUNT(void)
{
unsigned int K,L;
int J,I;
/* Scan active search entries */
for(J=I=0;J<Count;++J)
{
L = Buf[J].Flags&HUNT_32BIT? 0xFFFFFFFF:Buf[J].Flags&HUNT_16BIT? 0xFFFF:0x00FF;
K = (L>0xFFFF? MEMREAD32(Buf[J].Addr):L>0xFF? MEMREAD16(Buf[J].Addr):MEMREAD8(Buf[J].Addr))&L;
/* Check for expected changes */
switch(Buf[J].Flags&HUNT_MASK_CHANGE)
{
case HUNT_PLUSONE: L = K==((Buf[J].Value+1)&L);break;
case HUNT_PLUSMANY: L = K>Buf[J].Value;break;
case HUNT_MINUSONE: L = K==((Buf[J].Value-1)&L);break;
case HUNT_MINUSMANY: L = K<Buf[J].Value;break;
default:
case HUNT_CONSTANT: L = K==Buf[J].Value;break;
}
/* Delete any entry that does not change as expected */
if(L)
{
if(Buf[J].Count<(1<<(sizeof(Buf[J].Count)<<3))-1) ++Buf[J].Count;
Buf[J].Value = K;
Buf[I++] = Buf[J];
}
}
/* Return number of successfully updated entries */
return(Count=I);
}
/** HUNT2Cheat() *********************************************/
/** Create cheat code from Nth hunt entry. Returns 0 if the **/
/** entry is invalid. **/
/*************************************************************/
const char *HUNT2Cheat(int N,unsigned int Type)
{
static char Buf[32];
HUNTEntry *HE;
/* Must have a valid entry */
if(!(HE=GetHUNT(N))) return(0);
/* Depending on cheat type... */
switch(Type)
{
/** GameBoy Advance ******************************************/
/** There are two versions of GameShark (v1/v3) differing **/
/** by encryption and CodeBreaker. Not encrypting here. **/
/*************************************************************/
case HUNT_GBA_GS:
/* 00AAAAAA NNNNNNDD - Multiple 8bit RAM Write */
/* 02AAAAAA NNNNDDDD - Multiple 816bit RAM Write */
sprintf(Buf,"0%c%06X 0000%04X",
HE->Flags&HUNT_16BIT? '2':'0',
(HE->Addr&0x000FFFFF)|((HE->Addr&0x0F000000)>>4),
HE->Orig
);
return(Buf);
case HUNT_GBA_CB:
/* 2AAAAAAA XXXX - 16bit RAM Write */
/* 3AAAAAAA 00XX - 8bit RAM Write */
sprintf(Buf,"%c%07X %04X",
HE->Flags&HUNT_16BIT? '2':'3',
HE->Addr&0x0FFFFFFF,
HE->Orig
);
return(Buf);
/** GameBoy **************************************************/
/** GameBoy has GameShark and GameGenie, but only GameShark **/
/** can modify RAM. **/
/*************************************************************/
case HUNT_GB_GS:
/* 00DDAAAA - 8bit RAM Write, No Bank */
sprintf(Buf,"00%02X%02X%02X",(HE->Orig)&0xFF,HE->Addr&0x00FF,(HE->Addr&0xFF00)>>8);
if(HE->Flags&HUNT_16BIT)
sprintf(Buf+8,";00%02X%02X%02X",HE->Orig>>8,(HE->Addr+1)&0x00FF,((HE->Addr+1)&0xFF00)>>8);
return(Buf);
/** NES ******************************************************/
/** NES has both Pro Action Replay and GameGenie, but only **/
/** Pro Action Replay can modify RAM. **/
/*************************************************************/
case HUNT_NES_AR:
/* 00AAAADD - 8bit RAM Write */
sprintf(Buf,"00%04X%02X",HE->Addr&0xFFFF,HE->Orig&0xFF);
if(HE->Flags&HUNT_16BIT)
sprintf(Buf+8,";00%04X%02X",(HE->Addr+1)&0xFFFF,HE->Orig>>8);
return(Buf);
/** Sega MasterSystem and GameGear ***************************/
/** MasterSystem has Pro Action Replay, while GameGear has **/
/** GameGenie. Only Pro Action Replay can modify RAM. **/
/*************************************************************/
case HUNT_SMS_AR:
/* 00AA-AADD - 8bit RAM Write */
sprintf(Buf,"00%02X-%02X%02X",(HE->Addr&0xFF00)>>8,HE->Addr&0x00FF,HE->Orig&0xFF);
if(HE->Flags&HUNT_16BIT)
sprintf(Buf+9,";00%02X-%02X%02X",((HE->Addr+1)&0xFF00)>>8,(HE->Addr+1)&0x00FF,HE->Orig>>8);
return(Buf);
/** ColecoVision, MSX, ZX Spectrum ***************************/
/** There was no official cheating hardware for these **/
/** systems, so we come up with our own "hardware". **/
/*************************************************************/
case HUNT_MSX:
case HUNT_ZXS:
case HUNT_COLECO:
/* AAAA-DD[DD] - 8bit[16bit] RAM Write */
if(HE->Flags&HUNT_16BIT)
sprintf(Buf,"%04X-%04X",HE->Addr,HE->Orig&0xFFFF);
else
sprintf(Buf,"%04X-%02X",HE->Addr,HE->Orig&0x00FF);
return(Buf);
}
/* Invalid cheat type */
return(0);
}
/** EMULib Emulation Library *********************************/
/** **/
/** Hunt.h **/
/** **/
/** This file declares functions to search for possible **/
/** cheats inside running game data. Also see Hunt.c. **/
/** **/
/** Copyright (C) Marat Fayzullin 2013-2016 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef HUNT_H
#define HUNT_H
#define HUNT_BUFSIZE 1024
/** Flags used in AddHUNT() **********************************/
#define HUNT_MASK_ID 0x00FF
#define HUNT_MASK_CHANGE 0x0700
#define HUNT_CONSTANT 0x0000
#define HUNT_PLUSONE 0x0100
#define HUNT_PLUSMANY 0x0200
#define HUNT_MINUSONE 0x0300
#define HUNT_MINUSMANY 0x0400
#define HUNT_MASK_SIZE 0x1800
#define HUNT_8BIT 0x0000
#define HUNT_16BIT 0x0800
#define HUNT_32BIT 0x1000
/** Types used in HUNT2Cheat() *******************************/
#define HUNT_GBA_GS 0 /* GBA GameShark Advance */
#define HUNT_GBA_CB 1 /* GBA CodeBreaker Advance */
#define HUNT_SMS_AR 2 /* SMS Pro Action Replay */
#define HUNT_NES_AR 3 /* NES Pro Action Replay */
#define HUNT_GB_GS 4 /* GB GameShark */
#define HUNT_COLECO 5 /* ColecoVision cheats */
#define HUNT_MSX 6 /* MSX cheats */
#define HUNT_ZXS 7 /* ZX Spectrum cheats */
/** HUNTEntry ************************************************/
/** Search entry containing data on one memory location. **/
/*************************************************************/
typedef struct
{
unsigned int Addr; /* Memory location address */
unsigned int Orig; /* Original value at the address */
unsigned int Value; /* Current value at the address */
unsigned short Flags; /* Options supplied in AddHUNT() */
unsigned short Count; /* Number of detected changes */
} HUNTEntry;
/** InitHUNT() ***********************************************/
/** Initialize cheat search, clearing all data. **/
/*************************************************************/
void InitHUNT(void);
/** AddHUNT() ************************************************/
/** Add a new value to search for, with the address range **/
/** to search in. Returns number of memory locations found. **/
/*************************************************************/
int AddHUNT(unsigned int Addr,unsigned int Size,unsigned int Value,unsigned int NewValue,unsigned int Flags);
/** ScanHUNT() ***********************************************/
/** Scan memory for changed values and update search data. **/
/** Returns number of memory locations updated. **/
/*************************************************************/
int ScanHUNT(void);
/** TotalHUNT() **********************************************/
/** Get total number of currently watched locations. **/
/*************************************************************/
int TotalHUNT(void);
/** GetHUNT() ************************************************/
/** Get Nth memory location. Returns 0 for invalid N. **/
/*************************************************************/
HUNTEntry *GetHUNT(int N);
/** HUNT2Cheat() *********************************************/
/** Create cheat code from Nth hunt entry. Returns 0 if the **/
/** entry is invalid. **/
/*************************************************************/
const char *HUNT2Cheat(int N,unsigned int Type);
#endif /* HUNT_H */
#include "IPS.h"
#include <stdio.h>
#include <string.h>
#if defined(ANDROID)
#include "MemFS.h"
#define fopen mopen
#define fclose mclose
#define fread mread
#define fseek mseek
#elif defined(ZLIB)
#include <zlib.h>
#define fopen(F,M) (FILE *)gzopen(F,M)
#define fclose(F) gzclose((gzFile)(F))
#define fread(B,N,L,F) gzread((gzFile)(F),B,(L)*(N))
#define fseek(F,N,W) (gzseek((gzFile)(F),N,W)<0? -1:0)
#endif
/** MeasureIPS() *********************************************/
/** Find total data size assumed by a given .IPS file. **/
/*************************************************************/
unsigned int MeasureIPS(const char *FileName)
{
return(ApplyIPS(FileName,0,0));
}
/** ApplyIPS() ***********************************************/
/** Loads patches from an .IPS file and applies them to the **/
/** given data buffer. Returns number of patches applied. **/
/*************************************************************/
unsigned int ApplyIPS(const char *FileName,unsigned char *Data,unsigned int Size)
{
unsigned char Buf[16];
unsigned int Result,Count,J,N;
FILE *F;
F = fopen(FileName,"rb");
if(!F) return(0);
/* Verify file header */
if(fread(Buf,1,5,F)!=5) { fclose(F);return(0); }
if(memcmp(Buf,"PATCH",5)) { fclose(F);return(0); }
for(Result=0,Count=1;fread(Buf,1,5,F)==5;++Count)
{
J = Buf[2]+((unsigned int)Buf[1]<<8)+((unsigned int)Buf[0]<<16);
N = Buf[4]+((unsigned int)Buf[3]<<8);
/* Apparently, these may signal the end of .IPS file */
if((J==0xFFFFFF) || !memcmp(Buf,"EOF",3)) break;
/* If patching with a block of data... */
if(N)
{
/* Copying data */
if(!Data)
{
/* Just measuring patch size */
if(Result<J+N) Result=J+N;
if(fseek(F,N,SEEK_CUR)<0) break;
}
else if(J+N>Size)
{
printf("IPS: Failed applying COPY patch #%d to 0x%X..0x%X of 0x%X bytes.\n",Count,J,J+N-1,Size);
if(fseek(F,N,SEEK_CUR)<0) break;
}
else if(fread(Data+J,1,N,F)==N)
{
// printf("IPS: Applied COPY patch #%d to 0x%X..0x%X.\n",Count,J,J+N-1);
++Result;
}
else
{
printf("IPS: Failed reading COPY patch #%d from the file.\n",Count);
break;
}
}
else
{
/* Filling with a value */
if(fread(Buf,1,3,F)!=3)
{
if(Data) printf("IPS: Failed reading FILL patch #%d from the file.\n",Count);
break;
}
/* Compute fill length */
N = ((unsigned int)Buf[0]<<8)+Buf[1];
if(!Data)
{
if(Result<J+N) Result=J+N;
}
else if(!N || (J+N>Size))
{
printf("IPS: Failed applying FILL patch #%d (0x%02X) to 0x%X..0x%X of 0x%X bytes.\n",Count,Buf[1],J,J+N-1,Size);
}
else
{
// printf("IPS: Applied FILL patch #%d (0x%02X) to 0x%X..0x%X.\n",Count,Buf[1],J,J+N-1);
memset(Data+J,Buf[2],N);
++Result;
}
}
}
fclose(F);
return(Result);
}
#if defined(ZLIB) || defined(ANDROID)
#undef fopen
#undef fclose
#undef fread
#undef fseek
#endif
#ifndef IPS_H
#define IPS_H
/** ApplyIPS() ***********************************************/
/** Loads patches from an .IPS file and applies them to the **/
/** given data buffer. Returns number of patches applied. **/
/*************************************************************/
unsigned int ApplyIPS(const char *FileName,unsigned char *Data,unsigned int Size);
/** MeasureIPS() *********************************************/
/** Find total data size assumed by a given .IPS file. **/
/*************************************************************/
unsigned int MeasureIPS(const char *FileName);
#endif /* IPS_H */
This diff is collapsed.
/** EMULib Emulation Library *********************************/
/** **/
/** ImageMux.h **/
/** **/
/** This file wraps Image.c routines for multiple display **/
/** depths (BPP8,BPP16,BPP32). It is used automatically **/
/** when none of BPP* values are defined. **/
/** **/
/** Copyright (C) Marat Fayzullin 2008-2016 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef IMAGEMUX_H
#define IMAGEMUX_H
#include "EMULib.h"
#undef BPP8
#undef BPP16
#undef BPP24
#undef BPP32
#undef RMASK
#undef GMASK
#undef BMASK
#undef PIXEL
#define BPP8
#define pixel unsigned char
#define PIXEL(R,G,B) (pixel)(((7*(R)/255)<<5)|((7*(G)/255)<<2)|(3*(B)/255))
#define GetColor GetColor_8
#define IMGCopy IMGCopy_8
#define IMGDrawRect IMGDrawRect_8
#define IMGFillRect IMGFillRect_8
#define CropImage CropImage_8
#define ClearImage ClearImage_8
#define ScaleImage ScaleImage_8
#define RasterizeImage RasterizeImage_8
#define TelevizeImage TelevizeImage_8
#define LcdizeImage LcdizeImage_8
#define CMYizeImage CMYizeImage_8
#define RGBizeImage RGBizeImage_8
#define MonoImage MonoImage_8
#define SepiaImage SepiaImage_8
#define GreenImage GreenImage_8
#define AmberImage AmberImage_8
#define SoftenImage SoftenImage_8
#define SoftenSCALE2X SoftenSCALE2X_8
#define SoftenEPX SoftenEPX_8
#define SoftenEAGLE SoftenEAGLE_8
#define LoadPNG LoadPNG_8
#include "Image.c"
#undef pixel
#undef PIXEL
#undef GetColor
#undef IMGCopy
#undef IMGDrawRect
#undef IMGFillRect
#undef CropImage
#undef ClearImage
#undef ScaleImage
#undef RasterizeImage
#undef TelevizeImage
#undef LcdizeImage
#undef CMYizeImage
#undef RGBizeImage
#undef MonoImage
#undef SepiaImage
#undef GreenImage
#undef AmberImage
#undef SoftenImage
#undef SoftenSCALE2X
#undef SoftenEPX
#undef SoftenEAGLE
#undef LoadPNG
#undef BPP8
#define BPP16
#define pixel unsigned short
#if defined(UNIX) || defined(ANDROID) || defined(S60) || defined(UIQ) || defined(NXC2600) || defined(STMP3700)
/* Symbian and Unix use true 16BPP color */
#define PIXEL(R,G,B) (pixel)(((31*(R)/255)<<11)|((63*(G)/255)<<5)|(31*(B)/255))
#define RMASK 0xF800
#define GMASK 0x07E0
#define BMASK 0x001F
#else
/* Other platforms use 15BPP color */
#define PIXEL(R,G,B) (pixel)(((31*(R)/255)<<10)|((31*(G)/255)<<5)|(31*(B)/255))
#define RMASK 0x7C00
#define GMASK 0x03E0
#define BMASK 0x001F
#endif
#define GetColor GetColor_16
#define IMGCopy IMGCopy_16
#define IMGDrawRect IMGDrawRect_16
#define IMGFillRect IMGFillRect_16
#define CropImage CropImage_16
#define ClearImage ClearImage_16
#define ScaleImage ScaleImage_16
#define RasterizeImage RasterizeImage_16
#define TelevizeImage TelevizeImage_16
#define LcdizeImage LcdizeImage_16
#define CMYizeImage CMYizeImage_16
#define RGBizeImage RGBizeImage_16
#define MonoImage MonoImage_16
#define SepiaImage SepiaImage_16
#define GreenImage GreenImage_16
#define AmberImage AmberImage_16
#define SoftenImage SoftenImage_16
#define SoftenSCALE2X SoftenSCALE2X_16
#define SoftenEPX SoftenEPX_16
#define SoftenEAGLE SoftenEAGLE_16
#define LoadPNG LoadPNG_16
#define ARMScaleImage ARMScaleImage_16
#define Merge2 Merge2_16
#define Merge4 Merge4_16
#undef LIBARM_H
#include "Image.c"
#undef pixel
#undef PIXEL
#undef RMASK
#undef GMASK
#undef BMASK
#undef GetColor
#undef IMGCopy
#undef IMGDrawRect
#undef IMGFillRect
#undef CropImage
#undef ClearImage
#undef ScaleImage
#undef RasterizeImage
#undef TelevizeImage
#undef LcdizeImage
#undef CMYizeImage
#undef RGBizeImage
#undef MonoImage
#undef SepiaImage
#undef GreenImage
#undef AmberImage
#undef SoftenImage
#undef SoftenSCALE2X
#undef SoftenEPX
#undef SoftenEAGLE
#undef LoadPNG
#undef ARMScaleImage
#undef Merge2
#undef Merge4
#undef BPP16
#define BPP32
#define pixel unsigned int
#if defined(ANDROID)
#define PIXEL(R,G,B) (pixel)(((int)R<<16)|((int)G<<8)|B|0xFF000000)
#else
#define PIXEL(R,G,B) (pixel)(((int)R<<16)|((int)G<<8)|B)
#endif
#define RMASK 0xFF0000
#define GMASK 0x00FF00
#define BMASK 0x0000FF
#define GetColor GetColor_32
#define IMGCopy IMGCopy_32
#define IMGDrawRect IMGDrawRect_32
#define IMGFillRect IMGFillRect_32
#define CropImage CropImage_32
#define ClearImage ClearImage_32
#define ScaleImage ScaleImage_32
#define RasterizeImage RasterizeImage_32
#define TelevizeImage TelevizeImage_32
#define LcdizeImage LcdizeImage_32
#define CMYizeImage CMYizeImage_32
#define RGBizeImage RGBizeImage_32
#define MonoImage MonoImage_32
#define SepiaImage SepiaImage_32
#define GreenImage GreenImage_32
#define AmberImage AmberImage_32