-CC = arm-linux-gcc
-STRIP = arm-linux-strip
-TFLAGS = -mcpu=arm920t -Izlib -DGP2X=1 -DLSB_FIRST -DUNIX -DPSS_STYLE=1 -DZLIB -DFRAMESKIP -D_REENTRANT
+CROSS = arm-linux-
+CC = $(CROSS)gcc
+STRIP = $(CROSS)strip
+AS = $(CROSS)as
+TFLAGS = -Winline -mcpu=arm920t -Izlib -DGP2X=1 -DLSB_FIRST -DUNIX -DPSS_STYLE=1 -DZLIB -DFRAMESKIP -D_REENTRANT
+ASFLAGS = -mcpu=arm920t -mfloat-abi=soft
RM = rm -f
B = drivers/gp2x/
ifdef DEBUG
TFLAGS += -ggdb
+LDRIVER += -ggdb
else
-TFLAGS += -O3
+TFLAGS += -ftracer -fstrength-reduce -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math
+TFLAGS += -O3 # -pg
+LDRIVER += -O3 # -pg
endif
all: fceu
include zlib/Makefile
-OBJDRIVER = ${B}minimal.o ${B}gp2x.o ${B}main.o ${B}throttle.o ${B}unix-netplay.o ${B}gp2x-sound.o ${B}gp2x-video.o ${B}lnx-joystick.o drivers/common/cheat.o drivers/common/config.o drivers/common/args.o drivers/common/vidblit.o ${UNZIPOBJS} ppu.o
-LDRIVER = -L /mnt/sd/lib -L/mnt/sd/gp2x/usr/lib -lm -lz -static
+OBJDRIVER = ${B}minimal.o ${B}squidgehack.o ${B}asmutils.o ${B}gp2x.o ${B}main.o ${B}throttle.o \
+ ${B}unix-netplay.o ${B}gp2x-sound.o ${B}gp2x-video.o ${B}lnx-joystick.o \
+ drivers/common/cheat.o drivers/common/config.o drivers/common/args.o drivers/common/vidblit.o ${UNZIPOBJS} ppu.o
+LDRIVER += -L /mnt/sd/lib -L/mnt/sd/gp2x/usr/lib -lm -lz -static
include Makefile.base
-${B}lnx-joystick.o: ${B}lnx-joystick.c
${B}main.o: ${B}main.c ${B}main.h ${B}usage.h ${B}input.c
${B}gp2x.o: ${B}gp2x.c ${B}gp2x.h
-${B}gp2x-video.o: ${B}gp2x-video.c
-${B}gp2x-video.o: ${B}minimal.c
-${B}gp2x-sound.o: ${B}gp2x-sound.c
-${B}unix-netplay.o: ${B}unix-netplay.c
${B}throttle.o: ${B}throttle.c ${B}main.h ${B}throttle.h
ppu.o: ppu.c ppu.h
include Makefile.common
+#x6502.o: x6502.c x6502.h ops.h fce.h sound.h
+# $(CC) $(CFLAGS) -finline-limit=60000 -c $< -o $@
+
up: fceu
cp -v fceu /mnt/gp2x/mnt/sd/emus/Gpfce_v02/gpfce
#include "general.h"
#include "svga.h"
-/*
+/*
This file contains all code for coordinating the mapping in of the
address space external to the NES.
It's also (ab)used by the NSF code.
PRGmask4[chip]=(size>>12)-1;
PRGmask8[chip]=(size>>13)-1;
PRGmask16[chip]=(size>>14)-1;
- PRGmask32[chip]=(size>>15)-1;
+ PRGmask32[chip]=(size>>15)-1;
PRGram[chip]=ram?1:0;
}
goto grerr;
}
fclose(fp);
-
+
/* Workaround for the FCE Ultra CHR page size only being 1KB */
for(x=0;x<4;x++)
memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256);
else
{
modcon=V^0xFF;
- if(V==0x71)
+ if(V==0x71)
modcon=0;
}
break;
VPageR=VPage;
FlushGenieRW();
-
+
for(x=0;x<3;x++)
if((modcon>>(4+x))&1)
{
void SetupCartMirroring(int m, int hard, uint8 *extra);
DECLFR(CartBR);
+
extern uint8 *PRGptr[32];
extern uint8 *CHRptr[32];
{
*dest=0x81818181;
dest+=2;
- }
+ }
dest=(uint32 *)(XBuf+272*(12+4)+164+6 );
for(x=0;x<8;x++,dest+=2)
if(!((vsdip>>x)&1))
da+=(272>>2)*10;
-
+
for(y=4;y;y--,da+=272>>2)
*da=0x80808080;
-
+
}
}
{
uint8 *t;
howlong--;
- t=XBuf+(FSettings.LastSLine-29)*272+32;
+ t=XBuf+(FSettings.LastSLine-29)*320+32;
if(t>=XBuf)
- DrawTextTrans(t,272,(uint8 *)errmsg,132);
+ DrawTextTrans(t,320,(uint8 *)errmsg,132);
}
}
if(XBaf>=XBuf)
for(z=1;z<11;z++)
{
- if(SaveStateStatus[z%10])
+ if(SaveStateStatus[z%10])
{
for(y=0;y<13;y++)
for(x=0;x<21;x++)
- XBaf[y*272+x+z*21+z]=sstat[y*21+x+(z-1)*21*12];
+ XBaf[y*272+x+z*21+z]=sstat[y*21+x+(z-1)*21*12];
} else {
for(y=0;y<13;y++)
for(x=0;x<21;x++)
for(x=0;x<21;x++)
XBaf[3264+x+z*21+z*1]=132;
}
- }
+ }
StateShow--;
}
uint8 y;
uint8 z;
- for(x=0;x<length;x++)
- for(y=0;y<8;y++)
- for(z=0;z<8;z++)
+ for(x=0;x<length;x++)
+ for(y=0;y<8;y++)
+ for(z=0;z<8;z++)
if((fontdata2[(textmsg[x]<<3)+y]>>z)&1) dest[y*width+(x<<3)+z]=fgcolor;
}
/* Prototypes for platform interface functions follow: */
-void FCEUD_Update(uint8 *XBuf, int16 *Buffer, int Count);
+void FCEUD_Update(uint8 *buf, int16 *Buffer, int Count);
/* Video interface */
void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b);
--- /dev/null
+void flushcache(unsigned int beginning_addr, unsigned int end_addr, unsigned int flags);\r
+\r
--- /dev/null
+@ vim:filetype=armasm
+
+@ test
+.global flushcache @ beginning_addr, end_addr, flags
+
+flushcache:
+ swi #0x9f0002
+ mov pc, lr
+
void GetBaseDirectory(char *BaseDirectory);
int InitSound(void);
-void WriteSound(int16 *Buffer, int Count, int NoWaiting);
+void WriteSound(int16 *Buffer, int Count);
void KillSound(void);
void SilenceSound(int s); /* DOS and SDL */
int InitVideo(void);
void KillVideo(void);
-void BlitScreen(uint8 *XBuf);
+void BlitScreen(uint8 *buf);
void LockConsole(void);
void UnlockConsole(void);
void ToggleFS(); /* SDL */
#include <string.h>
#include <sys/time.h>
+#include "../../video.h"
+
#include "gp2x.h"
#include "minimal.h"
static char fps_str[32];
static int framesEmulated, framesRendered;
-int stretch_offset=32;
+int scaled_display=0;
int paletterefresh;
#define FPS_COLOR 61
memset (gp2x_screen8, 0x80, 320*240);
gp2x_video_flip();
}
+ XBuf = gp2x_screen8;
}
srendline=0;
erendline=239;
+ XBuf = gp2x_screen8; // TODO: use mmuhacked upper mem
return 1;
}
prevsec = tv_now.tv_sec;
}
- if (stretch_offset > 0)
+ if (!scaled_display)
{
if (needfpsflip)
{
int y, *destt = (int *) screen;
- for (y = 240; y; y--)
+ for (y = 20/*240*/; y; y--)
{
*destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F;
*destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F;
- destt += 64;
+ destt += 64+8;
- *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F;
- *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F;
+ //*destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F;
+ //*destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F; *destt++ = 0x3F3F3F3F;
}
if (showfps)
{
{
if (showfps)
{
- gp2x_text(screen, 0, 0, fps_str, FPS_COLOR, 0);
+ gp2x_text(screen+32, 0, 0, fps_str, FPS_COLOR, 0);
}
}
}
-void BlitScreen(uint8 * XBuf)
+void BlitScreen(uint8 *buf)
{
- int x, y, yinc;
-
framesEmulated++;
- if (!XBuf) return;
+ if (!buf) return;
framesRendered++;
-#if 1 // 48->54
- y=240;
- yinc=272*(y-1);
- while (y--)
- {
- int* dest=(int *) (gp2x_screen8+((y << 8) + (y << 6))+stretch_offset);
-
- int* src=(int *) (XBuf+yinc);
- x=64;
- while (x--)
- {
- dest[x]=src[x];
- }
- yinc-=272;
- }
-
- if (paletterefresh)
- {
- gp2x_video_setpalette();
- paletterefresh = 0;
- }
-#endif
printFps(gp2x_screen8);
gp2x_video_flip();
+ XBuf = gp2x_screen8;
}
//#define SOUND_RATE 44100
#define SOUND_RATE 22050
+#define GP2X_PORT_VERSION "0.3"
DSETTINGS Settings;
CFGSTRUCT DriverConfig[]={
#include "unix-basedir.h"
extern int showfps;
extern int swapbuttons;
+char **g_argv;
int main(int argc, char *argv[])
{
+ g_argv = argv;
- puts("Starting GPFCE - Port version 0.2 05-29-2006");
+ puts("Starting GPFCE - Port version " GP2X_PORT_VERSION " (" __DATE__ ")");
puts("Based on FCE Ultra "VERSION_STRING"...");
- puts("Ported by Zheng Zhu\n");
+ puts("Ported by Zheng Zhu");
+ puts("Additional optimization/misc work by notaz\n");
// stereo
//gp2x_init (1000, 8, SOUND_RATE, 16, 1, 60);
// mono 22khz
gp2x_init (1000, 8, SOUND_RATE, 16, 0, 60);
+ // unscale the screen, in case this is bad.
+ SetVideoScaling(320, 320, 240);
+
SetDefaults();
int ret=CLImain(argc,argv);
#include "minimal.h"
extern int swapbuttons;
-extern int stretch_offset;
+extern int scaled_display;
extern int FSkip_setting;
extern void SetVideoScaling(int pixels,int width,int height);
-INLINE long UpdateGamepadGP2X(void);
+static INLINE long UpdateGamepadGP2X(void);
* GP2x joystick reader
*
*/
-INLINE long UpdateGamepadGP2X(void)
+static INLINE long UpdateGamepadGP2X(void)
{
uint32 JS=0;
// still pressed down from stretching from last one
goto no_pad;
}
- if (stretch_offset == 32)
- {
- stretch_offset=0;
- }
- else
- {
- stretch_offset=32;
- }
+ scaled_display = !scaled_display;
- if (stretch_offset == 32)
+ if (scaled_display)
{
- SetVideoScaling(320, 320, 240);
- CleanSurface();
+ SetVideoScaling(320, 256, 240);
}
else
{
- SetVideoScaling(320, 256, 240);
+ SetVideoScaling(320, 320, 240);
}
goto no_pad;
FCEUGI *tmp;
int ret;
+ if(argc<=1)
+ {
+ ShowUsage(argv[0]);
+ return 1;
+ }
+
+ if(!DriverInitialize())
+ {
+ return 1;
+ }
+
if(!(ret=FCEUI_Initialize()))
return(1);
GetBaseDirectory(BaseDirectory);
FCEUI_SetBaseDirectory(BaseDirectory);
CreateDirs();
- if(argc<=1)
- {
- ShowUsage(argv[0]);
- return 1;
- }
LoadConfig();
DoArgs(argc-2,&argv[1]);
if(cpalette)
}
ParseGI(tmp);
//RefreshThrottleFPS();
- if(!DriverInitialize())
- {
- ret=0;
- goto dk;
- }
InitOtherInput();
FCEUI_Emulate();
inited=0;
}
-void FCEUD_Update(uint8 *XBuf, int16 *Buffer, int Count)
+void FCEUD_Update(uint8 *xbuf, int16 *Buffer, int Count)
{
if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
SpeedThrottle();
- BlitScreen(XBuf);
- if(Count)
- WriteSound(Buffer,Count,NoWaiting);
+ BlitScreen(xbuf);
+ if(Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
+ WriteSound(Buffer,Count);
FCEUD_UpdateInput();
}
*/
#include "minimal.h"
+#include "squidgehack.h"
+#include "asmutils.h"
unsigned char *gp2x_screen8 ,*gp2x_upperRAM;
unsigned long gp2x_dev[8]={0,0,0,0,0,0,0,0}, gp2x_physvram[8], *gp2x_memregl, gp2x_volume, gp2x_ticks_per_second;
-volatile unsigned long gp2x_sound_pausei=1, gp2x_ticks=0, gp2x_sound=0, *gp2x_dualcore_ram;
+volatile unsigned long gp2x_sound_pausei=1, gp2x_ticks=0, gp2x_sound=0, *gp2x_dualcore_ram=0;
unsigned short *gp2x_memregs, *gp2x_screen15, *gp2x_logvram15[4], gp2x_sound_buffer[4+((44100/25)*2)*8]; //25 Hz gives our biggest supported sampling buffer
volatile unsigned short gp2x_palette[512];
extern void gp2x_sound_frame(void *blah, void *buff, int samples);
+// hack
+static int scaling_enabled = 0;
void gp2x_video_flip(void)
{
unsigned long address=gp2x_physvram[gp2x_physvram[7]];
+ if (scaling_enabled) address += 32;
+
+ // since we are using the mmu hack, we must flush the cache first
+ // (the params are most likely wrong, but they seem to work somehow)
+ flushcache(address, address + 320*240, 0);
if(++gp2x_physvram[7]==4) gp2x_physvram[7]=0;
gp2x_screen15=gp2x_logvram15[gp2x_physvram[7]];
}
#endif
+#if 0
static void gp2x_initqueue(gp2x_queue *q, unsigned long queue_items, unsigned long *position920t, unsigned long *position940t)
{
q->head = q->tail = q->items = 0;
q->items--;
return q->place920t[q->tail = (q->tail < q->max_items ? q->tail+1 : 0)];
} */
-
-
+#endif
void gp2x_dualcore_pause(int yes) { if(yes) gp2x_memregs[0x0904>>1] &= 0xFFFE; else gp2x_memregs[0x0904>>1] |= 1; }
static void gp2x_940t_reset(int yes) { gp2x_memregs[0x3B48>>1] = ((yes&1) << 7) | (0x03); }
}
}
+#if 0
void gp2x_dualcore_sync(void)
{
gp2x_queue *q=(gp2x_queue *)gp2x_1stcore_data_ptr(GP2X_QUEUE_ARRAY_PTR);
free(data);
fclose(in);
}
+#endif
void gp2x_init(int ticks_per_second, int bpp, int rate, int bits, int stereo, int Hz)
{
int frag=0;
int channels=1;
int stereoLocal=0;
+ int ret;
gp2x_ticks_per_second=7372800/ticks_per_second;
if(!gp2x_dev[1]) gp2x_dev[1] = open("/dev/fb1", O_RDWR);
if(!gp2x_dev[2]) gp2x_dev[2] = open("/dev/mem", O_RDWR);
+ ioctl(gp2x_dev[gp2x_physvram[7]=0], FBIOGET_FSCREENINFO, &fixed_info);
+ gp2x_physvram[2]=gp2x_physvram[0]=fixed_info.smem_start;
+ gp2x_screen15=gp2x_logvram15[2]=gp2x_logvram15[0]=
+ (unsigned short *)mmap(0, 0x20000*2, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], gp2x_physvram[0]);
+ gp2x_screen8=(unsigned char *)gp2x_screen15;
+ printf("/dev/fb0 is @ %08lx / %p\n", gp2x_physvram[0], gp2x_screen15);
+
+ ioctl(gp2x_dev[1], FBIOGET_FSCREENINFO, &fixed_info);
+ gp2x_physvram[3]=gp2x_physvram[1]=fixed_info.smem_start;
+ gp2x_logvram15[3]=gp2x_logvram15[1]=
+ (unsigned short *)mmap(0, 0x20000*2, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], gp2x_physvram[1]);
+ printf("/dev/fb1 is @ %08lx / %p\n", gp2x_physvram[1], gp2x_logvram15[1]);
+
+ // apply the MMU hack
+ ret = mmuhack();
+ printf("squidge hack code finished and returned %s\n", ret ? "ok" : "fail");
+
// don't run sound right now
if ( gp2x_do_sound)
{
if(!gp2x_dev[4]) gp2x_dev[4] = open("/dev/mixer", O_RDWR);
}
- gp2x_dualcore_ram=(unsigned long *)mmap(0, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0x03000000);
+// gp2x_dualcore_ram=(unsigned long *)mmap(0, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0x03000000);
/*gp2x_dualcore_ram=(unsigned long *)mmap(0, 0x2000000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0x02000000);*/
gp2x_memregl=(unsigned long *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0xc0000000);
gp2x_memregs=(unsigned short *)gp2x_memregl;
gp2x_memregs[0x0F16>>1] = 0x830a; usleep(100000);
gp2x_memregs[0x0F58>>1] = 0x100c; usleep(100000); }
- ioctl(gp2x_dev[gp2x_physvram[7]=0], FBIOGET_FSCREENINFO, &fixed_info);
- gp2x_screen15=gp2x_logvram15[2]=gp2x_logvram15[0]=(unsigned short *)mmap(0, 320*240*2, PROT_WRITE, MAP_SHARED, gp2x_dev[0], 0);
- gp2x_screen8=(unsigned char *)gp2x_screen15;
- gp2x_physvram[2]=gp2x_physvram[0]=fixed_info.smem_start;
-
- ioctl(gp2x_dev[1], FBIOGET_FSCREENINFO, &fixed_info);
- gp2x_logvram15[3]=gp2x_logvram15[1]=(unsigned short *)mmap(0, 320*240*2, PROT_WRITE, MAP_SHARED, gp2x_dev[1], 0);
- gp2x_physvram[3]=gp2x_physvram[1]=fixed_info.smem_start;
-
gp2x_memregs[0x28DA>>1]=(((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/
gp2x_memregs[0x290C>>1]=320*((bpp+1)/8); /*line width in bytes*/
memset(gp2x_screen15, 0, 320*240*2); gp2x_video_flip();
memset(gp2x_screen15, 0, 320*240*2); gp2x_video_flip();
- if(bpp==8) gp2x_physvram[2]+=320*240, gp2x_physvram[3]+=320*240,
- gp2x_logvram15[2]+=320*240/2, gp2x_logvram15[3]+=320*240/2;
+ //if(bpp==8) gp2x_physvram[2]+=320*240, gp2x_physvram[3]+=320*240,
+ // gp2x_logvram15[2]+=320*240/2, gp2x_logvram15[3]+=320*240/2;
+ if(bpp==8) gp2x_physvram[2]+=0x20000, gp2x_physvram[3]+=0x20000,
+ gp2x_logvram15[2]+=0x20000/2, gp2x_logvram15[3]+=0x20000/2;
if ( gp2x_do_sound)
{
-
ioctl(gp2x_dev[3], SNDCTL_DSP_SPEED, &rate);
ioctl(gp2x_dev[3], SNDCTL_DSP_SETFMT, &bits);
first=0;
}
}
-
}
while((gp2x_sound++)<1000000); //wait arm920t threads to finish
gp2x_dualcore_registers(0);
+ mmuunhack();
gp2x_memregs[0x28DA>>1]=0x4AB; //set video mode
gp2x_memregs[0x290C>>1]=640;
int bpp=(gp2x_memregs[0x28DA>>1]>>9)&0x3; /* bytes per pixel */
+ scaling_enabled = (width == 320) ? 0 : 1;
+
if(gp2x_memregs[0x2800>>1]&0x100) /* TV-Out ON? */
{
xscale=489.0; /* X-Scale with TV-Out (PAL or NTSC) */
--- /dev/null
+#include <linux/config.h>\r
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/init.h>\r
+#include <linux/miscdevice.h>\r
+#include <asm/memory.h>\r
+\r
+#define MMUHACK_MINOR 225\r
+#define DEVICE_NAME "mmuhack"\r
+\r
+#if __GNUC__ == 3\r
+#include <linux/version.h>\r
+static const char __module_kernel_version_gcc3[] __attribute__((__used__)) __attribute__((section(".modinfo"))) =\r
+"kernel_version=" UTS_RELEASE;\r
+#endif\r
+\r
+static ssize_t mmuhack_open(struct inode *inode, struct file *filp)\r
+{\r
+ unsigned int *pgtable;\r
+ unsigned int *cpt;\r
+ int i, j;\r
+ int ttb;\r
+ int ret = -EFAULT;\r
+\r
+ // get the pointer to the translation table base...\r
+ asm volatile(\r
+ "stmdb sp!, {r0}\n\t"\r
+ "mrc p15, 0, r0, c2, c0, 0\n\t"\r
+ "mov %0, r0\n\t"\r
+ "ldmia sp!, {r0}\n\t": "=r"(ttb)\r
+ );\r
+\r
+ pgtable = __va(ttb);\r
+\r
+ for (i = 0; i < 4096; i ++) if ( (pgtable[i] & 3) == 1 ) {\r
+ cpt = __va(pgtable[i] & 0xfffffc00);\r
+\r
+ for (j = 0; j < 256; j ++) {/*\r
+ if ( (cpt[j] & 0xfe00000f) == 0x02000002 ) {\r
+ // set C and B bits in upper 32MB memory area...\r
+ printk("Set C&B bits %08x\n",cpt[j]);\r
+ cpt[j] |= 0xFFC;\r
+ ret = 0;\r
+ }\r
+ */\r
+ if (((cpt[j] & 0xff000000) == 0x02000000) && ((cpt[j] & 12)==0) )\r
+ {\r
+ //printk("Set C&B bits %08x\n",cpt[j]);\r
+ cpt[j] |= 0xFFC;\r
+ }\r
+ //if ((a>=0x31 && a<=0x36) && ((cpt[i] & 12)==0))\r
+ if (((cpt[j] & 0xff000000) == 0x03000000) && ((cpt[j] & 12)==0))\r
+ {\r
+ //printk("Set C&B bits %08x\n",cpt[j]);\r
+ //printf("SDL c and b bits not set, overwriting\n");\r
+ cpt[j] |= 0xFFC;\r
+ }\r
+ }\r
+ }\r
+\r
+ // drain the write buffer and flush the tlb caches...\r
+ asm volatile(\r
+ "stmdb sp!, {r0}\n\t"\r
+ "mov r0, #0\n\t"\r
+ "mcr 15, 0, r0, cr7, cr10, 4\n\t"\r
+ "mcr 15, 0, r0, cr8, cr7, 0\n\t"\r
+ "ldmia sp!, {r0}\n\t"\r
+ );\r
+\r
+ if (ret == 0)\r
+ printk("MMU hack applied.\n");\r
+\r
+ return 0;\r
+}\r
+\r
+static struct file_operations mmuhack_fops = {\r
+ owner: THIS_MODULE,\r
+ open: mmuhack_open,\r
+};\r
+\r
+\r
+static struct miscdevice mmuhack = {\r
+ MMUHACK_MINOR, DEVICE_NAME, &mmuhack_fops\r
+};\r
+\r
+static int __init mmuhack_init(void)\r
+{\r
+ misc_register(&mmuhack);\r
+/*\r
+ printk("MMSP2 MMU Hack module.\n");\r
+*/\r
+ return 0;\r
+}\r
+\r
+static void __exit mmuhack_exit(void)\r
+{\r
+ misc_deregister(&mmuhack);\r
+/*\r
+ printk(KERN_ALERT "MMU Hack module removed.\n");\r
+*/\r
+}\r
+\r
+module_init(mmuhack_init);\r
+module_exit(mmuhack_exit);\r
--- /dev/null
+Squidge's MMU Hack modularized.
+Original code by Squidge.
+Module by Annonymous?
+Slightly modified by me to suit my need.
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+extern char **g_argv;
+
+/* Call this MMU Hack kernel module after doing mmap, and before doing memset*/
+int mmuhack(void)
+{
+ char kocmd[1024];
+ int i, mmufd = open("/dev/mmuhack", O_RDWR);
+
+ if(mmufd < 0) {
+ strcpy(kocmd, "/sbin/insmod ");
+ strncpy(kocmd+13, g_argv[0], 1023-13);
+ kocmd[1023] = 0;
+ for (i = strlen(kocmd); i > 0; i--)
+ if (kocmd[i] == '/') { kocmd[i] = 0; break; }
+ strcat(kocmd, "/mmuhack.o");
+
+ printf("Installing NK's kernel module for Squidge MMU Hack (%s)...\n", kocmd);
+ system(kocmd);
+ mmufd = open("/dev/mmuhack", O_RDWR);
+ }
+ if(mmufd < 0) return 0;
+
+ close(mmufd);
+ return 1;
+}
+
+
+/* Unload MMU Hack kernel module after closing all memory devices*/
+int mmuunhack(void)
+{
+ int ret;
+ printf("Removing NK's kernel module for Squidge MMU Hack... "); fflush(stdout);
+ ret = system("/sbin/rmmod mmuhack");
+ printf("done (%i)\n", ret);
+
+ return ret;
+}
--- /dev/null
+#ifndef __MMUHACK__
+#define __MMUHACK__
+
+extern int mmuhack(void);
+extern int mmuunhack(void);
+
+#endif /* __MMUHACK__ */
FSkip = 1;
}
}
- else if (usec_done > usec_aim)
+ else if (usec_done > usec_aim + 1024*4)
{
/* auto frameskip */
if (usec_done - usec_aim > 150000)
- usec_done = usec_aim = 0; // too much behind, try to recover..
+ usec_done = usec_aim = 1; // too much behind, try to recover..
FSkip = 1;
tv_prev = tv_now;
return;
void RefreshThrottleFPS(void);
-INLINE void SpeedThrottle(void);
+void SpeedThrottle(void);
{
uint32 tem;
int x;
- uint8 *target=XBuf+(scanline<<8)+(scanline<<4)+8;
+ uint8 *target=XBuf+scanline*320+32;
if(ScreenON || SpriteON)
{
if(PPU[1]&0x01)
{
for(x=63;x>=0;x--)
- *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])&0xF0F0F0F0;
+ ((uint32 *)target)[x]=((uint32*)target)[x]&0xF0F0F0F0;
}
if((PPU[1]>>5)==0x7)
for(x=63;x>=0;x--)
- *(uint32 *)&target[x<<2]=((*(uint32*)&target[x<<2])&0x3f3f3f3f)|0x40404040;
+ ((uint32 *)target)[x]=(((uint32*)target)[x]&0x3f3f3f3f)|0x40404040;
else if(PPU[1]&0xE0)
for(x=63;x>=0;x--)
- *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])|0xC0C0C0C0;
+ ((uint32 *)target)[x]=((uint32*)target)[x]|0xC0C0C0C0;
else
for(x=63;x>=0;x--)
- *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])&0x3f3f3f3f;
-
+ ((uint32 *)target)[x]=((uint32*)target)[x]&0x3f3f3f3f;
+ FCEU_dwmemset(target- 8,0x3f3f3f3f,8);
+ FCEU_dwmemset(target+256,0x3f3f3f3f,8);
#ifdef FRAMESKIP
}
#endif
}
}
-static INLINE void Fixit2(void)
+//static INLINE
+void Fixit2(void)
{
if(ScreenON || SpriteON)
{
}
}
-static INLINE void Fixit1(void)
+//static INLINE
+void Fixit1(void)
{
if(ScreenON || SpriteON)
{
}
}
+//#define NEW_TRY
+
/* This is called at the beginning of all h-blanks on visible lines. */
+#ifndef NEW_TRY
static void DoHBlank(void)
{
if(ScreenON || SpriteON)
//PPU_hook(0,-1);
//fprintf(stderr,"%3d: $%04x\n",scanline,RefreshAddr);
}
-
+#endif
// ============================//
static INLINE void Thingo(void)
{
Loop6502();
+#ifndef NEW_TRY
if(tosprite>=256)
{
tosprite=256;
}
DoHBlank();
+#else
+ X6502_Run_scanline();
+#endif
}
#undef harko
{
for(;;)
{
+ //extern int asdc;
+ //printf("asdc: %i\n", asdc);
+ //asdc=0;
ApplyPeriodicCheats();
X6502_Run(256+85);
if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
}
if(FCEUGameInfo.type==GIT_NSF)
+ {
X6502_Run((256+85)*240);
+ }
else
{
int x,max,maxref;
uint32 m;
if(!XBuf) /* Some driver code may allocate XBuf externally. */
- if(!(XBuf = (uint8*) (FCEU_malloc((256+16) * 240 + 8))))
+ if(!(XBuf = (uint8*) (FCEU_malloc(320 * 240))))
return 0;
-
+/*
if(sizeof(uint8*)==4)
{
m=(uint32) XBuf;
m+=8;m&=0xFFFFFFF8;
XBuf=(uint8 *)m;
- }
-
- memset(XBuf,128,272*240);
+ }
+*/
+ memset(XBuf,128,320*240);
return 1;
}
fputc(b,pp);
}
fclose(pp);
-
+
return u+1;
}
{
char pdata[256*3];
-
+
//void FCEUD_GetPalette(uint8 i,uint8 *r, unsigned char *g, unsigned char *b);
for(x=0;x<256;x++)
FCEUD_GetPalette(x,(uint8*)(pdata+x*3),(unsigned char*)(pdata+x*3+1),(unsigned char*)(pdata+x*3+2));
*dest=0; // No filter.
dest++;
for(x=256;x;x--,tmp++,dest++)
- *dest=*tmp;
+ *dest=*tmp;
tmp+=16;
}
+#include "types.h"
int InitVirtualVideo(void);
int SaveSnapshot(void);
extern uint8 *XBuf;
#include "x6502.h"
#include "fce.h"
#include "sound.h"
+#include "cart.h"
X6502 X;
uint32 timestamp;
static INLINE uint8 RdMem(unsigned int A)
{
+ // notaz: try to avoid lookup of every address at least for ROM and RAM areas
+ // I've verified that if ARead[0xfff0] points to CartBR, it is always normal ROM read.
+#if 0
+ if ((A&0x8000)/* && ARead[0xfff0] == CartBR*/) {
+ return (_DB=Page[A>>11][A]);
+ }
+#endif
+#if 0 // enabling this causes 4fps slowdown. Why?
+ if ((A&0xe000) == 0) { // RAM area (always 0-0x1fff)
+ return (_DB=RAM[A&0x7FF]);
+ }
+#endif
return((_DB=ARead[A](A)));
}
static INLINE void WrMem(unsigned int A, uint8 V)
{
+ if ((A&0xe000) == 0) { // RAM area (always 0-0x1fff)
+ RAM[A&0x7FF] = V;
+ return;
+ }
BWrite[A](A,V);
}
static INLINE void ADDCYC(int x)
{
- _tcount+=x;
+ //_tcount+=x;
_count-=x*48;
timestamp+=x;
}
return(RdRAM(0x100+_S));
}
+#if 0
static uint8 ZNTable[256] = {
Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG
};
+#endif
/* Some of these operations will only make sense if you know what the flag
constants are. */
-#define X_ZN(zort) _P&=~(Z_FLAG|N_FLAG);_P|=ZNTable[zort]
-#define X_ZNT(zort) _P|=ZNTable[zort]
+//#define X_ZN(zort) _P&=~(Z_FLAG|N_FLAG);_P|=ZNTable[zort]
+//#define X_ZNT(zort) _P|=ZNTable[zort]
+#define X_ZN(zort) _P&=~(Z_FLAG|N_FLAG);if(!zort) _P|=Z_FLAG;else _P|=zort&N_FLAG
+#define X_ZNT(zort) if(!zort) _P|=Z_FLAG;else _P|=zort&N_FLAG
/* Care must be taken if you want to turn this into a macro. Use { and }. */
#define JR(); \
/* All of the freaky arithmetic operations. */
#define AND _A&=x;X_ZN(_A)
-#define BIT _P&=~(Z_FLAG|V_FLAG|N_FLAG);_P|=ZNTable[x&_A]&Z_FLAG;_P|=x&(V_FLAG|N_FLAG)
+//#define BIT _P&=~(Z_FLAG|V_FLAG|N_FLAG);_P|=ZNTable[x&_A]&Z_FLAG;_P|=x&(V_FLAG|N_FLAG)
+#define BIT _P&=~(Z_FLAG|V_FLAG|N_FLAG);if(!(x&_A)) _P|=Z_FLAG;_P|=x&(V_FLAG|N_FLAG)
#define EOR _A^=x;X_ZN(_A)
#define ORA _A|=x;X_ZN(_A)
_P|=l; \
X_ZNT(x); \
}
-
+
/* Icky icky thing for some undocumented instructions. Can easily be
broken if names of local variables are changed.
*/
#define ST_IY(r) {unsigned int A; GetIYWR(A); WrMem(A,r); break; }
static uint8 CycTable[256] =
-{
+{
/*0x00*/ 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,
/*0x10*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
/*0x20*/ 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,
void X6502_Power(void)
{
- memset((void *)&X,0,sizeof(X));
+ memset((void *)&X,0,sizeof(X));
timestamp=0;
X6502_Reset();
}
-void X6502_Run(int32 cycles)
+
+//int asdc = 0;
+
+void X6502_Run_(void/*int32 cycles*/)
{
+/*
if(PAL)
cycles*=15; // 15*4=60
else
cycles*=16; // 16*4=64
_count+=cycles;
+*/
+// if (_count <= 0) asdc++;
while(_count>0)
{
}
_PI=_P;
b1=RdMem(_PC);
- ADDCYC(CycTable[b1]);
- temp=_tcount;
- _tcount=0;
+ temp=CycTable[b1];
+ ADDCYC(temp);
+ //temp=_tcount;
+ //_tcount=0;
if(MapIRQHook) MapIRQHook(temp);
temp*=48;
fhcnt+=fhinc;
}
-
+
if(PCMIRQCount>0)
{
PCMIRQCount-=temp;
switch(b1)
{
#include "ops.h"
- }
+ }
}
}
+
+
void X6502_Reset(void);
void X6502_Power(void);
-void X6502_Run(int32 cycles);
+#define X6502_Run(c) \
+{ \
+ int32 cycles = (c) << 4; /* *16 */ \
+ if (PAL) cycles -= (c); /* *15 */ \
+ X.count+=cycles; \
+ if (X.count > 0) X6502_Run_(); \
+}
+void X6502_Run_(void);
+
void TriggerIRQ(void);
void TriggerNMI(void);
void FASTAPASS(1) X6502_AddCycles(int x);
void FASTAPASS(1) X6502_IRQBegin(int w);
void FASTAPASS(1) X6502_IRQEnd(int w);
+